From 39be4185c40bca200eacc9fb1b8b8bc49f41106e Mon Sep 17 00:00:00 2001
From: stamoor <stamoor@f3b2605a-c512-4ea7-a41b-209d697bcdaa>
Date: Tue, 6 Sep 2016 23:06:32 +0000
Subject: [PATCH] Updating Kokkos lib

git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@15556 f3b2605a-c512-4ea7-a41b-209d697bcdaa
---
 lib/kokkos/.gitignore                         |     8 +
 lib/kokkos/CMakeLists.txt                     |   184 +
 lib/kokkos/Copyright.txt                      |    40 +
 lib/kokkos/HOW_TO_SNAPSHOT                    |    73 +
 lib/kokkos/LICENSE                            |    40 +
 lib/kokkos/Makefile.kokkos                    |   480 +
 lib/kokkos/Makefile.targets                   |    72 +
 lib/kokkos/README                             |   152 +
 lib/kokkos/algorithms/CMakeLists.txt          |    10 +
 .../algorithms/cmake/Dependencies.cmake       |     5 +
 .../cmake/KokkosAlgorithms_config.h.in        |     4 +
 lib/kokkos/algorithms/src/CMakeLists.txt      |    21 +
 .../algorithms/src/KokkosAlgorithms_dummy.cpp |     0
 lib/kokkos/algorithms/src/Kokkos_Random.hpp   |  1751 ++
 lib/kokkos/algorithms/src/Kokkos_Sort.hpp     |   496 +
 .../algorithms/unit_tests/CMakeLists.txt      |    38 +
 lib/kokkos/algorithms/unit_tests/Makefile     |    92 +
 lib/kokkos/algorithms/unit_tests/TestCuda.cpp |   110 +
 .../algorithms/unit_tests/TestOpenMP.cpp      |   102 +
 .../algorithms/unit_tests/TestRandom.hpp      |   481 +
 .../algorithms/unit_tests/TestSerial.cpp      |    99 +
 lib/kokkos/algorithms/unit_tests/TestSort.hpp |   206 +
 .../algorithms/unit_tests/TestThreads.cpp     |   113 +
 .../algorithms/unit_tests/UnitTestMain.cpp    |    50 +
 lib/kokkos/cmake/Dependencies.cmake           |    10 +
 lib/kokkos/cmake/deps/CUDA.cmake              |    79 +
 lib/kokkos/cmake/deps/CUSPARSE.cmake          |    64 +
 lib/kokkos/cmake/deps/HWLOC.cmake             |    70 +
 lib/kokkos/cmake/deps/Pthread.cmake           |    83 +
 lib/kokkos/cmake/deps/QTHREAD.cmake           |    70 +
 lib/kokkos/cmake/tpls/FindTPLCUSPARSE.cmake   |    75 +
 lib/kokkos/cmake/tpls/FindTPLHWLOC.cmake      |    71 +
 lib/kokkos/cmake/tpls/FindTPLPthread.cmake    |    82 +
 lib/kokkos/cmake/tpls/FindTPLQTHREAD.cmake    |    70 +
 lib/kokkos/cmake/tribits.cmake                |   485 +
 lib/kokkos/config/configure_compton_cpu.sh    |   190 +
 lib/kokkos/config/configure_compton_mic.sh    |   186 +
 lib/kokkos/config/configure_kokkos.sh         |   293 +
 lib/kokkos/config/configure_kokkos_bgq.sh     |    88 +
 lib/kokkos/config/configure_kokkos_dev.sh     |   216 +
 lib/kokkos/config/configure_kokkos_nvidia.sh  |   204 +
 lib/kokkos/config/configure_shannon.sh        |   190 +
 ...nfigure_tpetra_kokkos_cuda_nvcc_wrapper.sh |   140 +
 .../kokkos-trilinos-integration-procedure.txt |   153 +
 .../config/kokkos_dev/config-core-all.sh      |   113 +
 .../kokkos_dev/config-core-cuda-omp-hwloc.sh  |   104 +
 .../config/kokkos_dev/config-core-cuda.sh     |    88 +
 .../kokkos_dev/config-core-cxx11-omp.sh       |    84 +
 .../config/kokkos_dev/config-core-dbg-none.sh |    78 +
 .../kokkos_dev/config-core-intel-cuda-omp.sh  |    89 +
 .../kokkos_dev/config-core-intel-omp.sh       |    84 +
 .../config/kokkos_dev/config-core-omp.sh      |    77 +
 .../kokkos_dev/config-core-threads-hwloc.sh   |    87 +
 lib/kokkos/config/master_history.txt          |     3 +
 lib/kokkos/config/nvcc_wrapper                |   280 +
 lib/kokkos/config/snapshot.py                 |   279 +
 lib/kokkos/config/test_all_sandia             |   539 +
 lib/kokkos/config/testing_scripts/README      |     5 +
 .../testing_scripts/jenkins_test_driver       |    83 +
 .../config/testing_scripts/obj_size_opt_check |   287 +
 lib/kokkos/containers/CMakeLists.txt          |    10 +
 .../containers/cmake/Dependencies.cmake       |     5 +
 .../cmake/KokkosContainers_config.h.in        |     4 +
 .../performance_tests/CMakeLists.txt          |    37 +
 .../containers/performance_tests/Makefile     |    81 +
 .../containers/performance_tests/TestCuda.cpp |   109 +
 .../performance_tests/TestDynRankView.hpp     |   265 +
 .../performance_tests/TestGlobal2LocalIds.hpp |   231 +
 .../containers/performance_tests/TestMain.cpp |    50 +
 .../performance_tests/TestOpenMP.cpp          |   140 +
 .../performance_tests/TestThreads.cpp         |   135 +
 .../TestUnorderedMapPerformance.hpp           |   262 +
 lib/kokkos/containers/src/CMakeLists.txt      |    31 +
 lib/kokkos/containers/src/Kokkos_Bitset.hpp   |   437 +
 lib/kokkos/containers/src/Kokkos_DualView.hpp |   982 +
 .../containers/src/Kokkos_DynRankView.hpp     |  1834 ++
 .../containers/src/Kokkos_DynamicView.hpp     |   494 +
 .../containers/src/Kokkos_Functional.hpp      |   173 +
 .../containers/src/Kokkos_SegmentedView.hpp   |   531 +
 .../containers/src/Kokkos_StaticCrsGraph.hpp  |   226 +
 .../containers/src/Kokkos_UnorderedMap.hpp    |   848 +
 lib/kokkos/containers/src/Kokkos_Vector.hpp   |   283 +
 .../src/impl/Kokkos_Bitset_impl.hpp           |   109 +
 .../src/impl/Kokkos_Functional_impl.hpp       |   195 +
 .../impl/Kokkos_StaticCrsGraph_factory.hpp    |   208 +
 .../src/impl/Kokkos_UnorderedMap_impl.cpp     |   101 +
 .../src/impl/Kokkos_UnorderedMap_impl.hpp     |   297 +
 .../containers/unit_tests/CMakeLists.txt      |    40 +
 lib/kokkos/containers/unit_tests/Makefile     |    92 +
 .../containers/unit_tests/TestBitset.hpp      |   285 +
 .../containers/unit_tests/TestComplex.hpp     |   263 +
 lib/kokkos/containers/unit_tests/TestCuda.cpp |   227 +
 .../containers/unit_tests/TestDualView.hpp    |   121 +
 .../containers/unit_tests/TestDynViewAPI.hpp  |  1559 ++
 .../containers/unit_tests/TestDynamicView.hpp |   168 +
 .../containers/unit_tests/TestOpenMP.cpp      |   182 +
 .../unit_tests/TestSegmentedView.hpp          |   708 +
 .../containers/unit_tests/TestSerial.cpp      |   175 +
 .../unit_tests/TestStaticCrsGraph.hpp         |   149 +
 .../containers/unit_tests/TestThreads.cpp     |   188 +
 .../unit_tests/TestUnorderedMap.hpp           |   313 +
 .../containers/unit_tests/TestVector.hpp      |   131 +
 .../containers/unit_tests/UnitTestMain.cpp    |    50 +
 lib/kokkos/core/CMakeLists.txt                |    11 +
 lib/kokkos/core/cmake/Dependencies.cmake      |     4 +
 lib/kokkos/core/cmake/KokkosCore_config.h.in  |    57 +
 lib/kokkos/core/perf_test/CMakeLists.txt      |    29 +
 lib/kokkos/core/perf_test/Makefile            |    66 +
 .../core/perf_test/PerfTestBlasKernels.hpp    |   309 +
 lib/kokkos/core/perf_test/PerfTestCuda.cpp    |   189 +
 lib/kokkos/core/perf_test/PerfTestDriver.hpp  |   152 +
 .../core/perf_test/PerfTestGramSchmidt.hpp    |   226 +
 lib/kokkos/core/perf_test/PerfTestHexGrad.hpp |   268 +
 lib/kokkos/core/perf_test/PerfTestHost.cpp    |   104 +
 lib/kokkos/core/perf_test/PerfTestMain.cpp    |    49 +
 lib/kokkos/core/perf_test/test_atomic.cpp     |   507 +
 lib/kokkos/core/src/CMakeLists.txt            |   113 +
 .../core/src/Cuda/KokkosExp_Cuda_View.hpp     |   334 +
 lib/kokkos/core/src/Cuda/Kokkos_CudaExec.hpp  |   318 +
 lib/kokkos/core/src/Cuda/Kokkos_CudaSpace.cpp |   829 +
 .../core/src/Cuda/Kokkos_Cuda_Alloc.hpp       |   182 +
 .../core/src/Cuda/Kokkos_Cuda_Error.hpp       |    69 +
 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Impl.cpp |   778 +
 .../core/src/Cuda/Kokkos_Cuda_Internal.hpp    |   202 +
 .../core/src/Cuda/Kokkos_Cuda_Parallel.hpp    |  1926 ++
 .../core/src/Cuda/Kokkos_Cuda_ReduceScan.hpp  |   433 +
 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.cpp |   179 +
 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.hpp |   519 +
 .../core/src/Cuda/Kokkos_Cuda_TaskPolicy.cpp  |   932 +
 .../core/src/Cuda/Kokkos_Cuda_TaskPolicy.hpp  |   833 +
 .../src/Cuda/Kokkos_Cuda_Vectorization.hpp    |   298 +
 lib/kokkos/core/src/Cuda/Kokkos_Cuda_View.hpp |    93 +
 .../core/src/Cuda/Kokkos_Cuda_abort.hpp       |   119 +
 .../core/src/KokkosExp_MDRangePolicy.hpp      |   611 +
 lib/kokkos/core/src/Kokkos_Array.hpp          |   302 +
 lib/kokkos/core/src/Kokkos_Atomic.hpp         |   305 +
 lib/kokkos/core/src/Kokkos_Complex.hpp        |   538 +
 lib/kokkos/core/src/Kokkos_Concepts.hpp       |    78 +
 lib/kokkos/core/src/Kokkos_Core.hpp           |   174 +
 lib/kokkos/core/src/Kokkos_Core_fwd.hpp       |   247 +
 lib/kokkos/core/src/Kokkos_Cuda.hpp           |   274 +
 lib/kokkos/core/src/Kokkos_CudaSpace.hpp      |   802 +
 lib/kokkos/core/src/Kokkos_ExecPolicy.hpp     |   570 +
 lib/kokkos/core/src/Kokkos_HBWSpace.hpp       |   312 +
 lib/kokkos/core/src/Kokkos_HostSpace.hpp      |   275 +
 lib/kokkos/core/src/Kokkos_Layout.hpp         |   233 +
 lib/kokkos/core/src/Kokkos_Macros.hpp         |   470 +
 lib/kokkos/core/src/Kokkos_MemoryPool.hpp     |  1523 ++
 lib/kokkos/core/src/Kokkos_MemoryTraits.hpp   |   116 +
 lib/kokkos/core/src/Kokkos_OpenMP.hpp         |   189 +
 lib/kokkos/core/src/Kokkos_Pair.hpp           |   530 +
 lib/kokkos/core/src/Kokkos_Parallel.hpp       |   527 +
 .../core/src/Kokkos_Parallel_Reduce.hpp       |  1240 +
 lib/kokkos/core/src/Kokkos_Qthread.hpp        |   172 +
 lib/kokkos/core/src/Kokkos_ScratchSpace.hpp   |   166 +
 lib/kokkos/core/src/Kokkos_Serial.hpp         |  1116 +
 lib/kokkos/core/src/Kokkos_TaskPolicy.hpp     |  1109 +
 lib/kokkos/core/src/Kokkos_Threads.hpp        |   222 +
 lib/kokkos/core/src/Kokkos_Vectorization.hpp  |    53 +
 lib/kokkos/core/src/Kokkos_View.hpp           |  2384 ++
 lib/kokkos/core/src/Kokkos_hwloc.hpp          |   144 +
 lib/kokkos/core/src/Makefile                  |   124 +
 .../src/OpenMP/Kokkos_OpenMP_Parallel.hpp     |   750 +
 .../core/src/OpenMP/Kokkos_OpenMP_Task.cpp    |   329 +
 .../core/src/OpenMP/Kokkos_OpenMP_Task.hpp    |   356 +
 .../core/src/OpenMP/Kokkos_OpenMPexec.cpp     |   408 +
 .../core/src/OpenMP/Kokkos_OpenMPexec.hpp     |  1083 +
 .../core/src/Qthread/Kokkos_QthreadExec.cpp   |   511 +
 .../core/src/Qthread/Kokkos_QthreadExec.hpp   |   620 +
 .../src/Qthread/Kokkos_Qthread_Parallel.hpp   |   745 +
 .../src/Qthread/Kokkos_Qthread_TaskPolicy.cpp |   491 +
 .../src/Qthread/Kokkos_Qthread_TaskPolicy.hpp |   664 +
 lib/kokkos/core/src/Qthread/README            |    25 +
 .../core/src/Threads/Kokkos_ThreadsExec.cpp   |   826 +
 .../core/src/Threads/Kokkos_ThreadsExec.hpp   |   631 +
 .../src/Threads/Kokkos_ThreadsExec_base.cpp   |   255 +
 .../core/src/Threads/Kokkos_ThreadsTeam.hpp   |   932 +
 .../src/Threads/Kokkos_Threads_Parallel.hpp   |   658 +
 .../src/Threads/Kokkos_Threads_TaskPolicy.cpp |   930 +
 .../src/Threads/Kokkos_Threads_TaskPolicy.hpp |   745 +
 lib/kokkos/core/src/impl/CMakeLists.txt       |    18 +
 .../core/src/impl/KokkosExp_SharedAlloc.cpp   |   346 +
 .../core/src/impl/KokkosExp_SharedAlloc.hpp   |   400 +
 .../core/src/impl/KokkosExp_ViewArray.hpp     |   606 +
 .../core/src/impl/KokkosExp_ViewCtor.hpp      |   252 +
 .../core/src/impl/KokkosExp_ViewMapping.hpp   |  2932 +++
 .../core/src/impl/KokkosExp_ViewTile.hpp      |   227 +
 .../core/src/impl/Kokkos_AnalyzePolicy.hpp    |   197 +
 .../core/src/impl/Kokkos_AnalyzeShape.hpp     |   260 +
 .../core/src/impl/Kokkos_Atomic_Assembly.hpp  |   112 +
 .../Kokkos_Atomic_Compare_Exchange_Strong.hpp |   271 +
 .../core/src/impl/Kokkos_Atomic_Decrement.hpp |   117 +
 .../core/src/impl/Kokkos_Atomic_Exchange.hpp  |   359 +
 .../core/src/impl/Kokkos_Atomic_Fetch_Add.hpp |   340 +
 .../core/src/impl/Kokkos_Atomic_Fetch_And.hpp |   125 +
 .../core/src/impl/Kokkos_Atomic_Fetch_Or.hpp  |   125 +
 .../core/src/impl/Kokkos_Atomic_Fetch_Sub.hpp |   235 +
 .../core/src/impl/Kokkos_Atomic_Generic.hpp   |   419 +
 .../core/src/impl/Kokkos_Atomic_Increment.hpp |   117 +
 .../core/src/impl/Kokkos_Atomic_View.hpp      |   430 +
 .../core/src/impl/Kokkos_Atomic_Windows.hpp   |   232 +
 lib/kokkos/core/src/impl/Kokkos_BitOps.hpp    |   122 +
 .../core/src/impl/Kokkos_CPUDiscovery.cpp     |   124 +
 .../core/src/impl/Kokkos_CPUDiscovery.hpp     |    51 +
 lib/kokkos/core/src/impl/Kokkos_Core.cpp      |   454 +
 lib/kokkos/core/src/impl/Kokkos_Error.cpp     |   193 +
 lib/kokkos/core/src/impl/Kokkos_Error.hpp     |    82 +
 .../core/src/impl/Kokkos_ExecPolicy.cpp       |    19 +
 .../core/src/impl/Kokkos_FunctorAdapter.hpp   |  1131 +
 .../core/src/impl/Kokkos_HBWAllocators.cpp    |   108 +
 .../core/src/impl/Kokkos_HBWAllocators.hpp    |    75 +
 lib/kokkos/core/src/impl/Kokkos_HBWSpace.cpp  |   379 +
 lib/kokkos/core/src/impl/Kokkos_HostSpace.cpp |   537 +
 .../core/src/impl/Kokkos_Memory_Fence.hpp     |   107 +
 .../core/src/impl/Kokkos_PhysicalLayout.hpp   |    73 +
 .../src/impl/Kokkos_Profiling_DeviceInfo.hpp  |    57 +
 .../src/impl/Kokkos_Profiling_Interface.cpp   |   186 +
 .../src/impl/Kokkos_Profiling_Interface.hpp   |   118 +
 lib/kokkos/core/src/impl/Kokkos_Serial.cpp    |   119 +
 .../core/src/impl/Kokkos_Serial_Task.cpp      |   147 +
 .../core/src/impl/Kokkos_Serial_Task.hpp      |   271 +
 .../src/impl/Kokkos_Serial_TaskPolicy.cpp     |   348 +
 .../src/impl/Kokkos_Serial_TaskPolicy.hpp     |   677 +
 lib/kokkos/core/src/impl/Kokkos_Shape.cpp     |   178 +
 lib/kokkos/core/src/impl/Kokkos_Shape.hpp     |   917 +
 lib/kokkos/core/src/impl/Kokkos_Singleton.hpp |    55 +
 .../core/src/impl/Kokkos_StaticAssert.hpp     |    79 +
 .../core/src/impl/Kokkos_Synchronic.hpp       |   693 +
 .../src/impl/Kokkos_Synchronic_Config.hpp     |   169 +
 .../core/src/impl/Kokkos_Synchronic_n3998.hpp |   162 +
 lib/kokkos/core/src/impl/Kokkos_Tags.hpp      |   198 +
 lib/kokkos/core/src/impl/Kokkos_TaskQueue.hpp |   499 +
 .../core/src/impl/Kokkos_TaskQueue_impl.hpp   |   569 +
 lib/kokkos/core/src/impl/Kokkos_Timer.hpp     |   118 +
 lib/kokkos/core/src/impl/Kokkos_Traits.hpp    |   501 +
 .../core/src/impl/Kokkos_ViewDefault.hpp      |   886 +
 .../core/src/impl/Kokkos_ViewOffset.hpp       |  1341 ++
 .../core/src/impl/Kokkos_ViewSupport.hpp      |   393 +
 .../core/src/impl/Kokkos_ViewTileLeft.hpp     |    56 +
 .../core/src/impl/Kokkos_Volatile_Load.hpp    |   242 +
 lib/kokkos/core/src/impl/Kokkos_hwloc.cpp     |   726 +
 lib/kokkos/core/src/impl/Kokkos_spinwait.cpp  |    89 +
 lib/kokkos/core/src/impl/Kokkos_spinwait.hpp  |    64 +
 lib/kokkos/core/unit_test/CMakeLists.txt      |   105 +
 lib/kokkos/core/unit_test/Makefile            |   153 +
 lib/kokkos/core/unit_test/TestAggregate.hpp   |   109 +
 .../core/unit_test/TestAggregateReduction.hpp |   191 +
 lib/kokkos/core/unit_test/TestAtomic.hpp      |   402 +
 .../core/unit_test/TestAtomicOperations.hpp   |   841 +
 lib/kokkos/core/unit_test/TestCXX11.hpp       |   334 +
 .../core/unit_test/TestCXX11Deduction.hpp     |    94 +
 .../core/unit_test/TestCompilerMacros.hpp     |    93 +
 lib/kokkos/core/unit_test/TestCuda.cpp        |   290 +
 lib/kokkos/core/unit_test/TestCuda_a.cpp      |   182 +
 lib/kokkos/core/unit_test/TestCuda_b.cpp      |   191 +
 lib/kokkos/core/unit_test/TestCuda_c.cpp      |   375 +
 .../core/unit_test/TestDefaultDeviceType.cpp  |   242 +
 .../unit_test/TestDefaultDeviceTypeInit.hpp   |   419 +
 .../unit_test/TestDefaultDeviceTypeInit_1.cpp |     2 +
 .../TestDefaultDeviceTypeInit_10.cpp          |     2 +
 .../TestDefaultDeviceTypeInit_11.cpp          |     2 +
 .../TestDefaultDeviceTypeInit_12.cpp          |     2 +
 .../TestDefaultDeviceTypeInit_13.cpp          |     2 +
 .../TestDefaultDeviceTypeInit_14.cpp          |     2 +
 .../TestDefaultDeviceTypeInit_15.cpp          |     2 +
 .../TestDefaultDeviceTypeInit_16.cpp          |     2 +
 .../unit_test/TestDefaultDeviceTypeInit_2.cpp |     2 +
 .../unit_test/TestDefaultDeviceTypeInit_3.cpp |     2 +
 .../unit_test/TestDefaultDeviceTypeInit_4.cpp |     2 +
 .../unit_test/TestDefaultDeviceTypeInit_5.cpp |     2 +
 .../unit_test/TestDefaultDeviceTypeInit_6.cpp |     2 +
 .../unit_test/TestDefaultDeviceTypeInit_7.cpp |     2 +
 .../unit_test/TestDefaultDeviceTypeInit_8.cpp |     2 +
 .../unit_test/TestDefaultDeviceTypeInit_9.cpp |     2 +
 .../unit_test/TestDefaultDeviceType_a.cpp     |    76 +
 lib/kokkos/core/unit_test/TestHWLOC.cpp       |    69 +
 lib/kokkos/core/unit_test/TestMDRange.hpp     |   555 +
 lib/kokkos/core/unit_test/TestMemoryPool.hpp  |   820 +
 .../unit_test/TestMemorySpaceTracking.hpp     |   100 +
 lib/kokkos/core/unit_test/TestOpenMP.cpp      |   262 +
 lib/kokkos/core/unit_test/TestOpenMP_a.cpp    |   150 +
 lib/kokkos/core/unit_test/TestOpenMP_b.cpp    |   185 +
 lib/kokkos/core/unit_test/TestOpenMP_c.cpp    |   262 +
 .../core/unit_test/TestPolicyConstruction.hpp |   493 +
 lib/kokkos/core/unit_test/TestQthread.cpp     |   290 +
 lib/kokkos/core/unit_test/TestRange.hpp       |   242 +
 lib/kokkos/core/unit_test/TestReduce.hpp      |  1872 ++
 lib/kokkos/core/unit_test/TestScan.hpp        |   103 +
 lib/kokkos/core/unit_test/TestSerial.cpp      |   571 +
 lib/kokkos/core/unit_test/TestSharedAlloc.hpp |   215 +
 lib/kokkos/core/unit_test/TestSynchronic.cpp  |   448 +
 lib/kokkos/core/unit_test/TestSynchronic.hpp  |   240 +
 lib/kokkos/core/unit_test/TestTaskPolicy.hpp  |  1145 +
 lib/kokkos/core/unit_test/TestTeam.hpp        |   910 +
 lib/kokkos/core/unit_test/TestTeamVector.hpp  |   646 +
 .../unit_test/TestTemplateMetaFunctions.hpp   |   219 +
 lib/kokkos/core/unit_test/TestThreads.cpp     |   614 +
 lib/kokkos/core/unit_test/TestTile.hpp        |   153 +
 lib/kokkos/core/unit_test/TestViewAPI.hpp     |  1416 ++
 lib/kokkos/core/unit_test/TestViewImpl.hpp    |   289 +
 lib/kokkos/core/unit_test/TestViewMapping.hpp |  1307 +
 lib/kokkos/core/unit_test/TestViewOfClass.hpp |   163 +
 lib/kokkos/core/unit_test/TestViewSubview.hpp |   874 +
 lib/kokkos/core/unit_test/UnitTestMain.cpp    |    50 +
 lib/kokkos/doc/Doxyfile                       |   127 +
 lib/kokkos/doc/Kokkos_PG.pdf                  |   Bin 0 -> 1359256 bytes
 lib/kokkos/doc/README                         |    32 +
 lib/kokkos/doc/build_docs                     |    15 +
 lib/kokkos/doc/index.doc                      |    72 +
 lib/kokkos/example/CMakeLists.txt             |    20 +
 lib/kokkos/example/README                     |    16 +
 lib/kokkos/example/cmake/Dependencies.cmake   |     4 +
 lib/kokkos/example/common/VectorImport.hpp    |   294 +
 lib/kokkos/example/common/WrapMPI.hpp         |   103 +
 lib/kokkos/example/feint/CMakeLists.txt       |    18 +
 lib/kokkos/example/feint/ElemFunctor.hpp      |   489 +
 lib/kokkos/example/feint/Makefile             |    61 +
 lib/kokkos/example/feint/feint.hpp            |   165 +
 lib/kokkos/example/feint/feint_cuda.cpp       |    67 +
 lib/kokkos/example/feint/feint_fwd.hpp        |    60 +
 lib/kokkos/example/feint/feint_openmp.cpp     |    67 +
 lib/kokkos/example/feint/feint_threads.cpp    |    66 +
 lib/kokkos/example/feint/main.cpp             |   110 +
 lib/kokkos/example/fenl/CGSolve.hpp           |   296 +
 lib/kokkos/example/fenl/CMakeLists.txt        |    17 +
 lib/kokkos/example/fenl/Makefile              |    54 +
 lib/kokkos/example/fenl/fenl.cpp              |   117 +
 lib/kokkos/example/fenl/fenl.hpp              |    89 +
 lib/kokkos/example/fenl/fenl_functors.hpp     |  1173 +
 lib/kokkos/example/fenl/fenl_impl.hpp         |   598 +
 lib/kokkos/example/fenl/main.cpp              |   422 +
 lib/kokkos/example/fixture/BoxElemFixture.hpp |   355 +
 lib/kokkos/example/fixture/BoxElemPart.cpp    |   413 +
 lib/kokkos/example/fixture/BoxElemPart.hpp    |   320 +
 lib/kokkos/example/fixture/CMakeLists.txt     |    13 +
 lib/kokkos/example/fixture/HexElement.hpp     |   270 +
 lib/kokkos/example/fixture/Main.cpp           |   304 +
 lib/kokkos/example/fixture/Makefile           |    48 +
 lib/kokkos/example/fixture/TestFixture.cpp    |    58 +
 lib/kokkos/example/fixture/TestFixture.hpp    |   156 +
 .../example/global_2_local_ids/CMakeLists.txt |    17 +
 lib/kokkos/example/global_2_local_ids/G2L.hpp |   266 +
 .../example/global_2_local_ids/G2L_Main.cpp   |   149 +
 .../example/global_2_local_ids/Makefile       |    53 +
 lib/kokkos/example/grow_array/CMakeLists.txt  |    14 +
 lib/kokkos/example/grow_array/Makefile        |    53 +
 lib/kokkos/example/grow_array/grow_array.hpp  |   257 +
 lib/kokkos/example/grow_array/main.cpp        |   110 +
 lib/kokkos/example/ichol/Makefile             |    63 +
 .../example_chol_performance_device.hpp       |   240 +
 .../example_chol_performance_device_cuda.cpp  |    70 +
 ...xample_chol_performance_device_pthread.cpp |    67 +
 lib/kokkos/example/ichol/src/chol.hpp         |    92 +
 lib/kokkos/example/ichol/src/chol_u.hpp       |    23 +
 .../ichol/src/chol_u_right_look_by_blocks.hpp |   394 +
 .../ichol/src/chol_u_unblocked_opt1.hpp       |    90 +
 .../ichol/src/chol_u_unblocked_opt2.hpp       |   154 +
 lib/kokkos/example/ichol/src/control.hpp      |   110 +
 lib/kokkos/example/ichol/src/coo.hpp          |    75 +
 .../example/ichol/src/crs_matrix_base.hpp     |   598 +
 .../ichol/src/crs_matrix_base_import.hpp      |   104 +
 .../example/ichol/src/crs_matrix_helper.hpp   |    71 +
 .../ichol/src/crs_matrix_helper_impl.hpp      |   364 +
 .../example/ichol/src/crs_matrix_view.hpp     |   226 +
 lib/kokkos/example/ichol/src/crs_row_view.hpp |   185 +
 lib/kokkos/example/ichol/src/dot.hpp          |    74 +
 lib/kokkos/example/ichol/src/gemm.hpp         |    99 +
 lib/kokkos/example/ichol/src/gemm_ct_nt.hpp   |    12 +
 .../src/gemm_ct_nt_for_factor_blocked.hpp     |   108 +
 .../example/ichol/src/graph_helper_scotch.hpp |   427 +
 lib/kokkos/example/ichol/src/herk.hpp         |    91 +
 lib/kokkos/example/ichol/src/herk_u_ct.hpp    |    11 +
 .../src/herk_u_ct_for_factor_blocked.hpp      |   103 +
 lib/kokkos/example/ichol/src/norm.hpp         |    82 +
 lib/kokkos/example/ichol/src/partition.hpp    |   381 +
 lib/kokkos/example/ichol/src/scale.hpp        |    92 +
 .../ichol/src/symbolic_factor_helper.hpp      |   379 +
 .../example/ichol/src/symbolic_task.hpp       |   118 +
 lib/kokkos/example/ichol/src/task_factory.hpp |    77 +
 lib/kokkos/example/ichol/src/task_view.hpp    |   104 +
 lib/kokkos/example/ichol/src/trsm.hpp         |    92 +
 lib/kokkos/example/ichol/src/trsm_l_u_ct.hpp  |    14 +
 .../src/trsm_l_u_ct_for_factor_blocked.hpp    |   185 +
 lib/kokkos/example/ichol/src/util.cpp         |     4 +
 lib/kokkos/example/ichol/src/util.hpp         |   237 +
 lib/kokkos/example/md_skeleton/CMakeLists.txt |    16 +
 lib/kokkos/example/md_skeleton/Makefile       |    53 +
 lib/kokkos/example/md_skeleton/README         |     3 +
 lib/kokkos/example/md_skeleton/force.cpp      |   192 +
 lib/kokkos/example/md_skeleton/main.cpp       |   205 +
 lib/kokkos/example/md_skeleton/neighbor.cpp   |   430 +
 lib/kokkos/example/md_skeleton/setup.cpp      |   271 +
 lib/kokkos/example/md_skeleton/system.h       |    92 +
 lib/kokkos/example/md_skeleton/types.h        |   118 +
 .../example/multi_fem/BoxMeshFixture.hpp      |   610 +
 .../example/multi_fem/BoxMeshPartition.cpp    |   381 +
 .../example/multi_fem/BoxMeshPartition.hpp    |   210 +
 lib/kokkos/example/multi_fem/CMakeLists.txt   |    16 +
 lib/kokkos/example/multi_fem/Explicit.hpp     |   452 +
 .../example/multi_fem/ExplicitFunctors.hpp    |  1471 ++
 lib/kokkos/example/multi_fem/FEMesh.hpp       |    86 +
 lib/kokkos/example/multi_fem/HexElement.hpp   |   268 +
 .../multi_fem/HexExplicitFunctions.hpp        |   443 +
 lib/kokkos/example/multi_fem/Implicit.hpp     |   341 +
 .../example/multi_fem/ImplicitFunctors.hpp    |   585 +
 lib/kokkos/example/multi_fem/LinAlgBLAS.hpp   |   567 +
 lib/kokkos/example/multi_fem/Makefile         |    53 +
 lib/kokkos/example/multi_fem/Nonlinear.hpp    |   573 +
 .../multi_fem/NonlinearElement_Cuda.hpp       |   390 +
 .../example/multi_fem/NonlinearFunctors.hpp   |   482 +
 lib/kokkos/example/multi_fem/ParallelComm.hpp |   167 +
 .../example/multi_fem/ParallelDataMap.hpp     |   517 +
 .../example/multi_fem/ParallelMachine.cpp     |   178 +
 .../example/multi_fem/ParallelMachine.hpp     |   118 +
 .../example/multi_fem/SparseLinearSystem.hpp  |   400 +
 .../multi_fem/SparseLinearSystemFill.hpp      |   276 +
 .../multi_fem/SparseLinearSystem_Cuda.hpp     |   164 +
 .../example/multi_fem/TestBoxMeshFixture.hpp  |   242 +
 .../multi_fem/TestBoxMeshPartition.cpp        |   172 +
 lib/kokkos/example/multi_fem/TestCuda.cpp     |   192 +
 lib/kokkos/example/multi_fem/TestHost.cpp     |   137 +
 .../example/multi_fem/TestHybridFEM.cpp       |   348 +
 .../example/query_device/CMakeLists.txt       |    14 +
 lib/kokkos/example/query_device/Makefile      |    53 +
 .../example/query_device/query_device.cpp     |   100 +
 lib/kokkos/example/sort_array/CMakeLists.txt  |    14 +
 lib/kokkos/example/sort_array/Makefile        |    53 +
 lib/kokkos/example/sort_array/main.cpp        |    95 +
 lib/kokkos/example/sort_array/sort_array.hpp  |   190 +
 .../tutorial/01_hello_world/CMakeLists.txt    |    11 +
 .../example/tutorial/01_hello_world/Makefile  |    43 +
 .../tutorial/01_hello_world/hello_world.cpp   |   130 +
 .../01_hello_world_lambda/CMakeLists.txt      |    13 +
 .../tutorial/01_hello_world_lambda/Makefile   |    44 +
 .../hello_world_lambda.cpp                    |   109 +
 .../tutorial/02_simple_reduce/CMakeLists.txt  |    10 +
 .../tutorial/02_simple_reduce/Makefile        |    43 +
 .../02_simple_reduce/simple_reduce.cpp        |   101 +
 .../02_simple_reduce_lambda/CMakeLists.txt    |    12 +
 .../tutorial/02_simple_reduce_lambda/Makefile |    44 +
 .../simple_reduce_lambda.cpp                  |    86 +
 .../tutorial/03_simple_view/CMakeLists.txt    |    10 +
 .../example/tutorial/03_simple_view/Makefile  |    43 +
 .../tutorial/03_simple_view/simple_view.cpp   |   142 +
 .../03_simple_view_lambda/CMakeLists.txt      |    12 +
 .../tutorial/03_simple_view_lambda/Makefile   |    44 +
 .../simple_view_lambda.cpp                    |   116 +
 .../04_simple_memoryspaces/CMakeLists.txt     |    10 +
 .../tutorial/04_simple_memoryspaces/Makefile  |    43 +
 .../simple_memoryspaces.cpp                   |   101 +
 .../tutorial/05_simple_atomics/CMakeLists.txt |    10 +
 .../tutorial/05_simple_atomics/Makefile       |    43 +
 .../05_simple_atomics/simple_atomics.cpp      |   137 +
 .../01_data_layouts/CMakeLists.txt            |    10 +
 .../Advanced_Views/01_data_layouts/Makefile   |    43 +
 .../01_data_layouts/data_layouts.cpp          |   171 +
 .../02_memory_traits/CMakeLists.txt           |    10 +
 .../Advanced_Views/02_memory_traits/Makefile  |    43 +
 .../02_memory_traits/memory_traits.cpp        |   141 +
 .../Advanced_Views/03_subviews/CMakeLists.txt |    10 +
 .../Advanced_Views/03_subviews/Makefile       |    43 +
 .../Advanced_Views/03_subviews/subviews.cpp   |   190 +
 .../04_dualviews/CMakeLists.txt               |    10 +
 .../Advanced_Views/04_dualviews/Makefile      |    43 +
 .../Advanced_Views/04_dualviews/dual_view.cpp |   218 +
 .../05_NVIDIA_UVM/CMakeLists.txt              |    13 +
 .../Advanced_Views/05_NVIDIA_UVM/Makefile     |    43 +
 .../05_NVIDIA_UVM/uvm_example.cpp             |   134 +
 .../Advanced_Views/06_AtomicViews/Makefile    |    43 +
 .../07_Overlapping_DeepCopy/Makefile          |    43 +
 .../overlapping_deepcopy.cpp                  |   148 +
 .../tutorial/Advanced_Views/CMakeLists.txt    |     9 +
 .../example/tutorial/Advanced_Views/Makefile  |    84 +
 .../Algorithms/01_random_numbers/Makefile     |    43 +
 .../01_random_numbers/random_numbers.cpp      |   152 +
 .../example/tutorial/Algorithms/Makefile      |    24 +
 lib/kokkos/example/tutorial/CMakeLists.txt    |    17 +
 .../01_thread_teams/CMakeLists.txt            |    10 +
 .../01_thread_teams/Makefile                  |    43 +
 .../01_thread_teams/thread_teams.cpp          |    94 +
 .../01_thread_teams_lambda/CMakeLists.txt     |    13 +
 .../01_thread_teams_lambda/Makefile           |    44 +
 .../thread_teams_lambda.cpp                   |    94 +
 .../02_nested_parallel_for/CMakeLists.txt     |    10 +
 .../02_nested_parallel_for/Makefile           |    43 +
 .../nested_parallel_for.cpp                   |    89 +
 .../03_vectorization/CMakeLists.txt           |    16 +
 .../03_vectorization/Makefile                 |    43 +
 .../03_vectorization/vectorization.cpp        |   162 +
 .../04_team_scan/CMakeLists.txt               |    10 +
 .../04_team_scan/Makefile                     |    43 +
 .../04_team_scan/team_scan.cpp                |   141 +
 .../Hierarchical_Parallelism/CMakeLists.txt   |     8 +
 .../Hierarchical_Parallelism/Makefile         |    72 +
 lib/kokkos/example/tutorial/Makefile          |   144 +
 lib/kokkos/example/tutorial/README            |    17 +
 lib/kokkos/generate_makefile.bash             |   336 +
 lib/kokkos/tpls/gtest/gtest/LICENSE           |    28 +
 lib/kokkos/tpls/gtest/gtest/README            |    13 +
 lib/kokkos/tpls/gtest/gtest/gtest-all.cc      |  9594 ++++++++
 lib/kokkos/tpls/gtest/gtest/gtest-test-part.h |     1 +
 lib/kokkos/tpls/gtest/gtest/gtest.h           | 20065 ++++++++++++++++
 502 files changed, 157510 insertions(+)
 create mode 100644 lib/kokkos/.gitignore
 create mode 100644 lib/kokkos/CMakeLists.txt
 create mode 100644 lib/kokkos/Copyright.txt
 create mode 100644 lib/kokkos/HOW_TO_SNAPSHOT
 create mode 100644 lib/kokkos/LICENSE
 create mode 100644 lib/kokkos/Makefile.kokkos
 create mode 100644 lib/kokkos/Makefile.targets
 create mode 100644 lib/kokkos/README
 create mode 100644 lib/kokkos/algorithms/CMakeLists.txt
 create mode 100644 lib/kokkos/algorithms/cmake/Dependencies.cmake
 create mode 100644 lib/kokkos/algorithms/cmake/KokkosAlgorithms_config.h.in
 create mode 100644 lib/kokkos/algorithms/src/CMakeLists.txt
 create mode 100644 lib/kokkos/algorithms/src/KokkosAlgorithms_dummy.cpp
 create mode 100644 lib/kokkos/algorithms/src/Kokkos_Random.hpp
 create mode 100644 lib/kokkos/algorithms/src/Kokkos_Sort.hpp
 create mode 100644 lib/kokkos/algorithms/unit_tests/CMakeLists.txt
 create mode 100644 lib/kokkos/algorithms/unit_tests/Makefile
 create mode 100644 lib/kokkos/algorithms/unit_tests/TestCuda.cpp
 create mode 100644 lib/kokkos/algorithms/unit_tests/TestOpenMP.cpp
 create mode 100644 lib/kokkos/algorithms/unit_tests/TestRandom.hpp
 create mode 100644 lib/kokkos/algorithms/unit_tests/TestSerial.cpp
 create mode 100644 lib/kokkos/algorithms/unit_tests/TestSort.hpp
 create mode 100644 lib/kokkos/algorithms/unit_tests/TestThreads.cpp
 create mode 100644 lib/kokkos/algorithms/unit_tests/UnitTestMain.cpp
 create mode 100644 lib/kokkos/cmake/Dependencies.cmake
 create mode 100644 lib/kokkos/cmake/deps/CUDA.cmake
 create mode 100644 lib/kokkos/cmake/deps/CUSPARSE.cmake
 create mode 100644 lib/kokkos/cmake/deps/HWLOC.cmake
 create mode 100644 lib/kokkos/cmake/deps/Pthread.cmake
 create mode 100644 lib/kokkos/cmake/deps/QTHREAD.cmake
 create mode 100644 lib/kokkos/cmake/tpls/FindTPLCUSPARSE.cmake
 create mode 100644 lib/kokkos/cmake/tpls/FindTPLHWLOC.cmake
 create mode 100644 lib/kokkos/cmake/tpls/FindTPLPthread.cmake
 create mode 100644 lib/kokkos/cmake/tpls/FindTPLQTHREAD.cmake
 create mode 100644 lib/kokkos/cmake/tribits.cmake
 create mode 100755 lib/kokkos/config/configure_compton_cpu.sh
 create mode 100755 lib/kokkos/config/configure_compton_mic.sh
 create mode 100755 lib/kokkos/config/configure_kokkos.sh
 create mode 100755 lib/kokkos/config/configure_kokkos_bgq.sh
 create mode 100755 lib/kokkos/config/configure_kokkos_dev.sh
 create mode 100755 lib/kokkos/config/configure_kokkos_nvidia.sh
 create mode 100755 lib/kokkos/config/configure_shannon.sh
 create mode 100755 lib/kokkos/config/configure_tpetra_kokkos_cuda_nvcc_wrapper.sh
 create mode 100644 lib/kokkos/config/kokkos-trilinos-integration-procedure.txt
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-all.sh
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-cuda-omp-hwloc.sh
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-cuda.sh
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-cxx11-omp.sh
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-dbg-none.sh
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-intel-cuda-omp.sh
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-intel-omp.sh
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-omp.sh
 create mode 100755 lib/kokkos/config/kokkos_dev/config-core-threads-hwloc.sh
 create mode 100644 lib/kokkos/config/master_history.txt
 create mode 100755 lib/kokkos/config/nvcc_wrapper
 create mode 100755 lib/kokkos/config/snapshot.py
 create mode 100755 lib/kokkos/config/test_all_sandia
 create mode 100644 lib/kokkos/config/testing_scripts/README
 create mode 100755 lib/kokkos/config/testing_scripts/jenkins_test_driver
 create mode 100755 lib/kokkos/config/testing_scripts/obj_size_opt_check
 create mode 100644 lib/kokkos/containers/CMakeLists.txt
 create mode 100644 lib/kokkos/containers/cmake/Dependencies.cmake
 create mode 100644 lib/kokkos/containers/cmake/KokkosContainers_config.h.in
 create mode 100644 lib/kokkos/containers/performance_tests/CMakeLists.txt
 create mode 100644 lib/kokkos/containers/performance_tests/Makefile
 create mode 100644 lib/kokkos/containers/performance_tests/TestCuda.cpp
 create mode 100644 lib/kokkos/containers/performance_tests/TestDynRankView.hpp
 create mode 100644 lib/kokkos/containers/performance_tests/TestGlobal2LocalIds.hpp
 create mode 100644 lib/kokkos/containers/performance_tests/TestMain.cpp
 create mode 100644 lib/kokkos/containers/performance_tests/TestOpenMP.cpp
 create mode 100644 lib/kokkos/containers/performance_tests/TestThreads.cpp
 create mode 100644 lib/kokkos/containers/performance_tests/TestUnorderedMapPerformance.hpp
 create mode 100644 lib/kokkos/containers/src/CMakeLists.txt
 create mode 100644 lib/kokkos/containers/src/Kokkos_Bitset.hpp
 create mode 100644 lib/kokkos/containers/src/Kokkos_DualView.hpp
 create mode 100644 lib/kokkos/containers/src/Kokkos_DynRankView.hpp
 create mode 100644 lib/kokkos/containers/src/Kokkos_DynamicView.hpp
 create mode 100644 lib/kokkos/containers/src/Kokkos_Functional.hpp
 create mode 100644 lib/kokkos/containers/src/Kokkos_SegmentedView.hpp
 create mode 100644 lib/kokkos/containers/src/Kokkos_StaticCrsGraph.hpp
 create mode 100644 lib/kokkos/containers/src/Kokkos_UnorderedMap.hpp
 create mode 100644 lib/kokkos/containers/src/Kokkos_Vector.hpp
 create mode 100644 lib/kokkos/containers/src/impl/Kokkos_Bitset_impl.hpp
 create mode 100644 lib/kokkos/containers/src/impl/Kokkos_Functional_impl.hpp
 create mode 100644 lib/kokkos/containers/src/impl/Kokkos_StaticCrsGraph_factory.hpp
 create mode 100644 lib/kokkos/containers/src/impl/Kokkos_UnorderedMap_impl.cpp
 create mode 100644 lib/kokkos/containers/src/impl/Kokkos_UnorderedMap_impl.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/CMakeLists.txt
 create mode 100644 lib/kokkos/containers/unit_tests/Makefile
 create mode 100644 lib/kokkos/containers/unit_tests/TestBitset.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestComplex.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestCuda.cpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestDualView.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestDynViewAPI.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestDynamicView.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestOpenMP.cpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestSegmentedView.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestSerial.cpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestStaticCrsGraph.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestThreads.cpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestUnorderedMap.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/TestVector.hpp
 create mode 100644 lib/kokkos/containers/unit_tests/UnitTestMain.cpp
 create mode 100644 lib/kokkos/core/CMakeLists.txt
 create mode 100644 lib/kokkos/core/cmake/Dependencies.cmake
 create mode 100644 lib/kokkos/core/cmake/KokkosCore_config.h.in
 create mode 100644 lib/kokkos/core/perf_test/CMakeLists.txt
 create mode 100644 lib/kokkos/core/perf_test/Makefile
 create mode 100644 lib/kokkos/core/perf_test/PerfTestBlasKernels.hpp
 create mode 100644 lib/kokkos/core/perf_test/PerfTestCuda.cpp
 create mode 100644 lib/kokkos/core/perf_test/PerfTestDriver.hpp
 create mode 100644 lib/kokkos/core/perf_test/PerfTestGramSchmidt.hpp
 create mode 100644 lib/kokkos/core/perf_test/PerfTestHexGrad.hpp
 create mode 100644 lib/kokkos/core/perf_test/PerfTestHost.cpp
 create mode 100644 lib/kokkos/core/perf_test/PerfTestMain.cpp
 create mode 100644 lib/kokkos/core/perf_test/test_atomic.cpp
 create mode 100644 lib/kokkos/core/src/CMakeLists.txt
 create mode 100644 lib/kokkos/core/src/Cuda/KokkosExp_Cuda_View.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_CudaExec.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_CudaSpace.cpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Alloc.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Error.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Impl.cpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Internal.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Parallel.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_ReduceScan.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.cpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_TaskPolicy.cpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_TaskPolicy.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_Vectorization.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_View.hpp
 create mode 100644 lib/kokkos/core/src/Cuda/Kokkos_Cuda_abort.hpp
 create mode 100644 lib/kokkos/core/src/KokkosExp_MDRangePolicy.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Array.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Atomic.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Complex.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Concepts.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Core.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Core_fwd.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Cuda.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_CudaSpace.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_ExecPolicy.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_HBWSpace.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_HostSpace.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Layout.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Macros.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_MemoryPool.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_MemoryTraits.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_OpenMP.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Pair.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Parallel.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Parallel_Reduce.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Qthread.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_ScratchSpace.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Serial.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_TaskPolicy.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Threads.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_Vectorization.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_View.hpp
 create mode 100644 lib/kokkos/core/src/Kokkos_hwloc.hpp
 create mode 100644 lib/kokkos/core/src/Makefile
 create mode 100644 lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Parallel.hpp
 create mode 100644 lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Task.cpp
 create mode 100644 lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Task.hpp
 create mode 100644 lib/kokkos/core/src/OpenMP/Kokkos_OpenMPexec.cpp
 create mode 100644 lib/kokkos/core/src/OpenMP/Kokkos_OpenMPexec.hpp
 create mode 100644 lib/kokkos/core/src/Qthread/Kokkos_QthreadExec.cpp
 create mode 100644 lib/kokkos/core/src/Qthread/Kokkos_QthreadExec.hpp
 create mode 100644 lib/kokkos/core/src/Qthread/Kokkos_Qthread_Parallel.hpp
 create mode 100644 lib/kokkos/core/src/Qthread/Kokkos_Qthread_TaskPolicy.cpp
 create mode 100644 lib/kokkos/core/src/Qthread/Kokkos_Qthread_TaskPolicy.hpp
 create mode 100644 lib/kokkos/core/src/Qthread/README
 create mode 100644 lib/kokkos/core/src/Threads/Kokkos_ThreadsExec.cpp
 create mode 100644 lib/kokkos/core/src/Threads/Kokkos_ThreadsExec.hpp
 create mode 100644 lib/kokkos/core/src/Threads/Kokkos_ThreadsExec_base.cpp
 create mode 100644 lib/kokkos/core/src/Threads/Kokkos_ThreadsTeam.hpp
 create mode 100644 lib/kokkos/core/src/Threads/Kokkos_Threads_Parallel.hpp
 create mode 100644 lib/kokkos/core/src/Threads/Kokkos_Threads_TaskPolicy.cpp
 create mode 100644 lib/kokkos/core/src/Threads/Kokkos_Threads_TaskPolicy.hpp
 create mode 100644 lib/kokkos/core/src/impl/CMakeLists.txt
 create mode 100644 lib/kokkos/core/src/impl/KokkosExp_SharedAlloc.cpp
 create mode 100644 lib/kokkos/core/src/impl/KokkosExp_SharedAlloc.hpp
 create mode 100644 lib/kokkos/core/src/impl/KokkosExp_ViewArray.hpp
 create mode 100644 lib/kokkos/core/src/impl/KokkosExp_ViewCtor.hpp
 create mode 100644 lib/kokkos/core/src/impl/KokkosExp_ViewMapping.hpp
 create mode 100644 lib/kokkos/core/src/impl/KokkosExp_ViewTile.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_AnalyzePolicy.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_AnalyzeShape.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Assembly.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Compare_Exchange_Strong.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Decrement.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Exchange.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Add.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_And.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Or.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Sub.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Generic.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Increment.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_View.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Atomic_Windows.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_BitOps.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_CPUDiscovery.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_CPUDiscovery.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Core.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Error.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Error.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_ExecPolicy.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_FunctorAdapter.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_HBWAllocators.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_HBWAllocators.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_HBWSpace.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_HostSpace.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Memory_Fence.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_PhysicalLayout.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Profiling_DeviceInfo.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Profiling_Interface.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Profiling_Interface.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Serial.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Serial_Task.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Serial_Task.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Shape.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Shape.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Singleton.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_StaticAssert.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Synchronic.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Synchronic_Config.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Synchronic_n3998.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Tags.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_TaskQueue.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_TaskQueue_impl.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Timer.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Traits.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_ViewDefault.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_ViewOffset.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_ViewSupport.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_ViewTileLeft.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_Volatile_Load.hpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_hwloc.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_spinwait.cpp
 create mode 100644 lib/kokkos/core/src/impl/Kokkos_spinwait.hpp
 create mode 100644 lib/kokkos/core/unit_test/CMakeLists.txt
 create mode 100644 lib/kokkos/core/unit_test/Makefile
 create mode 100644 lib/kokkos/core/unit_test/TestAggregate.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestAggregateReduction.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestAtomic.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestAtomicOperations.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestCXX11.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestCXX11Deduction.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestCompilerMacros.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestCuda.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestCuda_a.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestCuda_b.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestCuda_c.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceType.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_1.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_10.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_11.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_12.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_13.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_14.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_15.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_16.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_2.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_3.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_4.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_5.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_6.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_7.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_8.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_9.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestDefaultDeviceType_a.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestHWLOC.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestMDRange.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestMemoryPool.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestMemorySpaceTracking.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestOpenMP.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestOpenMP_a.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestOpenMP_b.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestOpenMP_c.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestPolicyConstruction.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestQthread.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestRange.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestReduce.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestScan.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestSerial.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestSharedAlloc.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestSynchronic.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestSynchronic.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestTaskPolicy.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestTeam.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestTeamVector.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestTemplateMetaFunctions.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestThreads.cpp
 create mode 100644 lib/kokkos/core/unit_test/TestTile.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestViewAPI.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestViewImpl.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestViewMapping.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestViewOfClass.hpp
 create mode 100644 lib/kokkos/core/unit_test/TestViewSubview.hpp
 create mode 100644 lib/kokkos/core/unit_test/UnitTestMain.cpp
 create mode 100644 lib/kokkos/doc/Doxyfile
 create mode 100644 lib/kokkos/doc/Kokkos_PG.pdf
 create mode 100644 lib/kokkos/doc/README
 create mode 100755 lib/kokkos/doc/build_docs
 create mode 100644 lib/kokkos/doc/index.doc
 create mode 100644 lib/kokkos/example/CMakeLists.txt
 create mode 100644 lib/kokkos/example/README
 create mode 100644 lib/kokkos/example/cmake/Dependencies.cmake
 create mode 100644 lib/kokkos/example/common/VectorImport.hpp
 create mode 100644 lib/kokkos/example/common/WrapMPI.hpp
 create mode 100644 lib/kokkos/example/feint/CMakeLists.txt
 create mode 100644 lib/kokkos/example/feint/ElemFunctor.hpp
 create mode 100644 lib/kokkos/example/feint/Makefile
 create mode 100644 lib/kokkos/example/feint/feint.hpp
 create mode 100644 lib/kokkos/example/feint/feint_cuda.cpp
 create mode 100644 lib/kokkos/example/feint/feint_fwd.hpp
 create mode 100644 lib/kokkos/example/feint/feint_openmp.cpp
 create mode 100644 lib/kokkos/example/feint/feint_threads.cpp
 create mode 100644 lib/kokkos/example/feint/main.cpp
 create mode 100644 lib/kokkos/example/fenl/CGSolve.hpp
 create mode 100644 lib/kokkos/example/fenl/CMakeLists.txt
 create mode 100644 lib/kokkos/example/fenl/Makefile
 create mode 100644 lib/kokkos/example/fenl/fenl.cpp
 create mode 100644 lib/kokkos/example/fenl/fenl.hpp
 create mode 100644 lib/kokkos/example/fenl/fenl_functors.hpp
 create mode 100644 lib/kokkos/example/fenl/fenl_impl.hpp
 create mode 100644 lib/kokkos/example/fenl/main.cpp
 create mode 100644 lib/kokkos/example/fixture/BoxElemFixture.hpp
 create mode 100644 lib/kokkos/example/fixture/BoxElemPart.cpp
 create mode 100644 lib/kokkos/example/fixture/BoxElemPart.hpp
 create mode 100644 lib/kokkos/example/fixture/CMakeLists.txt
 create mode 100644 lib/kokkos/example/fixture/HexElement.hpp
 create mode 100644 lib/kokkos/example/fixture/Main.cpp
 create mode 100644 lib/kokkos/example/fixture/Makefile
 create mode 100644 lib/kokkos/example/fixture/TestFixture.cpp
 create mode 100644 lib/kokkos/example/fixture/TestFixture.hpp
 create mode 100644 lib/kokkos/example/global_2_local_ids/CMakeLists.txt
 create mode 100644 lib/kokkos/example/global_2_local_ids/G2L.hpp
 create mode 100644 lib/kokkos/example/global_2_local_ids/G2L_Main.cpp
 create mode 100644 lib/kokkos/example/global_2_local_ids/Makefile
 create mode 100644 lib/kokkos/example/grow_array/CMakeLists.txt
 create mode 100644 lib/kokkos/example/grow_array/Makefile
 create mode 100644 lib/kokkos/example/grow_array/grow_array.hpp
 create mode 100644 lib/kokkos/example/grow_array/main.cpp
 create mode 100644 lib/kokkos/example/ichol/Makefile
 create mode 100644 lib/kokkos/example/ichol/example/example_chol_performance_device.hpp
 create mode 100644 lib/kokkos/example/ichol/example/example_chol_performance_device_cuda.cpp
 create mode 100644 lib/kokkos/example/ichol/example/example_chol_performance_device_pthread.cpp
 create mode 100644 lib/kokkos/example/ichol/src/chol.hpp
 create mode 100644 lib/kokkos/example/ichol/src/chol_u.hpp
 create mode 100644 lib/kokkos/example/ichol/src/chol_u_right_look_by_blocks.hpp
 create mode 100644 lib/kokkos/example/ichol/src/chol_u_unblocked_opt1.hpp
 create mode 100644 lib/kokkos/example/ichol/src/chol_u_unblocked_opt2.hpp
 create mode 100644 lib/kokkos/example/ichol/src/control.hpp
 create mode 100644 lib/kokkos/example/ichol/src/coo.hpp
 create mode 100644 lib/kokkos/example/ichol/src/crs_matrix_base.hpp
 create mode 100644 lib/kokkos/example/ichol/src/crs_matrix_base_import.hpp
 create mode 100644 lib/kokkos/example/ichol/src/crs_matrix_helper.hpp
 create mode 100644 lib/kokkos/example/ichol/src/crs_matrix_helper_impl.hpp
 create mode 100644 lib/kokkos/example/ichol/src/crs_matrix_view.hpp
 create mode 100644 lib/kokkos/example/ichol/src/crs_row_view.hpp
 create mode 100644 lib/kokkos/example/ichol/src/dot.hpp
 create mode 100644 lib/kokkos/example/ichol/src/gemm.hpp
 create mode 100644 lib/kokkos/example/ichol/src/gemm_ct_nt.hpp
 create mode 100644 lib/kokkos/example/ichol/src/gemm_ct_nt_for_factor_blocked.hpp
 create mode 100644 lib/kokkos/example/ichol/src/graph_helper_scotch.hpp
 create mode 100644 lib/kokkos/example/ichol/src/herk.hpp
 create mode 100644 lib/kokkos/example/ichol/src/herk_u_ct.hpp
 create mode 100644 lib/kokkos/example/ichol/src/herk_u_ct_for_factor_blocked.hpp
 create mode 100644 lib/kokkos/example/ichol/src/norm.hpp
 create mode 100644 lib/kokkos/example/ichol/src/partition.hpp
 create mode 100644 lib/kokkos/example/ichol/src/scale.hpp
 create mode 100644 lib/kokkos/example/ichol/src/symbolic_factor_helper.hpp
 create mode 100644 lib/kokkos/example/ichol/src/symbolic_task.hpp
 create mode 100644 lib/kokkos/example/ichol/src/task_factory.hpp
 create mode 100644 lib/kokkos/example/ichol/src/task_view.hpp
 create mode 100644 lib/kokkos/example/ichol/src/trsm.hpp
 create mode 100644 lib/kokkos/example/ichol/src/trsm_l_u_ct.hpp
 create mode 100644 lib/kokkos/example/ichol/src/trsm_l_u_ct_for_factor_blocked.hpp
 create mode 100644 lib/kokkos/example/ichol/src/util.cpp
 create mode 100644 lib/kokkos/example/ichol/src/util.hpp
 create mode 100644 lib/kokkos/example/md_skeleton/CMakeLists.txt
 create mode 100644 lib/kokkos/example/md_skeleton/Makefile
 create mode 100644 lib/kokkos/example/md_skeleton/README
 create mode 100644 lib/kokkos/example/md_skeleton/force.cpp
 create mode 100644 lib/kokkos/example/md_skeleton/main.cpp
 create mode 100644 lib/kokkos/example/md_skeleton/neighbor.cpp
 create mode 100644 lib/kokkos/example/md_skeleton/setup.cpp
 create mode 100644 lib/kokkos/example/md_skeleton/system.h
 create mode 100644 lib/kokkos/example/md_skeleton/types.h
 create mode 100644 lib/kokkos/example/multi_fem/BoxMeshFixture.hpp
 create mode 100644 lib/kokkos/example/multi_fem/BoxMeshPartition.cpp
 create mode 100644 lib/kokkos/example/multi_fem/BoxMeshPartition.hpp
 create mode 100644 lib/kokkos/example/multi_fem/CMakeLists.txt
 create mode 100644 lib/kokkos/example/multi_fem/Explicit.hpp
 create mode 100644 lib/kokkos/example/multi_fem/ExplicitFunctors.hpp
 create mode 100644 lib/kokkos/example/multi_fem/FEMesh.hpp
 create mode 100644 lib/kokkos/example/multi_fem/HexElement.hpp
 create mode 100644 lib/kokkos/example/multi_fem/HexExplicitFunctions.hpp
 create mode 100644 lib/kokkos/example/multi_fem/Implicit.hpp
 create mode 100644 lib/kokkos/example/multi_fem/ImplicitFunctors.hpp
 create mode 100644 lib/kokkos/example/multi_fem/LinAlgBLAS.hpp
 create mode 100644 lib/kokkos/example/multi_fem/Makefile
 create mode 100644 lib/kokkos/example/multi_fem/Nonlinear.hpp
 create mode 100644 lib/kokkos/example/multi_fem/NonlinearElement_Cuda.hpp
 create mode 100644 lib/kokkos/example/multi_fem/NonlinearFunctors.hpp
 create mode 100644 lib/kokkos/example/multi_fem/ParallelComm.hpp
 create mode 100644 lib/kokkos/example/multi_fem/ParallelDataMap.hpp
 create mode 100644 lib/kokkos/example/multi_fem/ParallelMachine.cpp
 create mode 100644 lib/kokkos/example/multi_fem/ParallelMachine.hpp
 create mode 100644 lib/kokkos/example/multi_fem/SparseLinearSystem.hpp
 create mode 100644 lib/kokkos/example/multi_fem/SparseLinearSystemFill.hpp
 create mode 100644 lib/kokkos/example/multi_fem/SparseLinearSystem_Cuda.hpp
 create mode 100644 lib/kokkos/example/multi_fem/TestBoxMeshFixture.hpp
 create mode 100644 lib/kokkos/example/multi_fem/TestBoxMeshPartition.cpp
 create mode 100644 lib/kokkos/example/multi_fem/TestCuda.cpp
 create mode 100644 lib/kokkos/example/multi_fem/TestHost.cpp
 create mode 100644 lib/kokkos/example/multi_fem/TestHybridFEM.cpp
 create mode 100644 lib/kokkos/example/query_device/CMakeLists.txt
 create mode 100644 lib/kokkos/example/query_device/Makefile
 create mode 100644 lib/kokkos/example/query_device/query_device.cpp
 create mode 100644 lib/kokkos/example/sort_array/CMakeLists.txt
 create mode 100644 lib/kokkos/example/sort_array/Makefile
 create mode 100644 lib/kokkos/example/sort_array/main.cpp
 create mode 100644 lib/kokkos/example/sort_array/sort_array.hpp
 create mode 100644 lib/kokkos/example/tutorial/01_hello_world/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/01_hello_world/Makefile
 create mode 100644 lib/kokkos/example/tutorial/01_hello_world/hello_world.cpp
 create mode 100644 lib/kokkos/example/tutorial/01_hello_world_lambda/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/01_hello_world_lambda/Makefile
 create mode 100644 lib/kokkos/example/tutorial/01_hello_world_lambda/hello_world_lambda.cpp
 create mode 100644 lib/kokkos/example/tutorial/02_simple_reduce/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/02_simple_reduce/Makefile
 create mode 100644 lib/kokkos/example/tutorial/02_simple_reduce/simple_reduce.cpp
 create mode 100644 lib/kokkos/example/tutorial/02_simple_reduce_lambda/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/02_simple_reduce_lambda/Makefile
 create mode 100644 lib/kokkos/example/tutorial/02_simple_reduce_lambda/simple_reduce_lambda.cpp
 create mode 100644 lib/kokkos/example/tutorial/03_simple_view/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/03_simple_view/Makefile
 create mode 100644 lib/kokkos/example/tutorial/03_simple_view/simple_view.cpp
 create mode 100644 lib/kokkos/example/tutorial/03_simple_view_lambda/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/03_simple_view_lambda/Makefile
 create mode 100644 lib/kokkos/example/tutorial/03_simple_view_lambda/simple_view_lambda.cpp
 create mode 100644 lib/kokkos/example/tutorial/04_simple_memoryspaces/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/04_simple_memoryspaces/Makefile
 create mode 100644 lib/kokkos/example/tutorial/04_simple_memoryspaces/simple_memoryspaces.cpp
 create mode 100644 lib/kokkos/example/tutorial/05_simple_atomics/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/05_simple_atomics/Makefile
 create mode 100644 lib/kokkos/example/tutorial/05_simple_atomics/simple_atomics.cpp
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/data_layouts.cpp
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/memory_traits.cpp
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/03_subviews/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/03_subviews/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/03_subviews/subviews.cpp
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/dual_view.cpp
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/uvm_example.cpp
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/06_AtomicViews/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/07_Overlapping_DeepCopy/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/07_Overlapping_DeepCopy/overlapping_deepcopy.cpp
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Advanced_Views/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Algorithms/01_random_numbers/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Algorithms/01_random_numbers/random_numbers.cpp
 create mode 100644 lib/kokkos/example/tutorial/Algorithms/Makefile
 create mode 100644 lib/kokkos/example/tutorial/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/thread_teams.cpp
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/thread_teams_lambda.cpp
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/nested_parallel_for.cpp
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/vectorization.cpp
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/team_scan.cpp
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/CMakeLists.txt
 create mode 100644 lib/kokkos/example/tutorial/Hierarchical_Parallelism/Makefile
 create mode 100644 lib/kokkos/example/tutorial/Makefile
 create mode 100644 lib/kokkos/example/tutorial/README
 create mode 100755 lib/kokkos/generate_makefile.bash
 create mode 100644 lib/kokkos/tpls/gtest/gtest/LICENSE
 create mode 100644 lib/kokkos/tpls/gtest/gtest/README
 create mode 100644 lib/kokkos/tpls/gtest/gtest/gtest-all.cc
 create mode 120000 lib/kokkos/tpls/gtest/gtest/gtest-test-part.h
 create mode 100644 lib/kokkos/tpls/gtest/gtest/gtest.h

diff --git a/lib/kokkos/.gitignore b/lib/kokkos/.gitignore
new file mode 100644
index 0000000000..f9d16be155
--- /dev/null
+++ b/lib/kokkos/.gitignore
@@ -0,0 +1,8 @@
+# Standard ignores
+*~
+*.pyc
+\#*#
+.#*
+.*.swp
+.cproject
+.project
diff --git a/lib/kokkos/CMakeLists.txt b/lib/kokkos/CMakeLists.txt
new file mode 100644
index 0000000000..1219352f73
--- /dev/null
+++ b/lib/kokkos/CMakeLists.txt
@@ -0,0 +1,184 @@
+
+IF(COMMAND TRIBITS_PACKAGE_DECL)
+  SET(KOKKOS_HAS_TRILINOS ON CACHE BOOL "")
+ELSE()
+  SET(KOKKOS_HAS_TRILINOS OFF CACHE BOOL "")
+ENDIF()
+
+IF(NOT KOKKOS_HAS_TRILINOS)
+  CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11 FATAL_ERROR)
+  INCLUDE(cmake/tribits.cmake)
+ENDIF()
+
+#
+# A) Forward delcare the package so that certain options are also defined for
+# subpackages
+#
+
+TRIBITS_PACKAGE_DECL(Kokkos) # ENABLE_SHADOWING_WARNINGS)
+
+#------------------------------------------------------------------------------
+#
+# B) Define the common options for Kokkos first so they can be used by
+# subpackages as well.
+#
+
+
+
+# mfh 01 Aug 2016: See Issue #61:
+#
+# https://github.com/kokkos/kokkos/issues/61
+#
+# Don't use TRIBITS_ADD_DEBUG_OPTION() here, because that defines
+# HAVE_KOKKOS_DEBUG.  We define KOKKOS_HAVE_DEBUG here instead,
+# for compatibility with Kokkos' Makefile build system.
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  ${PACKAGE_NAME}_ENABLE_DEBUG
+  ${PACKAGE_NAME_UC}_HAVE_DEBUG
+  "Enable run-time debug checks.  These checks may be expensive, so they are disabled by default in a release build."
+  ${${PROJECT_NAME}_ENABLE_DEBUG}
+)
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_SIERRA_BUILD
+  KOKKOS_FOR_SIERRA
+  "Configure Kokkos for building within the Sierra build system."
+  OFF
+  )
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_Cuda
+  KOKKOS_HAVE_CUDA
+  "Enable CUDA support in Kokkos."
+  "${TPL_ENABLE_CUDA}"
+  )
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_Cuda_UVM
+  KOKKOS_USE_CUDA_UVM
+  "Enable CUDA Unified Virtual Memory support in Kokkos."
+  OFF
+  )
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_Pthread
+  KOKKOS_HAVE_PTHREAD
+  "Enable Pthread support in Kokkos."
+  OFF
+  )
+
+ASSERT_DEFINED(TPL_ENABLE_Pthread)
+IF (Kokkos_ENABLE_Pthread AND NOT TPL_ENABLE_Pthread)
+  MESSAGE(FATAL_ERROR "You set Kokkos_ENABLE_Pthread=ON, but Trilinos' support for Pthread(s) is not enabled (TPL_ENABLE_Pthread=OFF).  This is not allowed.  Please enable Pthreads in Trilinos before attempting to enable Kokkos' support for Pthreads.")
+ENDIF ()
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_OpenMP
+  KOKKOS_HAVE_OPENMP
+  "Enable OpenMP support in Kokkos."
+  "${${PROJECT_NAME}_ENABLE_OpenMP}"
+  )
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_QTHREAD
+  KOKKOS_HAVE_QTHREAD
+  "Enable QTHREAD support in Kokkos."
+  "${TPL_ENABLE_QTHREAD}"
+  )
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_CXX11
+  KOKKOS_HAVE_CXX11
+  "Enable C++11 support in Kokkos."
+  "${${PROJECT_NAME}_ENABLE_CXX11}"
+  )
+  
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_HWLOC
+  KOKKOS_HAVE_HWLOC
+  "Enable HWLOC support in Kokkos."
+  "${TPL_ENABLE_HWLOC}"
+  )
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_MPI
+  KOKKOS_HAVE_MPI
+  "Enable MPI support in Kokkos."
+  "${TPL_ENABLE_MPI}"
+  )
+
+# Set default value of Kokkos_ENABLE_Debug_Bounds_Check option
+#
+# CMake is case sensitive.  The Kokkos_ENABLE_Debug_Bounds_Check
+# option (defined below) is annoyingly not all caps, but we need to
+# keep it that way for backwards compatibility.  If users forget and
+# try using an all-caps variable, then make it count by using the
+# all-caps version as the default value of the original, not-all-caps
+# option.  Otherwise, the default value of this option comes from
+# Kokkos_ENABLE_DEBUG (see Issue #367).
+
+ASSERT_DEFINED(${PACKAGE_NAME}_ENABLE_DEBUG)
+IF(DEFINED Kokkos_ENABLE_DEBUG_BOUNDS_CHECK)
+  IF(Kokkos_ENABLE_DEBUG_BOUNDS_CHECK)
+    SET(Kokkos_ENABLE_Debug_Bounds_Check_DEFAULT ON)
+  ELSE()
+    SET(Kokkos_ENABLE_Debug_Bounds_Check_DEFAULT "${${PACKAGE_NAME}_ENABLE_DEBUG}")
+  ENDIF()
+ELSE()
+  SET(Kokkos_ENABLE_Debug_Bounds_Check_DEFAULT "${${PACKAGE_NAME}_ENABLE_DEBUG}")
+ENDIF()
+ASSERT_DEFINED(Kokkos_ENABLE_Debug_Bounds_Check_DEFAULT)
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_Debug_Bounds_Check
+  KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
+  "Enable Kokkos::View run-time bounds checking."
+  "${Kokkos_ENABLE_Debug_Bounds_Check_DEFAULT}"
+  )
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_Profiling
+  KOKKOS_ENABLE_PROFILING_INTERNAL
+  "Enable KokkosP profiling support for kernel data collections."
+  "${TPL_ENABLE_DLlib}"
+  )
+
+# placeholder for future device...
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_Winthread
+  KOKKOS_HAVE_WINTHREAD
+  "Enable Winthread support in Kokkos."
+  "${TPL_ENABLE_Winthread}"
+  )
+
+# use new/old View
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_USING_DEPRECATED_VIEW
+  KOKKOS_USING_DEPRECATED_VIEW
+  "Choose whether to use the old, deprecated Kokkos::View"
+  OFF
+  )
+
+#------------------------------------------------------------------------------
+#
+# C) Process the subpackages for Kokkos
+#
+
+TRIBITS_PROCESS_SUBPACKAGES()
+
+#
+# D) If Kokkos itself is enabled, process the Kokkos package
+#
+
+TRIBITS_PACKAGE_DEF()
+
+TRIBITS_EXCLUDE_AUTOTOOLS_FILES()
+
+TRIBITS_EXCLUDE_FILES(
+  classic/doc
+  classic/LinAlg/doc/CrsRefactorNotesMay2012
+  )
+
+TRIBITS_PACKAGE_POSTPROCESS()
+
diff --git a/lib/kokkos/Copyright.txt b/lib/kokkos/Copyright.txt
new file mode 100644
index 0000000000..05980758fa
--- /dev/null
+++ b/lib/kokkos/Copyright.txt
@@ -0,0 +1,40 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
diff --git a/lib/kokkos/HOW_TO_SNAPSHOT b/lib/kokkos/HOW_TO_SNAPSHOT
new file mode 100644
index 0000000000..46bfb4167f
--- /dev/null
+++ b/lib/kokkos/HOW_TO_SNAPSHOT
@@ -0,0 +1,73 @@
+
+Developers of Kokkos (those who commit modifications to Kokkos)
+must maintain the snapshot of Kokkos in the Trilinos repository.
+
+This file contains instructions for how to
+snapshot Kokkos from github.com/kokkos to Trilinos.
+
+------------------------------------------------------------------------
+*** EVERYTHING GOES RIGHT WORKFLOW ***
+
+1) Given a 'git clone' of Kokkos and of Trilinos repositories.
+1.1) Let ${KOKKOS} be the absolute path to the Kokkos clone.
+     This path *must* terminate with the directory name 'kokkos';
+     e.g., ${HOME}/kokkos .
+1.2) Let ${TRILINOS} be the absolute path to the Trilinos directory.
+
+2) Given that the Kokkos build & test is clean and
+   changes are committed to the Kokkos clone.
+
+3) Snapshot the current commit in the Kokkos clone into the Trilinos clone.
+   This overwrites ${TRILINOS}/packages/kokkos with the content of ${KOKKOS}:
+	${KOKKOS}/config/snapshot.py --verbose ${KOKKOS} ${TRILINOS}/packages
+
+4) Verify the snapshot commit happened as expected
+	cd ${TRILINOS}/packages/kokkos
+	git log -1 --name-only
+
+5) Modify, build, and test Trilinos with the Kokkos snapshot.
+
+6) Given that that the Trilinos build & test is clean and
+   changes are committed to the Trilinos clone.
+
+7) Attempt push to the Kokkos repository.
+   If push fails then you must 'remove the Kokkos snapshot'
+   from your Trilinos clone.
+   See below.
+
+8) Attempt to push to the Trilinos repository.
+   If updating for a failed push requires you to change Kokkos you must
+   'remove the Kokkos snapshot' from your Trilinos clone.
+   See below.
+
+------------------------------------------------------------------------
+*** WHEN SOMETHING GOES WRONG AND YOU MUST              ***
+*** REMOVE THE KOKKOS SNAPSHOT FROM YOUR TRILINOS CLONE ***
+
+1) Query the Trilinos clone commit log.
+	git log --oneline
+
+2) Note the <SHA1> of the commit to the Trillinos clone
+   immediately BEFORE the Kokkos snapshot commit.
+   Copy this <SHA1> for use in the next command.
+
+3) IF more than one outstanding commit then you can remove just the
+   Kokkos snapshot commit with 'git rebase -i'.  Edit the rebase file.
+   Remove or comment out the Kokkos snapshot commit entry.
+	git rebase -i <SHA1>
+
+4) IF the Kokkos snapshot commit is the one and only
+   outstanding commit then remove just than commit.
+	git reset --hard HEAD~1
+
+------------------------------------------------------------------------
+*** REGARDING 'snapshot.py' TOOL ***
+
+The 'snapshot.py' tool is developed and maintained by the
+Center for Computing Research (CCR)
+Software Engineering, Maintenance, and Support (SEMS) team.
+
+Contact Brent Perschbacher <bmpersc@sandia.gov> for questions>
+
+------------------------------------------------------------------------
+
diff --git a/lib/kokkos/LICENSE b/lib/kokkos/LICENSE
new file mode 100644
index 0000000000..05980758fa
--- /dev/null
+++ b/lib/kokkos/LICENSE
@@ -0,0 +1,40 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
diff --git a/lib/kokkos/Makefile.kokkos b/lib/kokkos/Makefile.kokkos
new file mode 100644
index 0000000000..c9b6cc464d
--- /dev/null
+++ b/lib/kokkos/Makefile.kokkos
@@ -0,0 +1,480 @@
+# Default settings common options
+
+#LAMMPS specific settings:
+KOKKOS_PATH=../../lib/kokkos
+CXXFLAGS=$(CCFLAGS)
+
+#Options: OpenMP,Serial,Pthreads,Cuda
+KOKKOS_DEVICES ?= "OpenMP"
+#KOKKOS_DEVICES ?= "Pthreads"
+#Options: KNC,SNB,HSW,Kepler,Kepler30,Kepler32,Kepler35,Kepler37,Maxwell,Maxwell50,Maxwell52,Maxwell53,Pascal61,ARMv8,BGQ,Power7,Power8,KNL,BDW
+KOKKOS_ARCH ?= ""
+#Options: yes,no
+KOKKOS_DEBUG ?= "no"
+#Options: hwloc,librt,experimental_memkind
+KOKKOS_USE_TPLS ?= ""
+#Options: c++11
+KOKKOS_CXX_STANDARD ?= "c++11"
+#Options: aggressive_vectorization,disable_profiling
+KOKKOS_OPTIONS ?= ""
+
+#Default settings specific options
+#Options: force_uvm,use_ldg,rdc,enable_lambda
+KOKKOS_CUDA_OPTIONS ?= ""
+
+# Check for general settings
+
+KOKKOS_INTERNAL_ENABLE_DEBUG := $(strip $(shell echo $(KOKKOS_DEBUG) | grep "yes" | wc -l))
+KOKKOS_INTERNAL_ENABLE_CXX11 := $(strip $(shell echo $(KOKKOS_CXX_STANDARD) | grep "c++11" | wc -l))
+
+# Check for external libraries
+KOKKOS_INTERNAL_USE_HWLOC := $(strip $(shell echo $(KOKKOS_USE_TPLS) | grep "hwloc" | wc -l))
+KOKKOS_INTERNAL_USE_LIBRT := $(strip $(shell echo $(KOKKOS_USE_TPLS) | grep "librt" | wc -l))
+KOKKOS_INTERNAL_USE_MEMKIND := $(strip $(shell echo $(KOKKOS_USE_TPLS) | grep "experimental_memkind" | wc -l))
+
+# Check for advanced settings
+KOKKOS_INTERNAL_OPT_RANGE_AGGRESSIVE_VECTORIZATION := $(strip $(shell echo $(KOKKOS_OPTIONS) | grep "aggressive_vectorization" | wc -l))
+KOKKOS_INTERNAL_DISABLE_PROFILING := $(strip $(shell echo $(KOKKOS_OPTIONS) | grep "disable_profiling" | wc -l))
+KOKKOS_INTERNAL_CUDA_USE_LDG := $(strip $(shell echo $(KOKKOS_CUDA_OPTIONS) | grep "use_ldg" | wc -l))
+KOKKOS_INTERNAL_CUDA_USE_UVM := $(strip $(shell echo $(KOKKOS_CUDA_OPTIONS) | grep "force_uvm" | wc -l))
+KOKKOS_INTERNAL_CUDA_USE_RELOC := $(strip $(shell echo $(KOKKOS_CUDA_OPTIONS) | grep "rdc" | wc -l))
+KOKKOS_INTERNAL_CUDA_USE_LAMBDA := $(strip $(shell echo $(KOKKOS_CUDA_OPTIONS) | grep "enable_lambda" | wc -l))
+
+# Check for Kokkos Host Execution Spaces one of which must be on
+
+KOKKOS_INTERNAL_USE_OPENMP := $(strip $(shell echo $(KOKKOS_DEVICES) | grep OpenMP | wc -l))
+KOKKOS_INTERNAL_USE_PTHREADS := $(strip $(shell echo $(KOKKOS_DEVICES) | grep Pthread | wc -l))
+KOKKOS_INTERNAL_USE_SERIAL := $(strip $(shell echo $(KOKKOS_DEVICES) | grep Serial | wc -l))
+KOKKOS_INTERNAL_USE_QTHREAD := $(strip $(shell echo $(KOKKOS_DEVICES) | grep Qthread | wc -l))
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 0)
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 0)
+	KOKKOS_INTERNAL_USE_SERIAL := 1
+endif
+endif
+
+KOKKOS_INTERNAL_COMPILER_INTEL := $(shell $(CXX) --version        2>&1 | grep "Intel Corporation" | wc -l)
+KOKKOS_INTERNAL_COMPILER_PGI   := $(shell $(CXX) --version        2>&1 | grep PGI   | wc -l)
+KOKKOS_INTERNAL_COMPILER_XL    := $(shell $(CXX) -qversion        2>&1 | grep XL    | wc -l)
+KOKKOS_INTERNAL_COMPILER_CRAY  := $(shell $(CXX) -craype-verbose  2>&1 | grep "CC-" | wc -l)
+KOKKOS_INTERNAL_OS_CYGWIN      := $(shell uname | grep CYGWIN | wc -l)
+
+ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
+  KOKKOS_INTERNAL_OPENMP_FLAG := -mp 
+else
+  ifeq ($(KOKKOS_INTERNAL_COMPILER_XL), 1)
+    KOKKOS_INTERNAL_OPENMP_FLAG := -qsmp=omp
+  else
+    ifeq ($(KOKKOS_INTERNAL_COMPILER_CRAY), 1)
+      # OpenMP is turned on by default in Cray compiler environment
+      KOKKOS_INTERNAL_OPENMP_FLAG :=
+    else
+      KOKKOS_INTERNAL_OPENMP_FLAG := -fopenmp
+    endif
+  endif
+endif
+
+ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
+  KOKKOS_INTERNAL_CXX11_FLAG := --c++11
+else
+  ifeq ($(KOKKOS_INTERNAL_COMPILER_XL), 1)
+     KOKKOS_INTERNAL_CXX11_FLAG := -std=c++11
+  else
+    ifeq ($(KOKKOS_INTERNAL_COMPILER_CRAY), 1)
+      KOKKOS_INTERNAL_CXX11_FLAG := -hstd=c++11
+    else
+      KOKKOS_INTERNAL_CXX11_FLAG := --std=c++11
+    endif
+  endif
+endif
+
+# Check for other Execution Spaces
+KOKKOS_INTERNAL_USE_CUDA := $(strip $(shell echo $(KOKKOS_DEVICES) | grep Cuda | wc -l))
+
+# Check for Kokkos Architecture settings
+
+#Intel based
+KOKKOS_INTERNAL_USE_ARCH_KNC := $(strip $(shell echo $(KOKKOS_ARCH) | grep KNC | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_SNB := $(strip $(shell echo $(KOKKOS_ARCH) | grep SNB | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_HSW := $(strip $(shell echo $(KOKKOS_ARCH) | grep HSW | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_BDW := $(strip $(shell echo $(KOKKOS_ARCH) | grep BDW | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_KNL := $(strip $(shell echo $(KOKKOS_ARCH) | grep KNL | wc -l))
+
+#NVIDIA based
+NVCC_WRAPPER :=  $(KOKKOS_PATH)/config/nvcc_wrapper
+KOKKOS_INTERNAL_USE_ARCH_KEPLER30 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Kepler30 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_KEPLER32 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Kepler32 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_KEPLER35 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Kepler35 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_KEPLER37 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Kepler37 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_MAXWELL50 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Maxwell50 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_MAXWELL52 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Maxwell52 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_MAXWELL53 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Maxwell53 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_PASCAL61 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Pascal61 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_NVIDIA := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_KEPLER30)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_KEPLER32)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_KEPLER35)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_KEPLER37)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_PASCAL61)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_MAXWELL50) \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_MAXWELL52) \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_MAXWELL53) | bc))
+
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_NVIDIA), 0)
+KOKKOS_INTERNAL_USE_ARCH_MAXWELL50 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Maxwell | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_KEPLER35 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Kepler | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_NVIDIA := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_KEPLER30)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_KEPLER32)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_KEPLER35)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_KEPLER37)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_PASCAL61)  \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_MAXWELL50) \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_MAXWELL52) \
+                                                      + $(KOKKOS_INTERNAL_USE_ARCH_MAXWELL53) | bc))
+endif
+
+#ARM based
+KOKKOS_INTERNAL_USE_ARCH_ARMV80 := $(strip $(shell echo $(KOKKOS_ARCH) | grep ARMv8 | wc -l))
+
+#IBM based
+KOKKOS_INTERNAL_USE_ARCH_BGQ := $(strip $(shell echo $(KOKKOS_ARCH) | grep BGQ | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_POWER7 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Power7 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_POWER8 := $(strip $(shell echo $(KOKKOS_ARCH) | grep Power8 | wc -l))
+KOKKOS_INTERNAL_USE_ARCH_IBM := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_BGQ)+$(KOKKOS_INTERNAL_USE_ARCH_POWER7)+$(KOKKOS_INTERNAL_USE_ARCH_POWER8) | bc))
+
+#AMD based
+KOKKOS_INTERNAL_USE_ARCH_AMDAVX := $(strip $(shell echo $(KOKKOS_ARCH) | grep AMDAVX | wc -l))
+
+#Any AVX?
+KOKKOS_INTERNAL_USE_ARCH_AVX       := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_SNB)+$(KOKKOS_INTERNAL_USE_ARCH_AMDAVX) | bc ))
+KOKKOS_INTERNAL_USE_ARCH_AVX2      := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_HSW)+$(KOKKOS_INTERNAL_USE_ARCH_BDW) | bc ))
+KOKKOS_INTERNAL_USE_ARCH_AVX512MIC := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_KNL) | bc ))
+
+# Decide what ISA level we are able to support
+KOKKOS_INTERNAL_USE_ISA_X86_64     := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_SNB)+$(KOKKOS_INTERNAL_USE_ARCH_HSW)+$(KOKKOS_INTERNAL_USE_ARCH_BDW)+$(KOKKOS_INTERNAL_USE_ARCH_KNL) | bc ))
+KOKKOS_INTERNAL_USE_ISA_KNC        := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_KNC) | bc ))
+KOKKOS_INTERNAL_USE_ISA_POWERPCLE  := $(strip $(shell echo $(KOKKOS_INTERNAL_USE_ARCH_POWER8) | bc ))
+
+#Incompatible flags?
+KOKKOS_INTERNAL_USE_ARCH_MULTIHOST := $(strip $(shell echo "$(KOKKOS_INTERNAL_USE_ARCH_AVX)+$(KOKKOS_INTERNAL_USE_ARCH_AVX2)+$(KOKKOS_INTERNAL_USE_ARCH_KNC)+$(KOKKOS_INTERNAL_USE_ARCH_IBM)+$(KOKKOS_INTERNAL_USE_ARCH_AMDAVX)+$(KOKKOS_INTERNAL_USE_ARCH_ARMV80)>1" | bc ))
+KOKKOS_INTERNAL_USE_ARCH_MULTIGPU := $(strip $(shell echo "$(KOKKOS_INTERNAL_USE_ARCH_NVIDIA)>1" | bc))
+
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_MULTIHOST), 1)
+  $(error Defined Multiple Host architectures: KOKKOS_ARCH=$(KOKKOS_ARCH) )
+endif
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_MULTIGPU), 1)
+  $(error Defined Multiple GPU architectures: KOKKOS_ARCH=$(KOKKOS_ARCH) )
+endif
+
+#Generating the list of Flags
+
+KOKKOS_CPPFLAGS = -I./ -I$(KOKKOS_PATH)/core/src -I$(KOKKOS_PATH)/containers/src -I$(KOKKOS_PATH)/algorithms/src
+
+# No warnings:
+KOKKOS_CXXFLAGS =
+# INTEL and CLANG warnings:
+#KOKKOS_CXXFLAGS = -Wall -Wshadow -pedantic -Wsign-compare -Wtype-limits -Wuninitialized
+# GCC warnings:
+#KOKKOS_CXXFLAGS = -Wall -Wshadow -pedantic -Wsign-compare -Wtype-limits -Wuninitialized -Wignored-qualifiers -Wempty-body -Wclobbered
+
+KOKKOS_LIBS = -lkokkos -ldl
+KOKKOS_LDFLAGS = -L$(shell pwd)
+KOKKOS_SRC = 
+KOKKOS_HEADERS =
+
+#Generating the KokkosCore_config.h file
+
+tmp := $(shell echo "/* ---------------------------------------------" > KokkosCore_config.tmp)
+tmp := $(shell echo "Makefile constructed configuration:" >> KokkosCore_config.tmp)
+tmp := $(shell date >> KokkosCore_config.tmp)
+tmp := $(shell echo "----------------------------------------------*/" >> KokkosCore_config.tmp)
+
+
+tmp := $(shell echo "/* Execution Spaces */" >> KokkosCore_config.tmp)
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+	tmp := $(shell echo '\#define KOKKOS_HAVE_OPENMP 1' >> KokkosCore_config.tmp) 
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+	tmp := $(shell echo "\#define KOKKOS_HAVE_PTHREAD 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_SERIAL), 1)
+	tmp := $(shell echo "\#define KOKKOS_HAVE_SERIAL 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	tmp := $(shell echo "\#define KOKKOS_HAVE_CUDA 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_ISA_X86_64), 1)
+  	tmp := $(shell echo "\#define KOKKOS_USE_ISA_X86_64" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_ISA_KNC), 1)
+  	tmp := $(shell echo "\#define KOKKOS_USE_ISA_KNC" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_ISA_POWERPCLE), 1)
+  	tmp := $(shell echo "\#define KOKKOS_USE_ISA_POWERPCLE" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_QTHREAD), 1)
+	KOKKOS_CPPFLAGS += -I$(QTHREAD_PATH)/include
+	KOKKOS_LDFLAGS += -L$(QTHREAD_PATH)/lib 
+	tmp := $(shell echo "\#define KOKKOS_HAVE_QTHREAD 1" >> KokkosCore_config.tmp )
+endif
+
+tmp := $(shell echo "/* General Settings */" >> KokkosCore_config.tmp)
+ifeq ($(KOKKOS_INTERNAL_ENABLE_CXX11), 1)
+	KOKKOS_CXXFLAGS += $(KOKKOS_INTERNAL_CXX11_FLAG)
+	tmp := $(shell echo "\#define KOKKOS_HAVE_CXX11 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_ENABLE_DEBUG), 1)
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	KOKKOS_CXXFLAGS += -G
+endif
+	KOKKOS_CXXFLAGS += -g 
+	KOKKOS_LDFLAGS += -g -ldl
+	tmp := $(shell echo "\#define KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK 1" >> KokkosCore_config.tmp )
+	tmp := $(shell echo "\#define KOKKOS_HAVE_DEBUG 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_HWLOC), 1)
+	KOKKOS_CPPFLAGS += -I$(HWLOC_PATH)/include
+	KOKKOS_LDFLAGS += -L$(HWLOC_PATH)/lib 
+        KOKKOS_LIBS += -lhwloc
+	tmp := $(shell echo "\#define KOKKOS_HAVE_HWLOC 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_LIBRT), 1)
+	tmp := $(shell echo "\#define KOKKOS_USE_LIBRT 1" >> KokkosCore_config.tmp )
+	tmp := $(shell echo "\#define PREC_TIMER 1" >> KokkosCore_config.tmp )
+  tmp := $(shell echo "\#define KOKKOSP_ENABLE_RTLIB 1" >> KokkosCore_config.tmp )
+	KOKKOS_LIBS += -lrt
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_MEMKIND), 1)
+  KOKKOS_CPPFLAGS += -I$(MEMKIND_PATH)/include
+  KOKKOS_LDFLAGS += -L$(MEMKIND_PATH)/lib 
+        KOKKOS_LIBS += -lmemkind
+  tmp := $(shell echo "\#define KOKKOS_HAVE_HBWSPACE 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_DISABLE_PROFILING), 1)
+  tmp := $(shell echo "\#define KOKKOS_ENABLE_PROFILING 0" >> KokkosCore_config.tmp )
+endif
+
+tmp := $(shell echo "/* Optimization Settings */" >> KokkosCore_config.tmp)
+
+ifeq ($(KOKKOS_INTERNAL_OPT_RANGE_AGGRESSIVE_VECTORIZATION), 1)
+  tmp := $(shell echo "\#define KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION 1" >> KokkosCore_config.tmp )
+endif
+
+tmp := $(shell echo "/* Cuda Settings */" >> KokkosCore_config.tmp)
+
+ifeq ($(KOKKOS_INTERNAL_CUDA_USE_LDG), 1)
+	tmp := $(shell echo "\#define KOKKOS_CUDA_USE_LDG_INTRINSIC 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_CUDA_USE_UVM), 1)
+	tmp := $(shell echo "\#define KOKKOS_CUDA_USE_UVM 1" >> KokkosCore_config.tmp )
+  tmp := $(shell echo "\#define KOKKOS_USE_CUDA_UVM 1" >> KokkosCore_config.tmp )
+endif
+
+ifeq ($(KOKKOS_INTERNAL_CUDA_USE_RELOC), 1)
+	tmp := $(shell echo "\#define KOKKOS_CUDA_USE_RELOCATABLE_DEVICE_CODE 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += --relocatable-device-code=true
+	KOKKOS_LDFLAGS += --relocatable-device-code=true
+endif
+
+ifeq ($(KOKKOS_INTERNAL_CUDA_USE_LAMBDA), 1)
+  tmp := $(shell echo "\#define KOKKOS_CUDA_USE_LAMBDA 1" >> KokkosCore_config.tmp )
+  KOKKOS_CXXFLAGS += -expt-extended-lambda
+endif
+
+#Add Architecture flags
+
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_AVX), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_AVX 1" >> KokkosCore_config.tmp )
+    ifeq ($(KOKKOS_INTERNAL_COMPILER_CRAY), 1)
+	KOKKOS_CXXFLAGS +=
+	KOKKOS_LDFLAGS +=
+    else	
+	KOKKOS_CXXFLAGS += -mavx
+	KOKKOS_LDFLAGS += -mavx
+    endif
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_POWER8), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_POWER8 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -mcpu=power8 -mtune=power8
+	KOKKOS_LDFLAGS  += -mcpu=power8 -mtune=power8
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_AVX2), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_AVX2 1" >> KokkosCore_config.tmp )
+	ifeq ($(KOKKOS_INTERNAL_COMPILER_INTEL), 1)
+		KOKKOS_CXXFLAGS += -xCORE-AVX2
+		KOKKOS_LDFLAGS  += -xCORE-AVX2
+	else
+		ifeq ($(KOKKOS_INTERNAL_COMPILER_CRAY), 1)
+
+		else
+			ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1) 
+
+			else
+				# Assume that this is a really a GNU compiler
+				KOKKOS_CXXFLAGS += -march=core-avx2 -mtune=core-avx2
+				KOKKOS_LDFLAGS  += -march=core-avx2 -mtune=core-avx2
+			endif
+		endif
+	endif
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_AVX512MIC), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_AVX512MIC 1" >> KokkosCore_config.tmp )
+	ifeq ($(KOKKOS_INTERNAL_COMPILER_INTEL), 1)
+		KOKKOS_CXXFLAGS += -xMIC-AVX512
+		KOKKOS_LDFLAGS  += -xMIC-AVX512
+	else
+		ifeq ($(KOKKOS_INTERNAL_COMPILER_CRAY), 1)
+
+		else
+			ifeq ($(KOKKOS_INTERNAL_COMPILER_PGI), 1)
+
+			else
+				# Asssume that this is really a GNU compiler
+				KOKKOS_CXXFLAGS += -march=knl
+				KOKKOS_LDFLAGS  += -march=knl
+			endif
+		endif
+	endif
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_KNC), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KNC 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -mmic
+	KOKKOS_LDFLAGS += -mmic
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_KEPLER30), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KEPLER 1" >> KokkosCore_config.tmp )
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KEPLER30 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -arch=sm_30
+endif
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_KEPLER32), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KEPLER 1" >> KokkosCore_config.tmp )
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KEPLER32 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -arch=sm_32
+endif
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_KEPLER35), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KEPLER 1" >> KokkosCore_config.tmp )
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KEPLER35 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -arch=sm_35
+endif
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_KEPLER37), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KEPLER 1" >> KokkosCore_config.tmp )
+    tmp := $(shell echo "\#define KOKKOS_ARCH_KEPLER37 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -arch=sm_37
+endif
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_MAXWELL50), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_MAXWELL 1" >> KokkosCore_config.tmp )
+    tmp := $(shell echo "\#define KOKKOS_ARCH_MAXWELL50 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -arch=sm_50
+endif
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_MAXWELL52), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_MAXWELL 1" >> KokkosCore_config.tmp )
+    tmp := $(shell echo "\#define KOKKOS_ARCH_MAXWELL52 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -arch=sm_52
+endif
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_MAXWELL53), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_MAXWELL 1" >> KokkosCore_config.tmp )
+    tmp := $(shell echo "\#define KOKKOS_ARCH_MAXWELL53 1" >> KokkosCore_config.tmp )
+	KOKKOS_CXXFLAGS += -arch=sm_53
+endif
+ifeq ($(KOKKOS_INTERNAL_USE_ARCH_PASCAL61), 1)
+    tmp := $(shell echo "\#define KOKKOS_ARCH_PASCAL 1" >> KokkosCore_config.tmp )
+    tmp := $(shell echo "\#define KOKKOS_ARCH_PASCAL61 1" >> KokkosCore_config.tmp )
+        KOKKOS_CXXFLAGS += -arch=sm_61
+endif
+endif
+ 
+KOKKOS_INTERNAL_LS_CONFIG := $(shell ls KokkosCore_config.h)
+ifeq ($(KOKKOS_INTERNAL_LS_CONFIG), KokkosCore_config.h)
+KOKKOS_INTERNAL_NEW_CONFIG := $(strip $(shell diff KokkosCore_config.h KokkosCore_config.tmp | grep define | wc -l))
+else
+KOKKOS_INTERNAL_NEW_CONFIG := 1
+endif
+
+ifneq ($(KOKKOS_INTERNAL_NEW_CONFIG), 0)
+	tmp := $(shell cp KokkosCore_config.tmp KokkosCore_config.h)
+endif
+
+KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/*.hpp)
+KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/impl/*.hpp)
+KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/containers/src/*.hpp)
+KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/containers/src/impl/*.hpp)
+KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/algorithms/src/*.hpp)
+
+KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/impl/*.cpp)
+KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/containers/src/impl/*.cpp)
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/Cuda/*.cpp)
+	KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/Cuda/*.hpp)
+	KOKKOS_LDFLAGS += -L$(CUDA_PATH)/lib64 
+	KOKKOS_LIBS += -lcudart -lcuda
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+	KOKKOS_LIBS += -lpthread
+	KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.cpp)
+	KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.hpp)
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_QTHREAD), 1)
+	KOKKOS_LIBS += -lqthread
+	KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/Qthread/*.cpp)
+	KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/Qthread/*.hpp)
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+	KOKKOS_SRC += $(wildcard $(KOKKOS_PATH)/core/src/OpenMP/*.cpp)
+	KOKKOS_HEADERS += $(wildcard $(KOKKOS_PATH)/core/src/OpenMP/*.hpp)
+	ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+		KOKKOS_CXXFLAGS += -Xcompiler $(KOKKOS_INTERNAL_OPENMP_FLAG)
+	else
+		KOKKOS_CXXFLAGS += $(KOKKOS_INTERNAL_OPENMP_FLAG)
+	endif
+	KOKKOS_LDFLAGS += $(KOKKOS_INTERNAL_OPENMP_FLAG)
+endif
+
+#With Cygwin functions such as fdopen and fileno are not defined 
+#when strict ansi is enabled. strict ansi gets enabled with --std=c++11
+#though. So we hard undefine it here. Not sure if that has any bad side effects
+#This is needed for gtest actually, not for Kokkos itself!
+ifeq ($(KOKKOS_INTERNAL_OS_CYGWIN), 1)
+  KOKKOS_CXXFLAGS += -U__STRICT_ANSI__
+endif
+
+# Setting up dependencies
+
+KokkosCore_config.h:
+
+KOKKOS_CPP_DEPENDS := KokkosCore_config.h $(KOKKOS_HEADERS)
+
+KOKKOS_OBJ = $(KOKKOS_SRC:.cpp=.o)
+KOKKOS_OBJ_LINK = $(notdir $(KOKKOS_OBJ))
+
+include $(KOKKOS_PATH)/Makefile.targets
+
+kokkos-clean:
+	rm -f $(KOKKOS_OBJ_LINK) KokkosCore_config.h KokkosCore_config.tmp libkokkos.a
+
+libkokkos.a: $(KOKKOS_OBJ_LINK) $(KOKKOS_SRC) $(KOKKOS_HEADERS)
+	ar cr libkokkos.a $(KOKKOS_OBJ_LINK)
+	ranlib libkokkos.a
+
+KOKKOS_LINK_DEPENDS=libkokkos.a
diff --git a/lib/kokkos/Makefile.targets b/lib/kokkos/Makefile.targets
new file mode 100644
index 0000000000..86929ea0fe
--- /dev/null
+++ b/lib/kokkos/Makefile.targets
@@ -0,0 +1,72 @@
+Kokkos_UnorderedMap_impl.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/containers/src/impl/Kokkos_UnorderedMap_impl.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/containers/src/impl/Kokkos_UnorderedMap_impl.cpp
+Kokkos_Core.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_Core.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Core.cpp
+Kokkos_CPUDiscovery.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_CPUDiscovery.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_CPUDiscovery.cpp
+Kokkos_Error.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_Error.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Error.cpp
+Kokkos_ExecPolicy.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_ExecPolicy.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_ExecPolicy.cpp
+Kokkos_HostSpace.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_HostSpace.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_HostSpace.cpp
+Kokkos_hwloc.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_hwloc.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_hwloc.cpp
+Kokkos_Serial.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_Serial.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Serial.cpp
+Kokkos_Serial_TaskPolicy.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_Serial_TaskPolicy.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Serial_TaskPolicy.cpp
+Kokkos_TaskQueue.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_TaskQueue.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_TaskQueue.cpp
+Kokkos_Serial_Task.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_Serial_Task.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Serial_Task.cpp
+Kokkos_Shape.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_Shape.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Shape.cpp
+Kokkos_spinwait.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_spinwait.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_spinwait.cpp
+Kokkos_Profiling_Interface.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_Profiling_Interface.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_Profiling_Interface.cpp
+KokkosExp_SharedAlloc.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/KokkosExp_SharedAlloc.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/KokkosExp_SharedAlloc.cpp
+Kokkos_MemoryPool.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_MemoryPool.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_MemoryPool.cpp
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+Kokkos_Cuda_Impl.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Cuda/Kokkos_Cuda_Impl.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Cuda/Kokkos_Cuda_Impl.cpp
+Kokkos_CudaSpace.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Cuda/Kokkos_CudaSpace.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Cuda/Kokkos_CudaSpace.cpp
+Kokkos_Cuda_Task.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Cuda/Kokkos_Cuda_Task.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Cuda/Kokkos_Cuda_Task.cpp
+Kokkos_Cuda_TaskPolicy.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Cuda/Kokkos_Cuda_TaskPolicy.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Cuda/Kokkos_Cuda_TaskPolicy.cpp
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+Kokkos_ThreadsExec_base.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec_base.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec_base.cpp
+Kokkos_ThreadsExec.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Threads/Kokkos_ThreadsExec.cpp
+Kokkos_Threads_TaskPolicy.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Threads/Kokkos_Threads_TaskPolicy.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Threads/Kokkos_Threads_TaskPolicy.cpp
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_QTHREAD), 1)
+Kokkos_QthreadExec.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Qthread/Kokkos_QthreadExec.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Qthread/Kokkos_QthreadExec.cpp
+Kokkos_Qthread_TaskPolicy.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/Qthread/Kokkos_Qthread_TaskPolicy.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/Qthread/Kokkos_Qthread_TaskPolicy.cpp
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+Kokkos_OpenMPexec.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/OpenMP/Kokkos_OpenMPexec.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/OpenMP/Kokkos_OpenMPexec.cpp
+Kokkos_OpenMP_Task.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/OpenMP/Kokkos_OpenMP_Task.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/OpenMP/Kokkos_OpenMP_Task.cpp
+endif
+
+Kokkos_HBWSpace.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_HBWSpace.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_HBWSpace.cpp
+Kokkos_HBWAllocators.o: $(KOKKOS_CPP_DEPENDS) $(KOKKOS_PATH)/core/src/impl/Kokkos_HBWAllocators.cpp
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) -c $(KOKKOS_PATH)/core/src/impl/Kokkos_HBWAllocators.cpp
+
diff --git a/lib/kokkos/README b/lib/kokkos/README
new file mode 100644
index 0000000000..b094578af6
--- /dev/null
+++ b/lib/kokkos/README
@@ -0,0 +1,152 @@
+Kokkos implements a programming model in C++ for writing performance portable
+applications targeting all major HPC platforms. For that purpose it provides
+abstractions for both parallel execution of code and data management.
+Kokkos is designed to target complex node architectures with N-level memory
+hierarchies and multiple types of execution resources. It currently can use
+OpenMP, Pthreads and CUDA as backend programming models.
+
+The core developers of Kokkos are Carter Edwards and Christian Trott
+at the Computer Science Research Institute of the Sandia National
+Laboratories.
+
+The KokkosP interface and associated tools are developed by the Application
+Performance Team and Kokkos core developers at Sandia National Laboratories.
+
+To learn more about Kokkos consider watching one of our presentations:
+GTC 2015:
+  http://on-demand.gputechconf.com/gtc/2015/video/S5166.html
+  http://on-demand.gputechconf.com/gtc/2015/presentation/S5166-H-Carter-Edwards.pdf
+
+A programming guide can be found under doc/Kokkos_PG.pdf. This is an initial version
+and feedback is greatly appreciated.
+
+A separate repository with extensive tutorial material can be found under 
+https://github.com/kokkos/kokkos-tutorials.
+
+If you have a patch to contribute please feel free to issue a pull request against
+the develop branch. For major contributions it is better to contact us first
+for guidance.
+
+For questions please send an email to
+kokkos-users@software.sandia.gov
+
+For non-public questions send an email to
+hcedwar(at)sandia.gov and crtrott(at)sandia.gov
+
+============================================================================
+====Requirements============================================================
+============================================================================
+
+Primary tested compilers on X86 are:
+  GCC 4.7.2
+  GCC 4.8.4
+  GCC 4.9.2
+  GCC 5.1.0
+  Intel 14.0.4
+  Intel 15.0.2
+  Intel 16.0.1
+  Clang 3.5.2
+  Clang 3.6.1
+
+Primary tested compilers on Power 8 are:
+  IBM XL 13.1.3 (OpenMP,Serial)
+  GCC 4.9.2 (OpenMP,Serial)
+  GCC 5.3.0 (OpenMP,Serial)
+
+Secondary tested compilers are:
+  CUDA 6.5 (with gcc 4.7.2)
+  CUDA 7.0 (with gcc 4.7.2)
+  CUDA 7.5 (with gcc 4.8.4)
+
+Other compilers working:
+  X86:
+   Intel 17.0.042 (the FENL example causes internal compiler error)
+   PGI 15.4
+   Cygwin 2.1.0 64bit with gcc 4.9.3
+  KNL:
+   Intel 16.2.181 (the FENL example causes internal compiler error)
+   Intel 17.0.042 (the FENL example causes internal compiler error)
+
+Known non-working combinations:
+  Power8:
+   GCC 6.1.0
+   Pthreads backend
+
+
+Primary tested compiler are passing in release mode
+with warnings as errors. They also are tested with a comprehensive set of 
+backend combinations (i.e. OpenMP, Pthreads, Serial, OpenMP+Serial, ...).
+We are using the following set of flags:
+GCC:   -Wall -Wshadow -pedantic -Werror -Wsign-compare -Wtype-limits
+       -Wignored-qualifiers -Wempty-body -Wclobbered -Wuninitialized
+Intel: -Wall -Wshadow -pedantic -Werror -Wsign-compare -Wtype-limits -Wuninitialized
+Clang: -Wall -Wshadow -pedantic -Werror -Wsign-compare -Wtype-limits -Wuninitialized
+
+Secondary compilers are passing without -Werror.
+Other compilers are tested occasionally, in particular when pushing from develop to 
+master branch, without -Werror and only for a select set of backends.
+
+============================================================================
+====Getting started=========================================================
+============================================================================
+
+In the 'example/tutorial' directory you will find step by step tutorial
+examples which explain many of the features of Kokkos. They work with
+simple Makefiles. To build with g++ and OpenMP simply type 'make openmp'
+in the 'example/tutorial' directory. This will build all examples in the
+subfolders.
+
+============================================================================
+====Running Unit Tests======================================================
+============================================================================
+
+To run the unit tests create a build directory and run the following commands
+
+KOKKOS_PATH/generate_makefile.bash
+make build-test
+make test
+
+Run KOKKOS_PATH/generate_makefile.bash --help for more detailed options such as
+changing the device type for which to build.
+
+============================================================================
+====Install the library=====================================================
+============================================================================
+
+To install Kokkos as a library create a build directory and run the following
+
+KOKKOS_PATH/generate_makefile.bash --prefix=INSTALL_PATH
+make lib
+make install
+
+KOKKOS_PATH/generate_makefile.bash --help for more detailed options such as
+changing the device type for which to build.
+
+============================================================================
+====CMakeFiles==============================================================
+============================================================================
+
+The CMake files contained in this repository require Tribits and are used
+for integration with Trilinos. They do not currently support a standalone
+CMake build.
+
+===========================================================================
+====Kokkos and CUDA UVM====================================================
+===========================================================================
+
+Kokkos does support UVM as a specific memory space called CudaUVMSpace. 
+Allocations made with that space are accessible from host and device. 
+You can tell Kokkos to use that as the default space for Cuda allocations.
+In either case UVM comes with a number of restrictions:
+(i) You can't access allocations on the host while a kernel is potentially 
+running. This will lead to segfaults. To avoid that you either need to 
+call Kokkos::Cuda::fence() (or just Kokkos::fence()), after kernels, or
+you can set the environment variable CUDA_LAUNCH_BLOCKING=1.
+Furthermore in multi socket multi GPU machines, UVM defaults to using 
+zero copy allocations for technical reasons related to using multiple
+GPUs from the same process. If an executable doesn't do that (e.g. each
+MPI rank of an application uses a single GPU [can be the same GPU for 
+multiple MPI ranks]) you can set CUDA_MANAGED_FORCE_DEVICE_ALLOC=1.
+This will enforce proper UVM allocations, but can lead to errors if 
+more than a single GPU is used by a single process.
+ 
diff --git a/lib/kokkos/algorithms/CMakeLists.txt b/lib/kokkos/algorithms/CMakeLists.txt
new file mode 100644
index 0000000000..7853184a54
--- /dev/null
+++ b/lib/kokkos/algorithms/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+
+TRIBITS_SUBPACKAGE(Algorithms)
+
+ADD_SUBDIRECTORY(src)
+
+TRIBITS_ADD_TEST_DIRECTORIES(unit_tests)
+#TRIBITS_ADD_TEST_DIRECTORIES(performance_tests)
+
+TRIBITS_SUBPACKAGE_POSTPROCESS()
diff --git a/lib/kokkos/algorithms/cmake/Dependencies.cmake b/lib/kokkos/algorithms/cmake/Dependencies.cmake
new file mode 100644
index 0000000000..1d71d8af34
--- /dev/null
+++ b/lib/kokkos/algorithms/cmake/Dependencies.cmake
@@ -0,0 +1,5 @@
+TRIBITS_PACKAGE_DEFINE_DEPENDENCIES(
+  LIB_REQUIRED_PACKAGES KokkosCore
+  LIB_OPTIONAL_TPLS Pthread CUDA HWLOC
+  TEST_OPTIONAL_TPLS CUSPARSE
+  )
diff --git a/lib/kokkos/algorithms/cmake/KokkosAlgorithms_config.h.in b/lib/kokkos/algorithms/cmake/KokkosAlgorithms_config.h.in
new file mode 100644
index 0000000000..67334b70f3
--- /dev/null
+++ b/lib/kokkos/algorithms/cmake/KokkosAlgorithms_config.h.in
@@ -0,0 +1,4 @@
+#ifndef KOKKOS_ALGORITHMS_CONFIG_H
+#define KOKKOS_ALGORITHMS_CONFIG_H
+
+#endif
diff --git a/lib/kokkos/algorithms/src/CMakeLists.txt b/lib/kokkos/algorithms/src/CMakeLists.txt
new file mode 100644
index 0000000000..dfbf3323c2
--- /dev/null
+++ b/lib/kokkos/algorithms/src/CMakeLists.txt
@@ -0,0 +1,21 @@
+
+TRIBITS_CONFIGURE_FILE(${PACKAGE_NAME}_config.h)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+#-----------------------------------------------------------------------------
+
+FILE(GLOB HEADERS *.hpp)
+FILE(GLOB SOURCES *.cpp)
+LIST(APPEND HEADERS ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}_config.h)
+
+#-----------------------------------------------------------------------------
+
+TRIBITS_ADD_LIBRARY(
+    kokkosalgorithms
+    HEADERS ${HEADERS}
+    SOURCES ${SOURCES}
+    DEPLIBS
+    )
+
diff --git a/lib/kokkos/algorithms/src/KokkosAlgorithms_dummy.cpp b/lib/kokkos/algorithms/src/KokkosAlgorithms_dummy.cpp
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/lib/kokkos/algorithms/src/Kokkos_Random.hpp b/lib/kokkos/algorithms/src/Kokkos_Random.hpp
new file mode 100644
index 0000000000..d7c06dc14b
--- /dev/null
+++ b/lib/kokkos/algorithms/src/Kokkos_Random.hpp
@@ -0,0 +1,1751 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_RANDOM_HPP
+#define KOKKOS_RANDOM_HPP
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Complex.hpp>
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+
+/// \file Kokkos_Random.hpp
+/// \brief Pseudorandom number generators
+///
+/// These generators are based on Vigna, Sebastiano (2014). "An
+/// experimental exploration of Marsaglia's xorshift generators,
+/// scrambled."  See: http://arxiv.org/abs/1402.6246
+
+namespace Kokkos {
+
+  /*Template functions to get equidistributed random numbers from a generator for a specific Scalar type
+
+       template<class Generator,Scalar>
+       struct rand{
+
+         //Max value returned by draw(Generator& gen)
+         KOKKOS_INLINE_FUNCTION
+         static Scalar max();
+
+         //Returns a value between zero and max()
+         KOKKOS_INLINE_FUNCTION
+         static Scalar draw(Generator& gen);
+
+         //Returns a value between zero and range()
+         //Note: for floating point values range can be larger than max()
+         KOKKOS_INLINE_FUNCTION
+         static Scalar draw(Generator& gen, const Scalar& range){}
+
+         //Return value between start and end
+         KOKKOS_INLINE_FUNCTION
+         static Scalar draw(Generator& gen, const Scalar& start, const Scalar& end);
+      };
+
+    The Random number generators themselves have two components a state-pool and the actual generator
+    A state-pool manages a number of generators, so that each active thread is able to grep its own.
+    This allows the generation of random numbers which are independent between threads. Note that
+    in contrast to CuRand none of the functions of the pool (or the generator) are collectives,
+    i.e. all functions can be called inside conditionals.
+
+    template<class Device>
+    class Pool {
+     public:
+      //The Kokkos device type
+      typedef Device device_type;
+      //The actual generator type
+      typedef Generator<Device> generator_type;
+
+      //Default constructor: does not initialize a pool
+      Pool();
+
+      //Initializing constructor: calls init(seed,Device_Specific_Number);
+      Pool(unsigned int seed);
+
+      //Intialize Pool with seed as a starting seed with a pool_size of num_states
+      //The Random_XorShift64 generator is used in serial to initialize all states,
+      //thus the intialization process is platform independent and deterministic.
+      void init(unsigned int seed, int num_states);
+
+      //Get a generator. This will lock one of the states, guaranteeing that each thread
+      //will have its private generator. Note: on Cuda getting a state involves atomics,
+      //and is thus not deterministic!
+      generator_type get_state();
+
+      //Give a state back to the pool. This unlocks the state, and writes the modified
+      //state of the generator back to the pool.
+      void free_state(generator_type gen);
+
+    }
+
+    template<class Device>
+    class Generator {
+     public:
+     //The Kokkos device type
+    typedef DeviceType device_type;
+
+    //Max return values of respective [X]rand[S]() functions
+    enum {MAX_URAND = 0xffffffffU};
+    enum {MAX_URAND64 = 0xffffffffffffffffULL-1};
+    enum {MAX_RAND = static_cast<int>(0xffffffffU/2)};
+    enum {MAX_RAND64 = static_cast<int64_t>(0xffffffffffffffffULL/2-1)};
+
+
+    //Init with a state and the idx with respect to pool. Note: in serial the
+    //Generator can be used by just giving it the necessary state arguments
+    KOKKOS_INLINE_FUNCTION
+    Generator (STATE_ARGUMENTS, int state_idx = 0);
+
+    //Draw a equidistributed uint32_t in the range (0,MAX_URAND]
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand();
+
+    //Draw a equidistributed uint64_t in the range (0,MAX_URAND64]
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64();
+
+    //Draw a equidistributed uint32_t in the range (0,range]
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand(const uint32_t& range);
+
+    //Draw a equidistributed uint32_t in the range (start,end]
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand(const uint32_t& start, const uint32_t& end );
+
+    //Draw a equidistributed uint64_t in the range (0,range]
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64(const uint64_t& range);
+
+    //Draw a equidistributed uint64_t in the range (start,end]
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64(const uint64_t& start, const uint64_t& end );
+
+    //Draw a equidistributed int in the range (0,MAX_RAND]
+    KOKKOS_INLINE_FUNCTION
+    int rand();
+
+    //Draw a equidistributed int in the range (0,range]
+    KOKKOS_INLINE_FUNCTION
+    int rand(const int& range);
+
+    //Draw a equidistributed int in the range (start,end]
+    KOKKOS_INLINE_FUNCTION
+    int rand(const int& start, const int& end );
+
+    //Draw a equidistributed int64_t in the range (0,MAX_RAND64]
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64();
+
+    //Draw a equidistributed int64_t in the range (0,range]
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64(const int64_t& range);
+
+    //Draw a equidistributed int64_t in the range (start,end]
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64(const int64_t& start, const int64_t& end );
+
+    //Draw a equidistributed float in the range (0,1.0]
+    KOKKOS_INLINE_FUNCTION
+    float frand();
+
+    //Draw a equidistributed float in the range (0,range]
+    KOKKOS_INLINE_FUNCTION
+    float frand(const float& range);
+
+    //Draw a equidistributed float in the range (start,end]
+    KOKKOS_INLINE_FUNCTION
+    float frand(const float& start, const float& end );
+
+    //Draw a equidistributed double in the range (0,1.0]
+    KOKKOS_INLINE_FUNCTION
+    double drand();
+
+    //Draw a equidistributed double in the range (0,range]
+    KOKKOS_INLINE_FUNCTION
+    double drand(const double& range);
+
+    //Draw a equidistributed double in the range (start,end]
+    KOKKOS_INLINE_FUNCTION
+    double drand(const double& start, const double& end );
+
+    //Draw a standard normal distributed double
+    KOKKOS_INLINE_FUNCTION
+    double normal() ;
+
+    //Draw a normal distributed double with given mean and standard deviation
+    KOKKOS_INLINE_FUNCTION
+    double normal(const double& mean, const double& std_dev=1.0);
+    }
+
+    //Additional Functions:
+
+    //Fills view with random numbers in the range (0,range]
+    template<class ViewType, class PoolType>
+    void fill_random(ViewType view, PoolType pool, ViewType::value_type range);
+
+    //Fills view with random numbers in the range (start,end]
+    template<class ViewType, class PoolType>
+    void fill_random(ViewType view, PoolType pool,
+                     ViewType::value_type start, ViewType::value_type end);
+
+*/
+
+  template<class Generator, class Scalar>
+  struct rand;
+
+
+  template<class Generator>
+  struct rand<Generator,char> {
+
+    KOKKOS_INLINE_FUNCTION
+    static short max(){return 127;}
+    KOKKOS_INLINE_FUNCTION
+    static short draw(Generator& gen)
+                          {return short((gen.rand()&0xff+256)%256);}
+    KOKKOS_INLINE_FUNCTION
+    static short draw(Generator& gen, const char& range)
+                          {return char(gen.rand(range));}
+    KOKKOS_INLINE_FUNCTION
+    static short draw(Generator& gen, const char& start, const char& end)
+                          {return char(gen.rand(start,end));}
+
+  };
+
+  template<class Generator>
+  struct rand<Generator,short> {
+    KOKKOS_INLINE_FUNCTION
+    static short max(){return 32767;}
+    KOKKOS_INLINE_FUNCTION
+    static short draw(Generator& gen)
+                          {return short((gen.rand()&0xffff+65536)%32768);}
+    KOKKOS_INLINE_FUNCTION
+    static short draw(Generator& gen, const short& range)
+                          {return short(gen.rand(range));}
+    KOKKOS_INLINE_FUNCTION
+    static short draw(Generator& gen, const short& start, const short& end)
+                          {return short(gen.rand(start,end));}
+
+  };
+
+  template<class Generator>
+  struct rand<Generator,int> {
+    KOKKOS_INLINE_FUNCTION
+    static int max(){return Generator::MAX_RAND;}
+    KOKKOS_INLINE_FUNCTION
+    static int draw(Generator& gen)
+                          {return gen.rand();}
+    KOKKOS_INLINE_FUNCTION
+    static int draw(Generator& gen, const int& range)
+                          {return gen.rand(range);}
+    KOKKOS_INLINE_FUNCTION
+    static int draw(Generator& gen, const int& start, const int& end)
+                          {return gen.rand(start,end);}
+
+  };
+
+  template<class Generator>
+  struct rand<Generator,unsigned int> {
+    KOKKOS_INLINE_FUNCTION
+    static unsigned int max () {
+      return Generator::MAX_URAND;
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned int draw (Generator& gen) {
+      return gen.urand ();
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned int draw(Generator& gen, const unsigned int& range) {
+      return gen.urand (range);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned int
+    draw (Generator& gen, const unsigned int& start, const unsigned int& end) {
+      return gen.urand (start, end);
+    }
+  };
+
+  template<class Generator>
+  struct rand<Generator,long> {
+    KOKKOS_INLINE_FUNCTION
+    static long max () {
+      // FIXME (mfh 26 Oct 2014) It would be better to select the
+      // return value at compile time, using something like enable_if.
+      return sizeof (long) == 4 ?
+        static_cast<long> (Generator::MAX_RAND) :
+        static_cast<long> (Generator::MAX_RAND64);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static long draw (Generator& gen) {
+      // FIXME (mfh 26 Oct 2014) It would be better to select the
+      // return value at compile time, using something like enable_if.
+      return sizeof (long) == 4 ?
+        static_cast<long> (gen.rand ()) :
+        static_cast<long> (gen.rand64 ());
+    }
+    KOKKOS_INLINE_FUNCTION
+    static long draw (Generator& gen, const long& range) {
+      // FIXME (mfh 26 Oct 2014) It would be better to select the
+      // return value at compile time, using something like enable_if.
+      return sizeof (long) == 4 ?
+        static_cast<long> (gen.rand (static_cast<int> (range))) :
+        static_cast<long> (gen.rand64 (range));
+    }
+    KOKKOS_INLINE_FUNCTION
+    static long draw (Generator& gen, const long& start, const long& end) {
+      // FIXME (mfh 26 Oct 2014) It would be better to select the
+      // return value at compile time, using something like enable_if.
+      return sizeof (long) == 4 ?
+        static_cast<long> (gen.rand (static_cast<int> (start),
+                                     static_cast<int> (end))) :
+        static_cast<long> (gen.rand64 (start, end));
+    }
+  };
+
+  template<class Generator>
+  struct rand<Generator,unsigned long> {
+    KOKKOS_INLINE_FUNCTION
+    static unsigned long max () {
+      // FIXME (mfh 26 Oct 2014) It would be better to select the
+      // return value at compile time, using something like enable_if.
+      return sizeof (unsigned long) == 4 ?
+        static_cast<unsigned long> (Generator::MAX_URAND) :
+        static_cast<unsigned long> (Generator::MAX_URAND64);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned long draw (Generator& gen) {
+      // FIXME (mfh 26 Oct 2014) It would be better to select the
+      // return value at compile time, using something like enable_if.
+      return sizeof (unsigned long) == 4 ?
+        static_cast<unsigned long> (gen.urand ()) :
+        static_cast<unsigned long> (gen.urand64 ());
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned long draw(Generator& gen, const unsigned long& range) {
+      // FIXME (mfh 26 Oct 2014) It would be better to select the
+      // return value at compile time, using something like enable_if.
+      return sizeof (unsigned long) == 4 ?
+        static_cast<unsigned long> (gen.urand (static_cast<unsigned int> (range))) :
+        static_cast<unsigned long> (gen.urand64 (range));
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned long
+    draw (Generator& gen, const unsigned long& start, const unsigned long& end) {
+      // FIXME (mfh 26 Oct 2014) It would be better to select the
+      // return value at compile time, using something like enable_if.
+      return sizeof (unsigned long) == 4 ?
+        static_cast<unsigned long> (gen.urand (static_cast<unsigned int> (start),
+                                               static_cast<unsigned int> (end))) :
+        static_cast<unsigned long> (gen.urand64 (start, end));
+    }
+  };
+
+  // NOTE (mfh 26 oct 2014) This is a partial specialization for long
+  // long, a C99 / C++11 signed type which is guaranteed to be at
+  // least 64 bits.  Do NOT write a partial specialization for
+  // int64_t!!!  This is just a typedef!  It could be either long or
+  // long long.  We don't know which a priori, and I've seen both.
+  // The types long and long long are guaranteed to differ, so it's
+  // always safe to specialize for both.
+  template<class Generator>
+  struct rand<Generator, long long> {
+    KOKKOS_INLINE_FUNCTION
+    static long long max () {
+      // FIXME (mfh 26 Oct 2014) It's legal for long long to be > 64 bits.
+      return Generator::MAX_RAND64;
+    }
+    KOKKOS_INLINE_FUNCTION
+    static long long draw (Generator& gen) {
+      // FIXME (mfh 26 Oct 2014) It's legal for long long to be > 64 bits.
+      return gen.rand64 ();
+    }
+    KOKKOS_INLINE_FUNCTION
+    static long long draw (Generator& gen, const long long& range) {
+      // FIXME (mfh 26 Oct 2014) It's legal for long long to be > 64 bits.
+      return gen.rand64 (range);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static long long draw (Generator& gen, const long long& start, const long long& end) {
+      // FIXME (mfh 26 Oct 2014) It's legal for long long to be > 64 bits.
+      return gen.rand64 (start, end);
+    }
+  };
+
+  // NOTE (mfh 26 oct 2014) This is a partial specialization for
+  // unsigned long long, a C99 / C++11 unsigned type which is
+  // guaranteed to be at least 64 bits.  Do NOT write a partial
+  // specialization for uint64_t!!!  This is just a typedef!  It could
+  // be either unsigned long or unsigned long long.  We don't know
+  // which a priori, and I've seen both.  The types unsigned long and
+  // unsigned long long are guaranteed to differ, so it's always safe
+  // to specialize for both.
+  template<class Generator>
+  struct rand<Generator,unsigned long long> {
+    KOKKOS_INLINE_FUNCTION
+    static unsigned long long max () {
+      // FIXME (mfh 26 Oct 2014) It's legal for unsigned long long to be > 64 bits.
+      return Generator::MAX_URAND64;
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned long long draw (Generator& gen) {
+      // FIXME (mfh 26 Oct 2014) It's legal for unsigned long long to be > 64 bits.
+      return gen.urand64 ();
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned long long draw (Generator& gen, const unsigned long long& range) {
+      // FIXME (mfh 26 Oct 2014) It's legal for long long to be > 64 bits.
+      return gen.urand64 (range);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static unsigned long long
+    draw (Generator& gen, const unsigned long long& start, const unsigned long long& end) {
+      // FIXME (mfh 26 Oct 2014) It's legal for long long to be > 64 bits.
+      return gen.urand64 (start, end);
+    }
+  };
+
+  template<class Generator>
+  struct rand<Generator,float> {
+    KOKKOS_INLINE_FUNCTION
+    static float max(){return 1.0f;}
+    KOKKOS_INLINE_FUNCTION
+    static float draw(Generator& gen)
+                          {return gen.frand();}
+    KOKKOS_INLINE_FUNCTION
+    static float draw(Generator& gen, const float& range)
+                          {return gen.frand(range);}
+    KOKKOS_INLINE_FUNCTION
+    static float draw(Generator& gen, const float& start, const float& end)
+                          {return gen.frand(start,end);}
+
+  };
+
+  template<class Generator>
+  struct rand<Generator,double> {
+    KOKKOS_INLINE_FUNCTION
+    static double max(){return 1.0;}
+    KOKKOS_INLINE_FUNCTION
+    static double draw(Generator& gen)
+                          {return gen.drand();}
+    KOKKOS_INLINE_FUNCTION
+    static double draw(Generator& gen, const double& range)
+                          {return gen.drand(range);}
+    KOKKOS_INLINE_FUNCTION
+    static double draw(Generator& gen, const double& start, const double& end)
+                          {return gen.drand(start,end);}
+
+  };
+
+  template<class Generator>
+  struct rand<Generator, ::Kokkos::complex<float> > {
+    KOKKOS_INLINE_FUNCTION
+    static ::Kokkos::complex<float> max () {
+      return ::Kokkos::complex<float> (1.0, 1.0);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static ::Kokkos::complex<float> draw (Generator& gen) {
+      const float re = gen.frand ();
+      const float im = gen.frand ();
+      return ::Kokkos::complex<float> (re, im);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static ::Kokkos::complex<float> draw (Generator& gen, const ::Kokkos::complex<float>& range) {
+      const float re = gen.frand (real (range));
+      const float im = gen.frand (imag (range));
+      return ::Kokkos::complex<float> (re, im);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static ::Kokkos::complex<float> draw (Generator& gen, const ::Kokkos::complex<float>& start, const ::Kokkos::complex<float>& end) {
+      const float re = gen.frand (real (start), real (end));
+      const float im = gen.frand (imag (start), imag (end));
+      return ::Kokkos::complex<float> (re, im);
+    }
+  };
+
+  template<class Generator>
+  struct rand<Generator, ::Kokkos::complex<double> > {
+    KOKKOS_INLINE_FUNCTION
+    static ::Kokkos::complex<double> max () {
+      return ::Kokkos::complex<double> (1.0, 1.0);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static ::Kokkos::complex<double> draw (Generator& gen) {
+      const double re = gen.drand ();
+      const double im = gen.drand ();
+      return ::Kokkos::complex<double> (re, im);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static ::Kokkos::complex<double> draw (Generator& gen, const ::Kokkos::complex<double>& range) {
+      const double re = gen.drand (real (range));
+      const double im = gen.drand (imag (range));
+      return ::Kokkos::complex<double> (re, im);
+    }
+    KOKKOS_INLINE_FUNCTION
+    static ::Kokkos::complex<double> draw (Generator& gen, const ::Kokkos::complex<double>& start, const ::Kokkos::complex<double>& end) {
+      const double re = gen.drand (real (start), real (end));
+      const double im = gen.drand (imag (start), imag (end));
+      return ::Kokkos::complex<double> (re, im);
+    }
+  };
+
+  template<class DeviceType>
+  class Random_XorShift64_Pool;
+
+  template<class DeviceType>
+  class Random_XorShift64 {
+  private:
+    uint64_t state_;
+    const int state_idx_;
+    friend class Random_XorShift64_Pool<DeviceType>;
+  public:
+
+    typedef DeviceType device_type;
+
+    enum {MAX_URAND = 0xffffffffU};
+    enum {MAX_URAND64 = 0xffffffffffffffffULL-1};
+    enum {MAX_RAND = static_cast<int>(0xffffffff/2)};
+    enum {MAX_RAND64 = static_cast<int64_t>(0xffffffffffffffffLL/2-1)};
+
+    KOKKOS_INLINE_FUNCTION
+    Random_XorShift64 (uint64_t state, int state_idx = 0)
+     : state_(state),state_idx_(state_idx){}
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand() {
+      state_ ^= state_ >> 12;
+      state_ ^= state_ << 25;
+      state_ ^= state_ >> 27;
+
+      uint64_t tmp = state_ * 2685821657736338717ULL;
+      tmp = tmp>>16;
+      return static_cast<uint32_t>(tmp&MAX_URAND);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64() {
+      state_ ^= state_ >> 12;
+      state_ ^= state_ << 25;
+      state_ ^= state_ >> 27;
+      return (state_ * 2685821657736338717ULL) - 1;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand(const uint32_t& range) {
+      const uint32_t max_val = (MAX_URAND/range)*range;
+      uint32_t tmp = urand();
+      while(tmp>=max_val)
+        tmp = urand();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand(const uint32_t& start, const uint32_t& end ) {
+      return urand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64(const uint64_t& range) {
+      const uint64_t max_val = (MAX_URAND64/range)*range;
+      uint64_t tmp = urand64();
+      while(tmp>=max_val)
+        tmp = urand64();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64(const uint64_t& start, const uint64_t& end ) {
+      return urand64(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand() {
+      return static_cast<int>(urand()/2);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand(const int& range) {
+      const int max_val = (MAX_RAND/range)*range;
+      int tmp = rand();
+      while(tmp>=max_val)
+        tmp = rand();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand(const int& start, const int& end ) {
+      return rand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64() {
+      return static_cast<int64_t>(urand64()/2);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64(const int64_t& range) {
+      const int64_t max_val = (MAX_RAND64/range)*range;
+      int64_t tmp = rand64();
+      while(tmp>=max_val)
+        tmp = rand64();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64(const int64_t& start, const int64_t& end ) {
+      return rand64(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand() {
+      return 1.0f * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand(const float& range) {
+      return range * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand(const float& start, const float& end ) {
+      return frand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand() {
+      return 1.0 * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand(const double& range) {
+      return range * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand(const double& start, const double& end ) {
+      return drand(end-start)+start;
+    }
+
+    //Marsaglia polar method for drawing a standard normal distributed random number
+    KOKKOS_INLINE_FUNCTION
+    double normal() {
+      double S = 2.0;
+      double U;
+      while(S>=1.0) {
+        U = drand();
+        const double V = drand();
+        S = U*U+V*V;
+      }
+      return U*sqrt(-2.0*log(S)/S);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double normal(const double& mean, const double& std_dev=1.0) {
+      return mean + normal()*std_dev;
+    }
+
+  };
+
+  template<class DeviceType = Kokkos::DefaultExecutionSpace>
+  class Random_XorShift64_Pool {
+  private:
+    typedef View<int*,DeviceType> lock_type;
+    typedef View<uint64_t*,DeviceType> state_data_type;
+    lock_type locks_;
+    state_data_type state_;
+    int num_states_;
+
+  public:
+    typedef Random_XorShift64<DeviceType> generator_type;
+    typedef DeviceType device_type;
+
+    Random_XorShift64_Pool() {
+      num_states_ = 0;
+    }
+    Random_XorShift64_Pool(uint64_t seed) {
+      num_states_ = 0;
+      init(seed,DeviceType::max_hardware_threads());
+    }
+
+    Random_XorShift64_Pool(const Random_XorShift64_Pool& src):
+      locks_(src.locks_),
+      state_(src.state_),
+      num_states_(src.num_states_)
+    {}
+
+    Random_XorShift64_Pool operator = (const Random_XorShift64_Pool& src) {
+      locks_ = src.locks_;
+      state_ = src.state_;
+      num_states_ = src.num_states_;
+      return *this;
+    }
+
+    void init(uint64_t seed, int num_states) {
+      num_states_ = num_states;
+
+      locks_ = lock_type("Kokkos::Random_XorShift64::locks",num_states_);
+      state_ = state_data_type("Kokkos::Random_XorShift64::state",num_states_);
+
+      typename state_data_type::HostMirror h_state = create_mirror_view(state_);
+      typename lock_type::HostMirror h_lock = create_mirror_view(locks_);
+
+      // Execute on the HostMirror's default execution space.
+      Random_XorShift64<typename state_data_type::HostMirror::execution_space> gen(seed,0);
+      for(int i = 0; i < 17; i++)
+        gen.rand();
+      for(int i = 0; i < num_states_; i++) {
+        int n1 = gen.rand();
+        int n2 = gen.rand();
+        int n3 = gen.rand();
+        int n4 = gen.rand();
+        h_state(i) = (((static_cast<uint64_t>(n1)) & 0xffff)<<00) |
+                     (((static_cast<uint64_t>(n2)) & 0xffff)<<16) |
+                     (((static_cast<uint64_t>(n3)) & 0xffff)<<32) |
+                     (((static_cast<uint64_t>(n4)) & 0xffff)<<48);
+        h_lock(i) = 0;
+      }
+      deep_copy(state_,h_state);
+      deep_copy(locks_,h_lock);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    Random_XorShift64<DeviceType> get_state() const {
+      const int i = DeviceType::hardware_thread_id();;
+      return Random_XorShift64<DeviceType>(state_(i),i);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void free_state(const Random_XorShift64<DeviceType>& state) const {
+      state_(state.state_idx_) = state.state_;
+    }
+  };
+
+
+  template<class DeviceType>
+  class Random_XorShift1024_Pool;
+
+  template<class DeviceType>
+  class Random_XorShift1024 {
+  private:
+    int p_;
+    const int state_idx_;
+    uint64_t state_[16];
+    friend class Random_XorShift1024_Pool<DeviceType>;
+  public:
+
+    typedef Random_XorShift1024_Pool<DeviceType> pool_type;
+    typedef DeviceType device_type;
+
+    enum {MAX_URAND = 0xffffffffU};
+    enum {MAX_URAND64 = 0xffffffffffffffffULL-1};
+    enum {MAX_RAND = static_cast<int>(0xffffffffU/2)};
+    enum {MAX_RAND64 = static_cast<int64_t>(0xffffffffffffffffULL/2-1)};
+
+    KOKKOS_INLINE_FUNCTION
+    Random_XorShift1024 (const typename pool_type::state_data_type& state, int p, int state_idx = 0):
+      p_(p),state_idx_(state_idx){
+      for(int i=0 ; i<16; i++)
+        state_[i] = state(state_idx,i);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand() {
+      uint64_t state_0 = state_[ p_ ];
+      uint64_t state_1 = state_[ p_ = ( p_ + 1 ) & 15 ];
+      state_1 ^= state_1 << 31;
+      state_1 ^= state_1 >> 11;
+      state_0 ^= state_0 >> 30;
+      uint64_t tmp = ( state_[ p_ ] = state_0 ^ state_1 ) * 1181783497276652981ULL;
+      tmp = tmp>>16;
+      return static_cast<uint32_t>(tmp&MAX_URAND);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64() {
+      uint64_t state_0 = state_[ p_ ];
+      uint64_t state_1 = state_[ p_ = ( p_ + 1 ) & 15 ];
+      state_1 ^= state_1 << 31;
+      state_1 ^= state_1 >> 11;
+      state_0 ^= state_0 >> 30;
+      return (( state_[ p_ ] = state_0 ^ state_1 ) * 1181783497276652981LL) - 1;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand(const uint32_t& range) {
+      const uint32_t max_val = (MAX_URAND/range)*range;
+      uint32_t tmp = urand();
+      while(tmp>=max_val)
+        tmp = urand();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand(const uint32_t& start, const uint32_t& end ) {
+      return urand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64(const uint64_t& range) {
+      const uint64_t max_val = (MAX_URAND64/range)*range;
+      uint64_t tmp = urand64();
+      while(tmp>=max_val)
+        tmp = urand64();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64(const uint64_t& start, const uint64_t& end ) {
+      return urand64(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand() {
+      return static_cast<int>(urand()/2);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand(const int& range) {
+      const int max_val = (MAX_RAND/range)*range;
+      int tmp = rand();
+      while(tmp>=max_val)
+        tmp = rand();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand(const int& start, const int& end ) {
+      return rand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64() {
+      return static_cast<int64_t>(urand64()/2);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64(const int64_t& range) {
+      const int64_t max_val = (MAX_RAND64/range)*range;
+      int64_t tmp = rand64();
+      while(tmp>=max_val)
+        tmp = rand64();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64(const int64_t& start, const int64_t& end ) {
+      return rand64(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand() {
+      return 1.0f * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand(const float& range) {
+      return range * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand(const float& start, const float& end ) {
+      return frand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand() {
+      return 1.0 * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand(const double& range) {
+      return range * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand(const double& start, const double& end ) {
+      return frand(end-start)+start;
+    }
+
+    //Marsaglia polar method for drawing a standard normal distributed random number
+    KOKKOS_INLINE_FUNCTION
+    double normal() {
+      double S = 2.0;
+      double U;
+      while(S>=1.0) {
+        U = drand();
+        const double V = drand();
+        S = U*U+V*V;
+      }
+      return U*sqrt(-2.0*log(S)/S);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double normal(const double& mean, const double& std_dev=1.0) {
+      return mean + normal()*std_dev;
+    }
+  };
+
+
+  template<class DeviceType = Kokkos::DefaultExecutionSpace>
+  class Random_XorShift1024_Pool {
+  private:
+    typedef View<int*,DeviceType> int_view_type;
+    typedef View<uint64_t*[16],DeviceType> state_data_type;
+
+    int_view_type locks_;
+    state_data_type state_;
+    int_view_type p_;
+    int num_states_;
+    friend class Random_XorShift1024<DeviceType>;
+
+  public:
+    typedef Random_XorShift1024<DeviceType> generator_type;
+
+    typedef DeviceType device_type;
+
+    Random_XorShift1024_Pool() {
+      num_states_ = 0;
+    }
+
+    inline
+    Random_XorShift1024_Pool(uint64_t seed){
+      num_states_ = 0;
+      init(seed,DeviceType::max_hardware_threads());
+    }
+
+    Random_XorShift1024_Pool(const Random_XorShift1024_Pool& src):
+      locks_(src.locks_),
+      state_(src.state_),
+      p_(src.p_),
+      num_states_(src.num_states_)
+    {}
+
+    Random_XorShift1024_Pool operator = (const Random_XorShift1024_Pool& src) {
+      locks_ = src.locks_;
+      state_ = src.state_;
+      p_ = src.p_;
+      num_states_ = src.num_states_;
+      return *this;
+    }
+
+    inline
+    void init(uint64_t seed, int num_states) {
+      num_states_ = num_states;
+
+      locks_ = int_view_type("Kokkos::Random_XorShift1024::locks",num_states_);
+      state_ = state_data_type("Kokkos::Random_XorShift1024::state",num_states_);
+      p_ = int_view_type("Kokkos::Random_XorShift1024::p",num_states_);
+
+      typename state_data_type::HostMirror h_state = create_mirror_view(state_);
+      typename int_view_type::HostMirror h_lock = create_mirror_view(locks_);
+      typename int_view_type::HostMirror h_p = create_mirror_view(p_);
+
+      // Execute on the HostMirror's default execution space.
+      Random_XorShift64<typename state_data_type::HostMirror::execution_space> gen(seed,0);
+      for(int i = 0; i < 17; i++)
+        gen.rand();
+      for(int i = 0; i < num_states_; i++) {
+        for(int j = 0; j < 16 ; j++) {
+          int n1 = gen.rand();
+          int n2 = gen.rand();
+          int n3 = gen.rand();
+          int n4 = gen.rand();
+          h_state(i,j) = (((static_cast<uint64_t>(n1)) & 0xffff)<<00) |
+                         (((static_cast<uint64_t>(n2)) & 0xffff)<<16) |
+                         (((static_cast<uint64_t>(n3)) & 0xffff)<<32) |
+                         (((static_cast<uint64_t>(n4)) & 0xffff)<<48);
+        }
+        h_p(i) = 0;
+        h_lock(i) = 0;
+      }
+      deep_copy(state_,h_state);
+      deep_copy(locks_,h_lock);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    Random_XorShift1024<DeviceType> get_state() const {
+      const int i = DeviceType::hardware_thread_id();
+      return Random_XorShift1024<DeviceType>(state_,p_(i),i);
+    };
+
+    KOKKOS_INLINE_FUNCTION
+    void free_state(const Random_XorShift1024<DeviceType>& state) const {
+      for(int i = 0; i<16; i++)
+        state_(state.state_idx_,i) = state.state_[i];
+      p_(state.state_idx_) = state.p_;
+    }
+  };
+
+#if defined(KOKKOS_HAVE_CUDA) && defined(__CUDACC__)
+
+  template<>
+  class Random_XorShift1024<Kokkos::Cuda> {
+  private:
+    int p_;
+    const int state_idx_;
+    uint64_t* state_;
+    const int stride_;
+    friend class Random_XorShift1024_Pool<Kokkos::Cuda>;
+  public:
+
+    typedef Kokkos::Cuda device_type;
+    typedef Random_XorShift1024_Pool<device_type> pool_type;
+
+    enum {MAX_URAND = 0xffffffffU};
+    enum {MAX_URAND64 = 0xffffffffffffffffULL-1};
+    enum {MAX_RAND = static_cast<int>(0xffffffffU/2)};
+    enum {MAX_RAND64 = static_cast<int64_t>(0xffffffffffffffffULL/2-1)};
+
+    KOKKOS_INLINE_FUNCTION
+    Random_XorShift1024 (const typename pool_type::state_data_type& state, int p, int state_idx = 0):
+      p_(p),state_idx_(state_idx),state_(&state(state_idx,0)),stride_(state.stride_1()){
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand() {
+      uint64_t state_0 = state_[ p_ * stride_ ];
+      uint64_t state_1 = state_[ (p_ = ( p_ + 1 ) & 15) * stride_ ];
+      state_1 ^= state_1 << 31;
+      state_1 ^= state_1 >> 11;
+      state_0 ^= state_0 >> 30;
+      uint64_t tmp = ( state_[ p_ * stride_ ] = state_0 ^ state_1 ) * 1181783497276652981ULL;
+      tmp = tmp>>16;
+      return static_cast<uint32_t>(tmp&MAX_URAND);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64() {
+      uint64_t state_0 = state_[ p_ * stride_ ];
+      uint64_t state_1 = state_[ (p_ = ( p_ + 1 ) & 15) * stride_ ];
+      state_1 ^= state_1 << 31;
+      state_1 ^= state_1 >> 11;
+      state_0 ^= state_0 >> 30;
+      return (( state_[ p_ * stride_ ] = state_0 ^ state_1 ) * 1181783497276652981LL) - 1;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand(const uint32_t& range) {
+      const uint32_t max_val = (MAX_URAND/range)*range;
+      uint32_t tmp = urand();
+      while(tmp>=max_val)
+        urand();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint32_t urand(const uint32_t& start, const uint32_t& end ) {
+      return urand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64(const uint64_t& range) {
+      const uint64_t max_val = (MAX_URAND64/range)*range;
+      uint64_t tmp = urand64();
+      while(tmp>=max_val)
+        urand64();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    uint64_t urand64(const uint64_t& start, const uint64_t& end ) {
+      return urand64(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand() {
+      return static_cast<int>(urand()/2);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand(const int& range) {
+      const int max_val = (MAX_RAND/range)*range;
+      int tmp = rand();
+      while(tmp>=max_val)
+        rand();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int rand(const int& start, const int& end ) {
+      return rand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64() {
+      return static_cast<int64_t>(urand64()/2);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64(const int64_t& range) {
+      const int64_t max_val = (MAX_RAND64/range)*range;
+      int64_t tmp = rand64();
+      while(tmp>=max_val)
+        rand64();
+      return tmp%range;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int64_t rand64(const int64_t& start, const int64_t& end ) {
+      return rand64(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand() {
+      return 1.0f * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand(const float& range) {
+      return range * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float frand(const float& start, const float& end ) {
+      return frand(end-start)+start;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand() {
+      return 1.0 * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand(const double& range) {
+      return range * urand64()/MAX_URAND64;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double drand(const double& start, const double& end ) {
+      return frand(end-start)+start;
+    }
+
+    //Marsaglia polar method for drawing a standard normal distributed random number
+    KOKKOS_INLINE_FUNCTION
+    double normal() {
+      double S = 2.0;
+      double U;
+      while(S>=1.0) {
+        U = drand();
+        const double V = drand();
+        S = U*U+V*V;
+      }
+      return U*sqrt(-2.0*log(S)/S);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double normal(const double& mean, const double& std_dev=1.0) {
+      return mean + normal()*std_dev;
+    }
+  };
+
+template<>
+inline
+Random_XorShift64_Pool<Kokkos::Cuda>::Random_XorShift64_Pool(uint64_t seed) {
+  num_states_ = 0;
+  init(seed,4*32768);
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+Random_XorShift64<Kokkos::Cuda> Random_XorShift64_Pool<Kokkos::Cuda>::get_state() const {
+#ifdef __CUDA_ARCH__
+  const int i_offset = (threadIdx.x*blockDim.y + threadIdx.y)*blockDim.z+threadIdx.z;
+  int i = (((blockIdx.x*gridDim.y+blockIdx.y)*gridDim.z + blockIdx.z) *
+           blockDim.x*blockDim.y*blockDim.z + i_offset)%num_states_;
+  while(Kokkos::atomic_compare_exchange(&locks_(i),0,1)) {
+      i+=blockDim.x*blockDim.y*blockDim.z;
+      if(i>=num_states_) {i = i_offset;}
+  }
+
+  return Random_XorShift64<Kokkos::Cuda>(state_(i),i);
+#else
+  return Random_XorShift64<Kokkos::Cuda>(state_(0),0);
+#endif
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+void Random_XorShift64_Pool<Kokkos::Cuda>::free_state(const Random_XorShift64<Kokkos::Cuda> &state) const {
+#ifdef __CUDA_ARCH__
+  state_(state.state_idx_) = state.state_;
+  locks_(state.state_idx_) = 0;
+  return;
+#endif
+}
+
+
+template<>
+inline
+Random_XorShift1024_Pool<Kokkos::Cuda>::Random_XorShift1024_Pool(uint64_t seed) {
+  num_states_ = 0;
+  init(seed,4*32768);
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+Random_XorShift1024<Kokkos::Cuda> Random_XorShift1024_Pool<Kokkos::Cuda>::get_state() const {
+#ifdef __CUDA_ARCH__
+  const int i_offset = (threadIdx.x*blockDim.y + threadIdx.y)*blockDim.z+threadIdx.z;
+  int i = (((blockIdx.x*gridDim.y+blockIdx.y)*gridDim.z + blockIdx.z) *
+           blockDim.x*blockDim.y*blockDim.z + i_offset)%num_states_;
+  while(Kokkos::atomic_compare_exchange(&locks_(i),0,1)) {
+      i+=blockDim.x*blockDim.y*blockDim.z;
+      if(i>=num_states_) {i = i_offset;}
+  }
+
+  return Random_XorShift1024<Kokkos::Cuda>(state_, p_(i), i);
+#else
+  return Random_XorShift1024<Kokkos::Cuda>(state_, p_(0), 0);
+#endif
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+void Random_XorShift1024_Pool<Kokkos::Cuda>::free_state(const Random_XorShift1024<Kokkos::Cuda> &state) const {
+#ifdef __CUDA_ARCH__
+  for(int i=0; i<16; i++)
+    state_(state.state_idx_,i) = state.state_[i];
+  locks_(state.state_idx_) = 0;
+  return;
+#endif
+}
+
+
+#endif
+
+
+namespace Impl {
+
+template<class ViewType, class RandomPool, int loops, int rank, class IndexType>
+struct fill_random_functor_range;
+template<class ViewType, class RandomPool, int loops, int rank, class IndexType>
+struct fill_random_functor_begin_end;
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_range<ViewType,RandomPool,loops,1,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type range;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type range_):
+    a(a_),rand_pool(rand_pool_),range(range_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const IndexType& i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0()))
+        a(idx) = Rand::draw(gen,range);
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_range<ViewType,RandomPool,loops,2,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type range;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type range_):
+    a(a_),rand_pool(rand_pool_),range(range_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          a(idx,k) = Rand::draw(gen,range);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_range<ViewType,RandomPool,loops,3,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type range;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type range_):
+    a(a_),rand_pool(rand_pool_),range(range_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            a(idx,k,l) = Rand::draw(gen,range);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_range<ViewType,RandomPool,loops,4, IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type range;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type range_):
+    a(a_),rand_pool(rand_pool_),range(range_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              a(idx,k,l,m) = Rand::draw(gen,range);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_range<ViewType,RandomPool,loops,5,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type range;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type range_):
+    a(a_),rand_pool(rand_pool_),range(range_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              for(IndexType n=0;n<static_cast<IndexType>(a.dimension_4());n++)
+              a(idx,k,l,m,n) = Rand::draw(gen,range);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_range<ViewType,RandomPool,loops,6,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type range;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type range_):
+    a(a_),rand_pool(rand_pool_),range(range_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              for(IndexType n=0;n<static_cast<IndexType>(a.dimension_4());n++)
+                for(IndexType o=0;o<static_cast<IndexType>(a.dimension_5());o++)
+              a(idx,k,l,m,n,o) = Rand::draw(gen,range);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_range<ViewType,RandomPool,loops,7,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type range;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type range_):
+    a(a_),rand_pool(rand_pool_),range(range_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              for(IndexType n=0;n<static_cast<IndexType>(a.dimension_4());n++)
+                for(IndexType o=0;o<static_cast<IndexType>(a.dimension_5());o++)
+                  for(IndexType p=0;p<static_cast<IndexType>(a.dimension_6());p++)
+              a(idx,k,l,m,n,o,p) = Rand::draw(gen,range);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_range<ViewType,RandomPool,loops,8,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type range;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_range(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type range_):
+    a(a_),rand_pool(rand_pool_),range(range_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              for(IndexType n=0;n<static_cast<IndexType>(a.dimension_4());n++)
+                for(IndexType o=0;o<static_cast<IndexType>(a.dimension_5());o++)
+                  for(IndexType p=0;p<static_cast<IndexType>(a.dimension_6());p++)
+                    for(IndexType q=0;q<static_cast<IndexType>(a.dimension_7());q++)
+              a(idx,k,l,m,n,o,p,q) = Rand::draw(gen,range);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_begin_end<ViewType,RandomPool,loops,1,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type begin,end;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type begin_, typename ViewType::const_value_type end_):
+    a(a_),rand_pool(rand_pool_),begin(begin_),end(end_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0()))
+        a(idx) = Rand::draw(gen,begin,end);
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_begin_end<ViewType,RandomPool,loops,2,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type begin,end;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type begin_, typename ViewType::const_value_type end_):
+    a(a_),rand_pool(rand_pool_),begin(begin_),end(end_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          a(idx,k) = Rand::draw(gen,begin,end);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_begin_end<ViewType,RandomPool,loops,3,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type begin,end;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type begin_, typename ViewType::const_value_type end_):
+    a(a_),rand_pool(rand_pool_),begin(begin_),end(end_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            a(idx,k,l) = Rand::draw(gen,begin,end);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_begin_end<ViewType,RandomPool,loops,4,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type begin,end;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type begin_, typename ViewType::const_value_type end_):
+    a(a_),rand_pool(rand_pool_),begin(begin_),end(end_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              a(idx,k,l,m) = Rand::draw(gen,begin,end);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_begin_end<ViewType,RandomPool,loops,5,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type begin,end;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type begin_, typename ViewType::const_value_type end_):
+    a(a_),rand_pool(rand_pool_),begin(begin_),end(end_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())){
+        for(IndexType l=0;l<static_cast<IndexType>(a.dimension_1());l++)
+          for(IndexType m=0;m<static_cast<IndexType>(a.dimension_2());m++)
+            for(IndexType n=0;n<static_cast<IndexType>(a.dimension_3());n++)
+              for(IndexType o=0;o<static_cast<IndexType>(a.dimension_4());o++)
+          a(idx,l,m,n,o) = Rand::draw(gen,begin,end);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_begin_end<ViewType,RandomPool,loops,6,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type begin,end;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type begin_, typename ViewType::const_value_type end_):
+    a(a_),rand_pool(rand_pool_),begin(begin_),end(end_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              for(IndexType n=0;n<static_cast<IndexType>(a.dimension_4());n++)
+                for(IndexType o=0;o<static_cast<IndexType>(a.dimension_5());o++)
+          a(idx,k,l,m,n,o) = Rand::draw(gen,begin,end);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_begin_end<ViewType,RandomPool,loops,7,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type begin,end;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type begin_, typename ViewType::const_value_type end_):
+    a(a_),rand_pool(rand_pool_),begin(begin_),end(end_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              for(IndexType n=0;n<static_cast<IndexType>(a.dimension_4());n++)
+                for(IndexType o=0;o<static_cast<IndexType>(a.dimension_5());o++)
+                  for(IndexType p=0;p<static_cast<IndexType>(a.dimension_6());p++)
+            a(idx,k,l,m,n,o,p) = Rand::draw(gen,begin,end);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+template<class ViewType, class RandomPool, int loops, class IndexType>
+struct fill_random_functor_begin_end<ViewType,RandomPool,loops,8,IndexType>{
+  typedef typename ViewType::execution_space execution_space;
+  ViewType a;
+  RandomPool rand_pool;
+  typename ViewType::const_value_type begin,end;
+
+  typedef rand<typename RandomPool::generator_type, typename ViewType::non_const_value_type> Rand;
+
+  fill_random_functor_begin_end(ViewType a_, RandomPool rand_pool_,
+      typename ViewType::const_value_type begin_, typename ViewType::const_value_type end_):
+    a(a_),rand_pool(rand_pool_),begin(begin_),end(end_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (IndexType i) const {
+    typename RandomPool::generator_type gen = rand_pool.get_state();
+    for(IndexType j=0;j<loops;j++) {
+      const IndexType idx = i*loops+j;
+      if(idx<static_cast<IndexType>(a.dimension_0())) {
+        for(IndexType k=0;k<static_cast<IndexType>(a.dimension_1());k++)
+          for(IndexType l=0;l<static_cast<IndexType>(a.dimension_2());l++)
+            for(IndexType m=0;m<static_cast<IndexType>(a.dimension_3());m++)
+              for(IndexType n=0;n<static_cast<IndexType>(a.dimension_4());n++)
+                for(IndexType o=0;o<static_cast<IndexType>(a.dimension_5());o++)
+                  for(IndexType p=0;p<static_cast<IndexType>(a.dimension_6());p++)
+                    for(IndexType q=0;q<static_cast<IndexType>(a.dimension_7());q++)
+              a(idx,k,l,m,n,o,p,q) = Rand::draw(gen,begin,end);
+      }
+    }
+    rand_pool.free_state(gen);
+  }
+};
+
+}
+
+template<class ViewType, class RandomPool, class IndexType = int64_t>
+void fill_random(ViewType a, RandomPool g, typename ViewType::const_value_type range) {
+  int64_t LDA = a.dimension_0();
+  if(LDA>0)
+    parallel_for((LDA+127)/128,Impl::fill_random_functor_range<ViewType,RandomPool,128,ViewType::Rank,IndexType>(a,g,range));
+}
+
+template<class ViewType, class RandomPool, class IndexType = int64_t>
+void fill_random(ViewType a, RandomPool g, typename ViewType::const_value_type begin,typename ViewType::const_value_type end ) {
+  int64_t LDA = a.dimension_0();
+  if(LDA>0)
+    parallel_for((LDA+127)/128,Impl::fill_random_functor_begin_end<ViewType,RandomPool,128,ViewType::Rank,IndexType>(a,g,begin,end));
+}
+}
+
+#endif
diff --git a/lib/kokkos/algorithms/src/Kokkos_Sort.hpp b/lib/kokkos/algorithms/src/Kokkos_Sort.hpp
new file mode 100644
index 0000000000..6123ce978c
--- /dev/null
+++ b/lib/kokkos/algorithms/src/Kokkos_Sort.hpp
@@ -0,0 +1,496 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+
+#ifndef KOKKOS_SORT_HPP_
+#define KOKKOS_SORT_HPP_
+
+#include <Kokkos_Core.hpp>
+
+#include <algorithm>
+
+namespace Kokkos {
+
+  namespace SortImpl {
+
+  template<class ValuesViewType, int Rank=ValuesViewType::Rank>
+  struct CopyOp;
+
+  template<class ValuesViewType>
+  struct CopyOp<ValuesViewType,1> {
+    template<class DstType, class SrcType>
+    KOKKOS_INLINE_FUNCTION
+    static void copy(DstType& dst, size_t i_dst,
+                     SrcType& src, size_t i_src ) {
+      dst(i_dst) = src(i_src);
+    }
+  };
+
+  template<class ValuesViewType>
+  struct CopyOp<ValuesViewType,2> {
+    template<class DstType, class SrcType>
+    KOKKOS_INLINE_FUNCTION
+    static void copy(DstType& dst, size_t i_dst,
+                     SrcType& src, size_t i_src ) {
+      for(int j = 0;j< (int) dst.dimension_1(); j++)
+        dst(i_dst,j) = src(i_src,j);
+    }
+  };
+
+  template<class ValuesViewType>
+  struct CopyOp<ValuesViewType,3> {
+    template<class DstType, class SrcType>
+    KOKKOS_INLINE_FUNCTION
+    static void copy(DstType& dst, size_t i_dst,
+                     SrcType& src, size_t i_src ) {
+      for(int j = 0; j<dst.dimension_1(); j++)
+        for(int k = 0; k<dst.dimension_2(); k++)
+          dst(i_dst,j,k) = src(i_src,j,k);
+    }
+  };
+  }
+
+template<class KeyViewType, class BinSortOp, class ExecutionSpace = typename KeyViewType::execution_space,
+         class SizeType = typename KeyViewType::memory_space::size_type>
+class BinSort {
+
+
+public:
+  template<class ValuesViewType, class PermuteViewType, class CopyOp>
+  struct bin_sort_sort_functor {
+    typedef ExecutionSpace execution_space;
+    typedef typename ValuesViewType::non_const_type values_view_type;
+    typedef typename ValuesViewType::const_type const_values_view_type;
+    Kokkos::View<typename values_view_type::const_data_type,typename values_view_type::array_layout,
+                 typename values_view_type::memory_space,Kokkos::MemoryTraits<Kokkos::RandomAccess> > values;
+    values_view_type sorted_values;
+    typename PermuteViewType::const_type sort_order;
+    bin_sort_sort_functor(const_values_view_type values_, values_view_type  sorted_values_, PermuteViewType sort_order_):
+       values(values_),sorted_values(sorted_values_),sort_order(sort_order_) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i)  const {
+      //printf("Sort: %i %i\n",i,sort_order(i));
+      CopyOp::copy(sorted_values,i,values,sort_order(i));
+    }
+  };
+
+  typedef ExecutionSpace execution_space;
+  typedef BinSortOp bin_op_type;
+
+  struct bin_count_tag {};
+  struct bin_offset_tag {};
+  struct bin_binning_tag {};
+  struct bin_sort_bins_tag {};
+
+public:
+  typedef SizeType size_type;
+  typedef size_type value_type;
+
+  typedef Kokkos::View<size_type*, execution_space> offset_type;
+  typedef Kokkos::View<const int*, execution_space> bin_count_type;
+
+
+  typedef Kokkos::View<typename KeyViewType::const_data_type,
+                       typename KeyViewType::array_layout,
+                       typename KeyViewType::memory_space> const_key_view_type;
+  typedef Kokkos::View<typename KeyViewType::const_data_type,
+                       typename KeyViewType::array_layout,
+                       typename KeyViewType::memory_space,
+                       Kokkos::MemoryTraits<Kokkos::RandomAccess> > const_rnd_key_view_type;
+
+  typedef typename KeyViewType::non_const_value_type non_const_key_scalar;
+  typedef typename KeyViewType::const_value_type     const_key_scalar;
+
+private:
+  const_key_view_type keys;
+  const_rnd_key_view_type keys_rnd;
+
+public:
+  BinSortOp bin_op;
+
+  offset_type bin_offsets;
+
+  Kokkos::View<int*, ExecutionSpace, Kokkos::MemoryTraits<Kokkos::Atomic> > bin_count_atomic;
+  bin_count_type bin_count_const;
+
+  offset_type sort_order;
+
+  bool sort_within_bins;
+
+public:
+
+  // Constructor: takes the keys, the binning_operator and optionally whether to sort within bins (default false)
+  BinSort(const_key_view_type keys_, BinSortOp bin_op_,
+          bool sort_within_bins_ = false)
+     :keys(keys_),keys_rnd(keys_), bin_op(bin_op_) {
+
+    bin_count_atomic = Kokkos::View<int*, ExecutionSpace >("Kokkos::SortImpl::BinSortFunctor::bin_count",bin_op.max_bins());
+    bin_count_const =  bin_count_atomic;
+    bin_offsets =      offset_type("Kokkos::SortImpl::BinSortFunctor::bin_offsets",bin_op.max_bins());
+    sort_order =       offset_type("PermutationVector",keys.dimension_0());
+    sort_within_bins = sort_within_bins_;
+  }
+
+  // Create the permutation vector, the bin_offset array and the bin_count array. Can be called again if keys changed
+  void create_permute_vector() {
+    Kokkos::parallel_for (Kokkos::RangePolicy<ExecutionSpace,bin_count_tag>    (0,keys.dimension_0()),*this);
+    Kokkos::parallel_scan(Kokkos::RangePolicy<ExecutionSpace,bin_offset_tag>   (0,bin_op.max_bins()) ,*this);
+
+    Kokkos::deep_copy(bin_count_atomic,0);
+    Kokkos::parallel_for (Kokkos::RangePolicy<ExecutionSpace,bin_binning_tag>  (0,keys.dimension_0()),*this);
+
+    if(sort_within_bins)
+      Kokkos::parallel_for (Kokkos::RangePolicy<ExecutionSpace,bin_sort_bins_tag>(0,bin_op.max_bins()) ,*this);
+  }
+
+  // Sort a view with respect ot the first dimension using the permutation array
+  template<class ValuesViewType>
+  void sort(ValuesViewType values) {
+    ValuesViewType sorted_values = ValuesViewType("Copy",
+           values.dimension_0(),
+           values.dimension_1(),
+           values.dimension_2(),
+           values.dimension_3(),
+           values.dimension_4(),
+           values.dimension_5(),
+           values.dimension_6(),
+           values.dimension_7());
+
+    parallel_for(values.dimension_0(),
+        bin_sort_sort_functor<ValuesViewType, offset_type,
+                              SortImpl::CopyOp<ValuesViewType> >(values,sorted_values,sort_order));
+
+    deep_copy(values,sorted_values);
+  }
+
+  // Get the permutation vector
+  KOKKOS_INLINE_FUNCTION
+  offset_type get_permute_vector() const { return sort_order;}
+
+  // Get the start offsets for each bin
+  KOKKOS_INLINE_FUNCTION
+  offset_type get_bin_offsets() const { return bin_offsets;}
+
+  // Get the count for each bin
+  KOKKOS_INLINE_FUNCTION
+  bin_count_type get_bin_count() const {return bin_count_const;}
+
+public:
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const bin_count_tag& tag, const int& i) const {
+    bin_count_atomic(bin_op.bin(keys,i))++;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const bin_offset_tag& tag, const int& i, value_type& offset, const bool& final)  const {
+    if(final) {
+      bin_offsets(i) = offset;
+    }
+    offset+=bin_count_const(i);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const bin_binning_tag& tag, const int& i)  const {
+    const int bin = bin_op.bin(keys,i);
+    const int count = bin_count_atomic(bin)++;
+
+    sort_order(bin_offsets(bin) + count) = i;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const bin_sort_bins_tag& tag, const int&i )  const {
+    bool sorted = false;
+    int upper_bound = bin_offsets(i)+bin_count_const(i);
+    while(!sorted) {
+      sorted = true;
+      int old_idx = sort_order(bin_offsets(i));
+      int new_idx;
+      for(int k=bin_offsets(i)+1; k<upper_bound; k++) {
+        new_idx = sort_order(k);
+
+        if(!bin_op(keys_rnd,old_idx,new_idx)) {
+          sort_order(k-1) = new_idx;
+          sort_order(k) = old_idx;
+          sorted = false;
+        } else {
+          old_idx = new_idx;
+        }
+      }
+      upper_bound--;
+    }
+  }
+};
+
+namespace SortImpl {
+
+template<class KeyViewType>
+struct DefaultBinOp1D {
+  const int max_bins_;
+  const double mul_;
+  typename KeyViewType::const_value_type range_;
+  typename KeyViewType::const_value_type min_;
+
+  //Construct BinOp with number of bins, minimum value and maxuimum value
+  DefaultBinOp1D(int max_bins__, typename KeyViewType::const_value_type min,
+                               typename KeyViewType::const_value_type max )
+     :max_bins_(max_bins__+1),mul_(1.0*max_bins__/(max-min)),range_(max-min),min_(min) {}
+
+  //Determine bin index from key value
+  template<class ViewType>
+  KOKKOS_INLINE_FUNCTION
+  int bin(ViewType& keys, const int& i) const {
+    return int(mul_*(keys(i)-min_));
+  }
+
+  //Return maximum bin index + 1
+  KOKKOS_INLINE_FUNCTION
+  int max_bins() const {
+    return max_bins_;
+  }
+
+  //Compare to keys within a bin if true new_val will be put before old_val
+  template<class ViewType, typename iType1, typename iType2>
+  KOKKOS_INLINE_FUNCTION
+  bool operator()(ViewType& keys, iType1& i1, iType2& i2) const {
+    return keys(i1)<keys(i2);
+  }
+};
+
+template<class KeyViewType>
+struct DefaultBinOp3D {
+  int max_bins_[3];
+  double mul_[3];
+  typename KeyViewType::non_const_value_type range_[3];
+  typename KeyViewType::non_const_value_type min_[3];
+
+  DefaultBinOp3D(int max_bins__[], typename KeyViewType::const_value_type min[],
+                               typename KeyViewType::const_value_type max[] )
+  {
+    max_bins_[0] = max_bins__[0]+1;
+    max_bins_[1] = max_bins__[1]+1;
+    max_bins_[2] = max_bins__[2]+1;
+    mul_[0] = 1.0*max_bins__[0]/(max[0]-min[0]);
+    mul_[1] = 1.0*max_bins__[1]/(max[1]-min[1]);
+    mul_[2] = 1.0*max_bins__[2]/(max[2]-min[2]);
+    range_[0] = max[0]-min[0];
+    range_[1] = max[1]-min[1];
+    range_[2] = max[2]-min[2];
+    min_[0] = min[0];
+    min_[1] = min[1];
+    min_[2] = min[2];
+  }
+
+  template<class ViewType>
+  KOKKOS_INLINE_FUNCTION
+  int bin(ViewType& keys, const int& i) const {
+    return int( (((int(mul_[0]*(keys(i,0)-min_[0]))*max_bins_[1]) +
+                   int(mul_[1]*(keys(i,1)-min_[1])))*max_bins_[2]) +
+                   int(mul_[2]*(keys(i,2)-min_[2])));
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  int max_bins() const {
+    return max_bins_[0]*max_bins_[1]*max_bins_[2];
+  }
+
+  template<class ViewType, typename iType1, typename iType2>
+  KOKKOS_INLINE_FUNCTION
+  bool operator()(ViewType& keys, iType1& i1 , iType2& i2) const {
+    if (keys(i1,0)>keys(i2,0)) return true;
+    else if (keys(i1,0)==keys(i2,0)) {
+      if (keys(i1,1)>keys(i2,1)) return true;
+      else if (keys(i1,1)==keys(i2,2)) {
+        if (keys(i1,2)>keys(i2,2)) return true;
+      }
+    }
+    return false;
+  }
+};
+
+template<typename Scalar>
+struct min_max {
+  Scalar min;
+  Scalar max;
+  bool init;
+
+  KOKKOS_INLINE_FUNCTION
+  min_max() {
+    min = 0;
+    max = 0;
+    init = 0;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  min_max (const min_max& val) {
+    min = val.min;
+    max = val.max;
+    init = val.init;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  min_max operator = (const min_max& val) {
+    min = val.min;
+    max = val.max;
+    init = val.init;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator+= (const Scalar& val) {
+    if(init) {
+      min = min<val?min:val;
+      max = max>val?max:val;
+    } else {
+      min = val;
+      max = val;
+      init = 1;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator+= (const min_max& val) {
+    if(init && val.init) {
+      min = min<val.min?min:val.min;
+      max = max>val.max?max:val.max;
+    } else {
+      if(val.init) {
+        min = val.min;
+        max = val.max;
+        init = 1;
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator+= (volatile const Scalar& val) volatile {
+    if(init) {
+      min = min<val?min:val;
+      max = max>val?max:val;
+    } else {
+      min = val;
+      max = val;
+      init = 1;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator+= (volatile const min_max& val) volatile {
+    if(init && val.init) {
+      min = min<val.min?min:val.min;
+      max = max>val.max?max:val.max;
+    } else {
+      if(val.init) {
+        min = val.min;
+        max = val.max;
+        init = 1;
+      }
+    }
+  }
+};
+
+
+template<class ViewType>
+struct min_max_functor {
+  typedef typename ViewType::execution_space execution_space;
+  ViewType view;
+  typedef min_max<typename ViewType::non_const_value_type> value_type;
+  min_max_functor (const ViewType view_):view(view_) {
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(const size_t& i, value_type& val) const {
+    val += view(i);
+  }
+};
+
+template<class ViewType>
+bool try_std_sort(ViewType view) {
+  bool possible = true;
+#if ! KOKKOS_USING_EXP_VIEW
+  size_t stride[8];
+  view.stride(stride);
+#else
+  size_t stride[8] = { view.stride_0()
+                     , view.stride_1()
+                     , view.stride_2()
+                     , view.stride_3()
+                     , view.stride_4()
+                     , view.stride_5()
+                     , view.stride_6()
+                     , view.stride_7()
+                     };
+#endif
+  possible  = possible && Impl::is_same<typename ViewType::memory_space, HostSpace>::value;
+  possible  = possible && (ViewType::Rank == 1);
+  possible  = possible && (stride[0] == 1);
+  if(possible)  {
+   std::sort(view.ptr_on_device(),view.ptr_on_device()+view.dimension_0());
+  }
+  return possible;
+}
+
+}
+
+template<class ViewType>
+void sort(ViewType view, bool always_use_kokkos_sort = false) {
+  if(!always_use_kokkos_sort) {
+    if(SortImpl::try_std_sort(view)) return;
+  }
+
+  typedef SortImpl::DefaultBinOp1D<ViewType> CompType;
+  SortImpl::min_max<typename ViewType::non_const_value_type> val;
+  parallel_reduce(view.dimension_0(),SortImpl::min_max_functor<ViewType>(view),val);
+  BinSort<ViewType, CompType> bin_sort(view,CompType(view.dimension_0()/2,val.min,val.max),true);
+  bin_sort.create_permute_vector();
+  bin_sort.sort(view);
+}
+
+/*template<class ViewType, class Comparator>
+void sort(ViewType view, Comparator comp, bool always_use_kokkos_sort = false) {
+
+}*/
+
+}
+
+#endif
diff --git a/lib/kokkos/algorithms/unit_tests/CMakeLists.txt b/lib/kokkos/algorithms/unit_tests/CMakeLists.txt
new file mode 100644
index 0000000000..654104b44e
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/CMakeLists.txt
@@ -0,0 +1,38 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../src )
+
+SET(SOURCES
+  UnitTestMain.cpp 
+  TestCuda.cpp
+  )
+
+SET(LIBRARIES kokkoscore)
+
+IF(Kokkos_ENABLE_OpenMP)
+  LIST( APPEND SOURCES
+    TestOpenMP.cpp
+  )
+ENDIF()
+
+IF(Kokkos_ENABLE_Serial)
+  LIST( APPEND SOURCES
+    TestSerial.cpp
+  )
+ENDIF()
+
+IF(Kokkos_ENABLE_Pthread)
+  LIST( APPEND SOURCES
+    TestThreads.cpp
+  )
+ENDIF()
+
+TRIBITS_ADD_EXECUTABLE_AND_TEST(
+  UnitTest
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  NUM_MPI_PROCS 1
+  FAIL_REGULAR_EXPRESSION "  FAILED  "
+  TESTONLYLIBS kokkos_gtest
+  )
diff --git a/lib/kokkos/algorithms/unit_tests/Makefile b/lib/kokkos/algorithms/unit_tests/Makefile
new file mode 100644
index 0000000000..5d79364c52
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/Makefile
@@ -0,0 +1,92 @@
+KOKKOS_PATH = ../..
+
+GTEST_PATH = ../../TPL/gtest
+
+vpath %.cpp ${KOKKOS_PATH}/algorithms/unit_tests
+
+default: build_all
+	echo "End Build"
+
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?= -lpthread
+endif
+
+KOKKOS_CXXFLAGS += -I$(GTEST_PATH) -I${KOKKOS_PATH}/algorithms/unit_tests
+
+TEST_TARGETS = 
+TARGETS = 
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	OBJ_CUDA = TestCuda.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosAlgorithms_UnitTest_Cuda
+	TEST_TARGETS += test-cuda
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+	OBJ_THREADS = TestThreads.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosAlgorithms_UnitTest_Threads
+	TEST_TARGETS += test-threads
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+	OBJ_OPENMP = TestOpenMP.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosAlgorithms_UnitTest_OpenMP
+	TEST_TARGETS += test-openmp
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_SERIAL), 1)
+	OBJ_SERIAL = TestSerial.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosAlgorithms_UnitTest_Serial
+	TEST_TARGETS += test-serial
+endif
+
+KokkosAlgorithms_UnitTest_Cuda: $(OBJ_CUDA) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_CUDA) $(KOKKOS_LIBS) $(LIB) -o KokkosAlgorithms_UnitTest_Cuda
+
+KokkosAlgorithms_UnitTest_Threads: $(OBJ_THREADS) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_THREADS) $(KOKKOS_LIBS) $(LIB) -o KokkosAlgorithms_UnitTest_Threads
+
+KokkosAlgorithms_UnitTest_OpenMP: $(OBJ_OPENMP) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_OPENMP) $(KOKKOS_LIBS) $(LIB) -o KokkosAlgorithms_UnitTest_OpenMP
+
+KokkosAlgorithms_UnitTest_Serial: $(OBJ_SERIAL) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_SERIAL) $(KOKKOS_LIBS) $(LIB) -o KokkosAlgorithms_UnitTest_Serial
+
+test-cuda: KokkosAlgorithms_UnitTest_Cuda
+	./KokkosAlgorithms_UnitTest_Cuda
+
+test-threads: KokkosAlgorithms_UnitTest_Threads
+	./KokkosAlgorithms_UnitTest_Threads
+
+test-openmp: KokkosAlgorithms_UnitTest_OpenMP
+	./KokkosAlgorithms_UnitTest_OpenMP
+
+test-serial: KokkosAlgorithms_UnitTest_Serial
+	./KokkosAlgorithms_UnitTest_Serial
+
+build_all: $(TARGETS)
+
+test: $(TEST_TARGETS)
+
+clean: kokkos-clean 
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
+gtest-all.o:$(GTEST_PATH)/gtest/gtest-all.cc 
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $(GTEST_PATH)/gtest/gtest-all.cc
+
diff --git a/lib/kokkos/algorithms/unit_tests/TestCuda.cpp b/lib/kokkos/algorithms/unit_tests/TestCuda.cpp
new file mode 100644
index 0000000000..d19c778c46
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/TestCuda.cpp
@@ -0,0 +1,110 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdint.h>
+#include <iostream>
+#include <iomanip>
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#ifdef KOKKOS_HAVE_CUDA
+
+#include <TestRandom.hpp>
+#include <TestSort.hpp>
+
+namespace Test {
+
+class cuda : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+    Kokkos::HostSpace::execution_space::initialize();
+    Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice(0) );
+  }
+  static void TearDownTestCase()
+  {
+    Kokkos::Cuda::finalize();
+    Kokkos::HostSpace::execution_space::finalize();
+  }
+};
+
+void cuda_test_random_xorshift64( int num_draws  )
+{
+  Impl::test_random<Kokkos::Random_XorShift64_Pool<Kokkos::Cuda> >(num_draws);
+}
+
+void cuda_test_random_xorshift1024( int num_draws  )
+{
+  Impl::test_random<Kokkos::Random_XorShift1024_Pool<Kokkos::Cuda> >(num_draws);
+}
+
+
+#define CUDA_RANDOM_XORSHIFT64( num_draws )                                \
+  TEST_F( cuda, Random_XorShift64 ) {   \
+  cuda_test_random_xorshift64(num_draws);                                   \
+  }
+
+#define CUDA_RANDOM_XORSHIFT1024( num_draws )                                \
+  TEST_F( cuda, Random_XorShift1024 ) {   \
+  cuda_test_random_xorshift1024(num_draws);                                   \
+  }
+
+#define CUDA_SORT_UNSIGNED( size )                                \
+  TEST_F( cuda, SortUnsigned ) {   \
+      Impl::test_sort< Kokkos::Cuda, unsigned >(size);                                   \
+  }
+
+CUDA_RANDOM_XORSHIFT64(  132141141 )
+CUDA_RANDOM_XORSHIFT1024( 52428813 )
+CUDA_SORT_UNSIGNED(171)
+
+#undef CUDA_RANDOM_XORSHIFT64
+#undef CUDA_RANDOM_XORSHIFT1024
+#undef CUDA_SORT_UNSIGNED
+}
+
+#endif  /* #ifdef KOKKOS_HAVE_CUDA */
+
diff --git a/lib/kokkos/algorithms/unit_tests/TestOpenMP.cpp b/lib/kokkos/algorithms/unit_tests/TestOpenMP.cpp
new file mode 100644
index 0000000000..4b06dffcb6
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/TestOpenMP.cpp
@@ -0,0 +1,102 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+#include <TestRandom.hpp>
+#include <TestSort.hpp>
+#include <iomanip>
+
+namespace Test {
+
+#ifdef KOKKOS_HAVE_OPENMP
+class openmp : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+
+    unsigned threads_count = omp_get_max_threads();
+
+    if ( Kokkos::hwloc::available() ) {
+      threads_count = Kokkos::hwloc::get_available_numa_count() *
+                      Kokkos::hwloc::get_available_cores_per_numa();
+    }
+
+    Kokkos::OpenMP::initialize( threads_count );
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::OpenMP::finalize();
+  }
+};
+
+#define OPENMP_RANDOM_XORSHIFT64( num_draws )                                \
+  TEST_F( openmp, Random_XorShift64 ) {   \
+      Impl::test_random<Kokkos::Random_XorShift64_Pool<Kokkos::OpenMP> >(num_draws);                                   \
+  }
+
+#define OPENMP_RANDOM_XORSHIFT1024( num_draws )                                \
+  TEST_F( openmp, Random_XorShift1024 ) {   \
+      Impl::test_random<Kokkos::Random_XorShift1024_Pool<Kokkos::OpenMP> >(num_draws);                                   \
+  }
+
+#define OPENMP_SORT_UNSIGNED( size )                                \
+  TEST_F( openmp, SortUnsigned ) {   \
+      Impl::test_sort< Kokkos::OpenMP, unsigned >(size);                                   \
+  }
+
+OPENMP_RANDOM_XORSHIFT64( 10240000 )
+OPENMP_RANDOM_XORSHIFT1024( 10130144 )
+OPENMP_SORT_UNSIGNED(171)
+
+#undef OPENMP_RANDOM_XORSHIFT64
+#undef OPENMP_RANDOM_XORSHIFT1024
+#undef OPENMP_SORT_UNSIGNED
+#endif
+} // namespace test
+
diff --git a/lib/kokkos/algorithms/unit_tests/TestRandom.hpp b/lib/kokkos/algorithms/unit_tests/TestRandom.hpp
new file mode 100644
index 0000000000..c906b9f2cd
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/TestRandom.hpp
@@ -0,0 +1,481 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_TEST_DUALVIEW_HPP
+#define KOKKOS_TEST_DUALVIEW_HPP
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+#include <impl/Kokkos_Timer.hpp>
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Random.hpp>
+#include <cmath>
+#include <chrono>
+
+namespace Test {
+
+namespace Impl{
+
+// This test runs the random number generators and uses some statistic tests to
+// check the 'goodness' of the random numbers:
+//    (i)   mean:         the mean is expected to be 0.5*RAND_MAX
+//    (ii)  variance:     the variance is 1/3*mean*mean
+//    (iii) covariance:   the covariance is 0
+//    (iv)  1-tupledistr: the mean, variance and covariance of a 1D Histrogram of random numbers
+//    (v)   3-tupledistr: the mean, variance and covariance of a 3D Histrogram of random numbers
+
+#define HIST_DIM3D 24
+#define HIST_DIM1D (HIST_DIM3D*HIST_DIM3D*HIST_DIM3D)
+
+struct RandomProperties {
+  uint64_t count;
+  double mean;
+  double variance;
+  double covariance;
+  double min;
+  double max;
+
+  KOKKOS_INLINE_FUNCTION
+  RandomProperties() {
+    count = 0;
+    mean = 0.0;
+    variance = 0.0;
+    covariance = 0.0;
+    min = 1e64;
+    max = -1e64;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  RandomProperties& operator+=(const RandomProperties& add) {
+    count      += add.count;
+    mean       += add.mean;
+    variance   += add.variance;
+    covariance += add.covariance;
+    min         = add.min<min?add.min:min;
+    max         = add.max>max?add.max:max;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator+=(const volatile RandomProperties& add) volatile {
+    count      += add.count;
+    mean       += add.mean;
+    variance   += add.variance;
+    covariance += add.covariance;
+    min         = add.min<min?add.min:min;
+    max         = add.max>max?add.max:max;
+  }
+};
+
+template<class GeneratorPool, class Scalar>
+struct test_random_functor {
+  typedef typename GeneratorPool::generator_type rnd_type;
+
+  typedef RandomProperties value_type;
+  typedef typename GeneratorPool::device_type device_type;
+
+  GeneratorPool rand_pool;
+  const double mean;
+
+  // NOTE (mfh 03 Nov 2014): Kokkos::rand::max() is supposed to define
+  // an exclusive upper bound on the range of random numbers that
+  // draw() can generate.  However, for the float specialization, some
+  // implementations might violate this upper bound, due to rounding
+  // error.  Just in case, we leave an extra space at the end of each
+  // dimension, in the View types below.
+  typedef Kokkos::View<int[HIST_DIM1D+1],typename GeneratorPool::device_type> type_1d;
+  type_1d density_1d;
+  typedef Kokkos::View<int[HIST_DIM3D+1][HIST_DIM3D+1][HIST_DIM3D+1],typename GeneratorPool::device_type> type_3d;
+  type_3d density_3d;
+
+  test_random_functor (GeneratorPool rand_pool_, type_1d d1d, type_3d d3d) :
+    rand_pool (rand_pool_),
+    mean (0.5*Kokkos::rand<rnd_type,Scalar>::max ()),
+    density_1d (d1d),
+    density_3d (d3d)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, RandomProperties& prop) const {
+    using Kokkos::atomic_fetch_add;
+
+    rnd_type rand_gen = rand_pool.get_state();
+    for (int k = 0; k < 1024; ++k) {
+      const Scalar tmp = Kokkos::rand<rnd_type,Scalar>::draw(rand_gen);
+      prop.count++;
+      prop.mean += tmp;
+      prop.variance += (tmp-mean)*(tmp-mean);
+      const Scalar tmp2 = Kokkos::rand<rnd_type,Scalar>::draw(rand_gen);
+      prop.count++;
+      prop.mean += tmp2;
+      prop.variance += (tmp2-mean)*(tmp2-mean);
+      prop.covariance += (tmp-mean)*(tmp2-mean);
+      const Scalar tmp3 = Kokkos::rand<rnd_type,Scalar>::draw(rand_gen);
+      prop.count++;
+      prop.mean += tmp3;
+      prop.variance += (tmp3-mean)*(tmp3-mean);
+      prop.covariance += (tmp2-mean)*(tmp3-mean);
+
+      // NOTE (mfh 03 Nov 2014): Kokkos::rand::max() is supposed to
+      // define an exclusive upper bound on the range of random
+      // numbers that draw() can generate.  However, for the float
+      // specialization, some implementations might violate this upper
+      // bound, due to rounding error.  Just in case, we have left an
+      // extra space at the end of each dimension of density_1d and
+      // density_3d.
+      //
+      // Please note that those extra entries might not get counted in
+      // the histograms.  However, if Kokkos::rand is broken and only
+      // returns values of max(), the histograms will still catch this
+      // indirectly, since none of the other values will be filled in.
+
+      const Scalar theMax = Kokkos::rand<rnd_type, Scalar>::max ();
+
+      const uint64_t ind1_1d = static_cast<uint64_t> (1.0 * HIST_DIM1D * tmp / theMax);
+      const uint64_t ind2_1d = static_cast<uint64_t> (1.0 * HIST_DIM1D * tmp2 / theMax);
+      const uint64_t ind3_1d = static_cast<uint64_t> (1.0 * HIST_DIM1D * tmp3 / theMax);
+
+      const uint64_t ind1_3d = static_cast<uint64_t> (1.0 * HIST_DIM3D * tmp / theMax);
+      const uint64_t ind2_3d = static_cast<uint64_t> (1.0 * HIST_DIM3D * tmp2 / theMax);
+      const uint64_t ind3_3d = static_cast<uint64_t> (1.0 * HIST_DIM3D * tmp3 / theMax);
+
+      atomic_fetch_add (&density_1d(ind1_1d), 1);
+      atomic_fetch_add (&density_1d(ind2_1d), 1);
+      atomic_fetch_add (&density_1d(ind3_1d), 1);
+      atomic_fetch_add (&density_3d(ind1_3d, ind2_3d, ind3_3d), 1);
+    }
+    rand_pool.free_state(rand_gen);
+  }
+};
+
+template<class DeviceType>
+struct test_histogram1d_functor {
+  typedef RandomProperties value_type;
+  typedef typename DeviceType::execution_space execution_space;
+  typedef typename DeviceType::memory_space memory_space;
+
+  // NOTE (mfh 03 Nov 2014): Kokkos::rand::max() is supposed to define
+  // an exclusive upper bound on the range of random numbers that
+  // draw() can generate.  However, for the float specialization, some
+  // implementations might violate this upper bound, due to rounding
+  // error.  Just in case, we leave an extra space at the end of each
+  // dimension, in the View type below.
+  typedef Kokkos::View<int[HIST_DIM1D+1], memory_space> type_1d;
+  type_1d density_1d;
+  double mean;
+
+  test_histogram1d_functor (type_1d d1d, int num_draws) :
+    density_1d (d1d),
+    mean (1.0*num_draws/HIST_DIM1D*3)
+  {
+  }
+
+  KOKKOS_INLINE_FUNCTION void
+  operator() (const typename memory_space::size_type i,
+              RandomProperties& prop) const
+  {
+    typedef typename memory_space::size_type size_type;
+    const double count = density_1d(i);
+    prop.mean += count;
+    prop.variance += 1.0 * (count - mean) * (count - mean);
+    //prop.covariance += 1.0*count*count;
+    prop.min = count < prop.min ? count : prop.min;
+    prop.max = count > prop.max ? count : prop.max;
+    if (i < static_cast<size_type> (HIST_DIM1D-1)) {
+      prop.covariance += (count - mean) * (density_1d(i+1) - mean);
+    }
+  }
+};
+
+template<class DeviceType>
+struct test_histogram3d_functor {
+  typedef RandomProperties value_type;
+  typedef typename DeviceType::execution_space execution_space;
+  typedef typename DeviceType::memory_space memory_space;
+
+  // NOTE (mfh 03 Nov 2014): Kokkos::rand::max() is supposed to define
+  // an exclusive upper bound on the range of random numbers that
+  // draw() can generate.  However, for the float specialization, some
+  // implementations might violate this upper bound, due to rounding
+  // error.  Just in case, we leave an extra space at the end of each
+  // dimension, in the View type below.
+  typedef Kokkos::View<int[HIST_DIM3D+1][HIST_DIM3D+1][HIST_DIM3D+1], memory_space> type_3d;
+  type_3d density_3d;
+  double mean;
+
+  test_histogram3d_functor (type_3d d3d, int num_draws) :
+    density_3d (d3d),
+    mean (1.0*num_draws/HIST_DIM1D)
+  {}
+
+  KOKKOS_INLINE_FUNCTION void
+  operator() (const typename memory_space::size_type i,
+              RandomProperties& prop) const
+  {
+    typedef typename memory_space::size_type size_type;
+    const double count = density_3d(i/(HIST_DIM3D*HIST_DIM3D),
+                                    (i % (HIST_DIM3D*HIST_DIM3D))/HIST_DIM3D,
+                                    i % HIST_DIM3D);
+    prop.mean += count;
+    prop.variance += (count - mean) * (count - mean);
+    if (i < static_cast<size_type> (HIST_DIM1D-1)) {
+      const double count_next = density_3d((i+1)/(HIST_DIM3D*HIST_DIM3D),
+                                           ((i+1)%(HIST_DIM3D*HIST_DIM3D))/HIST_DIM3D,
+                                           (i+1)%HIST_DIM3D);
+      prop.covariance += (count - mean) * (count_next - mean);
+    }
+  }
+};
+
+//
+// Templated test that uses the above functors.
+//
+template <class RandomGenerator,class Scalar>
+struct test_random_scalar {
+  typedef typename RandomGenerator::generator_type rnd_type;
+
+  int pass_mean,pass_var,pass_covar;
+  int pass_hist1d_mean,pass_hist1d_var,pass_hist1d_covar;
+  int pass_hist3d_mean,pass_hist3d_var,pass_hist3d_covar;
+
+  test_random_scalar (typename test_random_functor<RandomGenerator,int>::type_1d& density_1d,
+                      typename test_random_functor<RandomGenerator,int>::type_3d& density_3d,
+                      RandomGenerator& pool,
+                      unsigned int num_draws)
+  {
+    using std::cerr;
+    using std::endl;
+    using Kokkos::parallel_reduce;
+
+    {
+      cerr << " -- Testing randomness properties" << endl;
+
+      RandomProperties result;
+      typedef test_random_functor<RandomGenerator, Scalar> functor_type;
+      parallel_reduce (num_draws/1024, functor_type (pool, density_1d, density_3d), result);
+
+      //printf("Result: %lf %lf %lf\n",result.mean/num_draws/3,result.variance/num_draws/3,result.covariance/num_draws/2);
+      double tolerance = 1.6*sqrt(1.0/num_draws);
+      double mean_expect = 0.5*Kokkos::rand<rnd_type,Scalar>::max();
+      double variance_expect = 1.0/3.0*mean_expect*mean_expect;
+      double mean_eps = mean_expect/(result.mean/num_draws/3)-1.0;
+      double variance_eps = variance_expect/(result.variance/num_draws/3)-1.0;
+      double covariance_eps = result.covariance/num_draws/2/variance_expect;
+      pass_mean  = ((-tolerance < mean_eps) &&
+                    ( tolerance > mean_eps)) ? 1:0;
+      pass_var   = ((-1.5*tolerance < variance_eps) &&
+                    ( 1.5*tolerance > variance_eps)) ? 1:0;
+      pass_covar = ((-2.0*tolerance < covariance_eps) &&
+                    ( 2.0*tolerance > covariance_eps)) ? 1:0;
+      cerr << "Pass: " << pass_mean
+           << " " << pass_var
+           << " " << mean_eps
+           << " " << variance_eps
+           << " " << covariance_eps
+           << " || " << tolerance << endl;
+    }
+    {
+      cerr << " -- Testing 1-D histogram" << endl;
+
+      RandomProperties result;
+      typedef test_histogram1d_functor<typename RandomGenerator::device_type> functor_type;
+      parallel_reduce (HIST_DIM1D, functor_type (density_1d, num_draws), result);
+
+      double tolerance = 6*sqrt(1.0/HIST_DIM1D);
+      double mean_expect = 1.0*num_draws*3/HIST_DIM1D;
+      double variance_expect = 1.0*num_draws*3/HIST_DIM1D*(1.0-1.0/HIST_DIM1D);
+      double covariance_expect = -1.0*num_draws*3/HIST_DIM1D/HIST_DIM1D;
+      double mean_eps = mean_expect/(result.mean/HIST_DIM1D)-1.0;
+      double variance_eps = variance_expect/(result.variance/HIST_DIM1D)-1.0;
+      double covariance_eps = (result.covariance/HIST_DIM1D - covariance_expect)/mean_expect;
+      pass_hist1d_mean  = ((-0.0001 < mean_eps) &&
+                           ( 0.0001 > mean_eps)) ? 1:0;
+      pass_hist1d_var   = ((-0.07 < variance_eps) &&
+                           ( 0.07 > variance_eps)) ? 1:0;
+      pass_hist1d_covar = ((-0.06 < covariance_eps) &&
+                           ( 0.06 > covariance_eps)) ? 1:0;
+
+      cerr << "Density 1D: " << mean_eps
+           << " " << variance_eps
+           << " " << (result.covariance/HIST_DIM1D/HIST_DIM1D)
+           << " || " << tolerance
+           << " " << result.min
+           << " " << result.max
+           << " || " << result.variance/HIST_DIM1D
+           << " " << 1.0*num_draws*3/HIST_DIM1D*(1.0-1.0/HIST_DIM1D)
+           << " || " << result.covariance/HIST_DIM1D
+           << " " << -1.0*num_draws*3/HIST_DIM1D/HIST_DIM1D
+           << endl;
+    }
+    {
+      cerr << " -- Testing 3-D histogram" << endl;
+
+      RandomProperties result;
+      typedef test_histogram3d_functor<typename RandomGenerator::device_type> functor_type;
+      parallel_reduce (HIST_DIM1D, functor_type (density_3d, num_draws), result);
+
+      double tolerance = 6*sqrt(1.0/HIST_DIM1D);
+      double mean_expect = 1.0*num_draws/HIST_DIM1D;
+      double variance_expect = 1.0*num_draws/HIST_DIM1D*(1.0-1.0/HIST_DIM1D);
+      double covariance_expect = -1.0*num_draws/HIST_DIM1D/HIST_DIM1D;
+      double mean_eps = mean_expect/(result.mean/HIST_DIM1D)-1.0;
+      double variance_eps = variance_expect/(result.variance/HIST_DIM1D)-1.0;
+      double covariance_eps = (result.covariance/HIST_DIM1D - covariance_expect)/mean_expect;
+      pass_hist3d_mean  = ((-tolerance < mean_eps) &&
+                           ( tolerance > mean_eps)) ? 1:0;
+      pass_hist3d_var   = ((-1.2*tolerance < variance_eps) &&
+                           ( 1.2*tolerance > variance_eps)) ? 1:0;
+      pass_hist3d_covar = ((-tolerance < covariance_eps) &&
+                           ( tolerance > covariance_eps)) ? 1:0;
+
+      cerr << "Density 3D: " << mean_eps
+           << " " << variance_eps
+           << " " << result.covariance/HIST_DIM1D/HIST_DIM1D
+           << " || " << tolerance
+           << " " << result.min
+           << " " << result.max << endl;
+    }
+  }
+};
+
+template <class RandomGenerator>
+void test_random(unsigned int num_draws)
+{
+  using std::cerr;
+  using std::endl;
+  typename test_random_functor<RandomGenerator,int>::type_1d density_1d("D1d");
+  typename test_random_functor<RandomGenerator,int>::type_3d density_3d("D3d");
+
+
+  uint64_t ticks = std::chrono::high_resolution_clock::now().time_since_epoch().count();
+  cerr << "Test Seed:" << ticks << endl;
+
+  RandomGenerator pool(ticks);
+
+  cerr << "Test Scalar=int" << endl;
+  test_random_scalar<RandomGenerator,int> test_int(density_1d,density_3d,pool,num_draws);
+  ASSERT_EQ( test_int.pass_mean,1);
+  ASSERT_EQ( test_int.pass_var,1);
+  ASSERT_EQ( test_int.pass_covar,1);
+  ASSERT_EQ( test_int.pass_hist1d_mean,1);
+  ASSERT_EQ( test_int.pass_hist1d_var,1);
+  ASSERT_EQ( test_int.pass_hist1d_covar,1);
+  ASSERT_EQ( test_int.pass_hist3d_mean,1);
+  ASSERT_EQ( test_int.pass_hist3d_var,1);
+  ASSERT_EQ( test_int.pass_hist3d_covar,1);
+  deep_copy(density_1d,0);
+  deep_copy(density_3d,0);
+
+  cerr << "Test Scalar=unsigned int" << endl;
+  test_random_scalar<RandomGenerator,unsigned int> test_uint(density_1d,density_3d,pool,num_draws);
+  ASSERT_EQ( test_uint.pass_mean,1);
+  ASSERT_EQ( test_uint.pass_var,1);
+  ASSERT_EQ( test_uint.pass_covar,1);
+  ASSERT_EQ( test_uint.pass_hist1d_mean,1);
+  ASSERT_EQ( test_uint.pass_hist1d_var,1);
+  ASSERT_EQ( test_uint.pass_hist1d_covar,1);
+  ASSERT_EQ( test_uint.pass_hist3d_mean,1);
+  ASSERT_EQ( test_uint.pass_hist3d_var,1);
+  ASSERT_EQ( test_uint.pass_hist3d_covar,1);
+  deep_copy(density_1d,0);
+  deep_copy(density_3d,0);
+
+  cerr << "Test Scalar=int64_t" << endl;
+  test_random_scalar<RandomGenerator,int64_t> test_int64(density_1d,density_3d,pool,num_draws);
+  ASSERT_EQ( test_int64.pass_mean,1);
+  ASSERT_EQ( test_int64.pass_var,1);
+  ASSERT_EQ( test_int64.pass_covar,1);
+  ASSERT_EQ( test_int64.pass_hist1d_mean,1);
+  ASSERT_EQ( test_int64.pass_hist1d_var,1);
+  ASSERT_EQ( test_int64.pass_hist1d_covar,1);
+  ASSERT_EQ( test_int64.pass_hist3d_mean,1);
+  ASSERT_EQ( test_int64.pass_hist3d_var,1);
+  ASSERT_EQ( test_int64.pass_hist3d_covar,1);
+  deep_copy(density_1d,0);
+  deep_copy(density_3d,0);
+
+  cerr << "Test Scalar=uint64_t" << endl;
+  test_random_scalar<RandomGenerator,uint64_t> test_uint64(density_1d,density_3d,pool,num_draws);
+  ASSERT_EQ( test_uint64.pass_mean,1);
+  ASSERT_EQ( test_uint64.pass_var,1);
+  ASSERT_EQ( test_uint64.pass_covar,1);
+  ASSERT_EQ( test_uint64.pass_hist1d_mean,1);
+  ASSERT_EQ( test_uint64.pass_hist1d_var,1);
+  ASSERT_EQ( test_uint64.pass_hist1d_covar,1);
+  ASSERT_EQ( test_uint64.pass_hist3d_mean,1);
+  ASSERT_EQ( test_uint64.pass_hist3d_var,1);
+  ASSERT_EQ( test_uint64.pass_hist3d_covar,1);
+  deep_copy(density_1d,0);
+  deep_copy(density_3d,0);
+
+  cerr << "Test Scalar=float" << endl;
+  test_random_scalar<RandomGenerator,float> test_float(density_1d,density_3d,pool,num_draws);
+  ASSERT_EQ( test_float.pass_mean,1);
+  ASSERT_EQ( test_float.pass_var,1);
+  ASSERT_EQ( test_float.pass_covar,1);
+  ASSERT_EQ( test_float.pass_hist1d_mean,1);
+  ASSERT_EQ( test_float.pass_hist1d_var,1);
+  ASSERT_EQ( test_float.pass_hist1d_covar,1);
+  ASSERT_EQ( test_float.pass_hist3d_mean,1);
+  ASSERT_EQ( test_float.pass_hist3d_var,1);
+  ASSERT_EQ( test_float.pass_hist3d_covar,1);
+  deep_copy(density_1d,0);
+  deep_copy(density_3d,0);
+
+  cerr << "Test Scalar=double" << endl;
+  test_random_scalar<RandomGenerator,double> test_double(density_1d,density_3d,pool,num_draws);
+  ASSERT_EQ( test_double.pass_mean,1);
+  ASSERT_EQ( test_double.pass_var,1);
+  ASSERT_EQ( test_double.pass_covar,1);
+  ASSERT_EQ( test_double.pass_hist1d_mean,1);
+  ASSERT_EQ( test_double.pass_hist1d_var,1);
+  ASSERT_EQ( test_double.pass_hist1d_covar,1);
+  ASSERT_EQ( test_double.pass_hist3d_mean,1);
+  ASSERT_EQ( test_double.pass_hist3d_var,1);
+  ASSERT_EQ( test_double.pass_hist3d_covar,1);
+}
+}
+
+} // namespace Test
+
+#endif //KOKKOS_TEST_UNORDERED_MAP_HPP
diff --git a/lib/kokkos/algorithms/unit_tests/TestSerial.cpp b/lib/kokkos/algorithms/unit_tests/TestSerial.cpp
new file mode 100644
index 0000000000..741cf97ae1
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/TestSerial.cpp
@@ -0,0 +1,99 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#include <TestRandom.hpp>
+#include <TestSort.hpp>
+#include <iomanip>
+
+
+//----------------------------------------------------------------------------
+
+
+namespace Test {
+
+#ifdef KOKKOS_HAVE_SERIAL
+class serial : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision (5) << std::scientific;
+    Kokkos::Serial::initialize ();
+  }
+
+  static void TearDownTestCase ()
+  {
+    Kokkos::Serial::finalize ();
+  }
+};
+
+#define SERIAL_RANDOM_XORSHIFT64( num_draws )  \
+  TEST_F( serial, Random_XorShift64 ) {                                \
+    Impl::test_random<Kokkos::Random_XorShift64_Pool<Kokkos::Serial> >(num_draws); \
+  }
+
+#define SERIAL_RANDOM_XORSHIFT1024( num_draws )        \
+  TEST_F( serial, Random_XorShift1024 ) {                              \
+    Impl::test_random<Kokkos::Random_XorShift1024_Pool<Kokkos::Serial> >(num_draws); \
+  }
+
+#define SERIAL_SORT_UNSIGNED( size )                                \
+  TEST_F( serial, SortUnsigned ) {   \
+      Impl::test_sort< Kokkos::Serial, unsigned >(size);                                   \
+  }
+
+SERIAL_RANDOM_XORSHIFT64( 10240000 )
+SERIAL_RANDOM_XORSHIFT1024( 10130144 )
+SERIAL_SORT_UNSIGNED(171)
+
+#undef SERIAL_RANDOM_XORSHIFT64
+#undef SERIAL_RANDOM_XORSHIFT1024
+#undef SERIAL_SORT_UNSIGNED
+
+#endif // KOKKOS_HAVE_SERIAL
+} // namespace Test
+
+
diff --git a/lib/kokkos/algorithms/unit_tests/TestSort.hpp b/lib/kokkos/algorithms/unit_tests/TestSort.hpp
new file mode 100644
index 0000000000..ccbcbdd001
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/TestSort.hpp
@@ -0,0 +1,206 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef TESTSORT_HPP_
+#define TESTSORT_HPP_
+
+#include <gtest/gtest.h>
+#include<Kokkos_Core.hpp>
+#include<Kokkos_Random.hpp>
+#include<Kokkos_Sort.hpp>
+
+namespace Test {
+
+namespace Impl{
+
+template<class ExecutionSpace, class Scalar>
+struct is_sorted_struct {
+  typedef unsigned int value_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<Scalar*,ExecutionSpace> keys;
+
+  is_sorted_struct(Kokkos::View<Scalar*,ExecutionSpace> keys_):keys(keys_) {}
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, unsigned int& count) const {
+    if(keys(i)>keys(i+1)) count++;
+  }
+};
+
+template<class ExecutionSpace, class Scalar>
+struct sum {
+  typedef double value_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<Scalar*,ExecutionSpace> keys;
+
+  sum(Kokkos::View<Scalar*,ExecutionSpace> keys_):keys(keys_) {}
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, double& count) const {
+    count+=keys(i);
+  }
+};
+
+template<class ExecutionSpace, class Scalar>
+struct bin3d_is_sorted_struct {
+  typedef unsigned int value_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<Scalar*[3],ExecutionSpace> keys;
+
+  int max_bins;
+  Scalar min;
+  Scalar max;
+
+  bin3d_is_sorted_struct(Kokkos::View<Scalar*[3],ExecutionSpace> keys_,int max_bins_,Scalar min_,Scalar max_):
+    keys(keys_),max_bins(max_bins_),min(min_),max(max_) {
+  }
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, unsigned int& count) const {
+    int ix1 = int ((keys(i,0)-min)/max * max_bins);
+    int iy1 = int ((keys(i,1)-min)/max * max_bins);
+    int iz1 = int ((keys(i,2)-min)/max * max_bins);
+    int ix2 = int ((keys(i+1,0)-min)/max * max_bins);
+    int iy2 = int ((keys(i+1,1)-min)/max * max_bins);
+    int iz2 = int ((keys(i+1,2)-min)/max * max_bins);
+
+    if (ix1>ix2)  count++;
+    else if(ix1==ix2) {
+      if (iy1>iy2)  count++;
+      else if ((iy1==iy2) && (iz1>iz2))  count++;
+    }
+  }
+};
+
+template<class ExecutionSpace, class Scalar>
+struct sum3D {
+  typedef double value_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<Scalar*[3],ExecutionSpace> keys;
+
+  sum3D(Kokkos::View<Scalar*[3],ExecutionSpace> keys_):keys(keys_) {}
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, double& count) const {
+    count+=keys(i,0);
+    count+=keys(i,1);
+    count+=keys(i,2);
+  }
+};
+
+template<class ExecutionSpace, typename KeyType>
+void test_1D_sort(unsigned int n,bool force_kokkos) {
+  typedef Kokkos::View<KeyType*,ExecutionSpace> KeyViewType;
+  KeyViewType keys("Keys",n);
+
+  Kokkos::Random_XorShift64_Pool<ExecutionSpace> g(1931);
+  Kokkos::fill_random(keys,g,Kokkos::Random_XorShift64_Pool<ExecutionSpace>::generator_type::MAX_URAND);
+
+  double sum_before = 0.0;
+  double sum_after = 0.0;
+  unsigned int sort_fails = 0;
+
+  Kokkos::parallel_reduce(n,sum<ExecutionSpace, KeyType>(keys),sum_before);
+
+  Kokkos::sort(keys,force_kokkos);
+
+  Kokkos::parallel_reduce(n,sum<ExecutionSpace, KeyType>(keys),sum_after);
+  Kokkos::parallel_reduce(n-1,is_sorted_struct<ExecutionSpace, KeyType>(keys),sort_fails);
+
+  double ratio = sum_before/sum_after;
+  double epsilon = 1e-10;
+  unsigned int equal_sum = (ratio > (1.0-epsilon)) && (ratio < (1.0+epsilon)) ? 1 : 0;
+
+  ASSERT_EQ(sort_fails,0);
+  ASSERT_EQ(equal_sum,1);
+}
+
+template<class ExecutionSpace, typename KeyType>
+void test_3D_sort(unsigned int n) {
+  typedef Kokkos::View<KeyType*[3],ExecutionSpace > KeyViewType;
+
+  KeyViewType keys("Keys",n*n*n);
+
+  Kokkos::Random_XorShift64_Pool<ExecutionSpace> g(1931);
+  Kokkos::fill_random(keys,g,100.0);
+
+  double sum_before = 0.0;
+  double sum_after = 0.0;
+  unsigned int sort_fails = 0;
+
+  Kokkos::parallel_reduce(keys.dimension_0(),sum3D<ExecutionSpace, KeyType>(keys),sum_before);
+
+  int bin_1d = 1;
+  while( bin_1d*bin_1d*bin_1d*4< (int) keys.dimension_0() ) bin_1d*=2;
+  int bin_max[3] = {bin_1d,bin_1d,bin_1d};
+  typename KeyViewType::value_type min[3] = {0,0,0};
+  typename KeyViewType::value_type max[3] = {100,100,100};
+
+  typedef Kokkos::SortImpl::DefaultBinOp3D< KeyViewType > BinOp;
+  BinOp bin_op(bin_max,min,max);
+  Kokkos::BinSort< KeyViewType , BinOp >
+    Sorter(keys,bin_op,false);
+  Sorter.create_permute_vector();
+  Sorter.template sort< KeyViewType >(keys);
+
+  Kokkos::parallel_reduce(keys.dimension_0(),sum3D<ExecutionSpace, KeyType>(keys),sum_after);
+  Kokkos::parallel_reduce(keys.dimension_0()-1,bin3d_is_sorted_struct<ExecutionSpace, KeyType>(keys,bin_1d,min[0],max[0]),sort_fails);
+
+  double ratio = sum_before/sum_after;
+  double epsilon = 1e-10;
+  unsigned int equal_sum = (ratio > (1.0-epsilon)) && (ratio < (1.0+epsilon)) ? 1 : 0;
+
+  printf("3D Sort Sum: %f %f Fails: %u\n",sum_before,sum_after,sort_fails);
+  ASSERT_EQ(sort_fails,0);
+  ASSERT_EQ(equal_sum,1);
+}
+
+template<class ExecutionSpace, typename KeyType>
+void test_sort(unsigned int N)
+{
+  test_1D_sort<ExecutionSpace,KeyType>(N*N*N, true);
+  test_1D_sort<ExecutionSpace,KeyType>(N*N*N, false);
+  test_3D_sort<ExecutionSpace,KeyType>(N);
+}
+
+}
+}
+#endif /* TESTSORT_HPP_ */
diff --git a/lib/kokkos/algorithms/unit_tests/TestThreads.cpp b/lib/kokkos/algorithms/unit_tests/TestThreads.cpp
new file mode 100644
index 0000000000..a61d6c8bd5
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/TestThreads.cpp
@@ -0,0 +1,113 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#include <TestRandom.hpp>
+#include <TestSort.hpp>
+#include <iomanip>
+
+
+//----------------------------------------------------------------------------
+
+
+namespace Test {
+
+#ifdef KOKKOS_HAVE_PTHREAD
+class threads : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+
+    unsigned num_threads = 4;
+
+    if (Kokkos::hwloc::available()) {
+      num_threads = Kokkos::hwloc::get_available_numa_count()
+                    * Kokkos::hwloc::get_available_cores_per_numa()
+                 // * Kokkos::hwloc::get_available_threads_per_core()
+                    ;
+
+    }
+
+    std::cout << "Threads: " << num_threads << std::endl;
+
+    Kokkos::Threads::initialize( num_threads );
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::Threads::finalize();
+  }
+};
+
+#define THREADS_RANDOM_XORSHIFT64( num_draws )                                \
+  TEST_F( threads, Random_XorShift64 ) {   \
+      Impl::test_random<Kokkos::Random_XorShift64_Pool<Kokkos::Threads> >(num_draws);                                   \
+  }
+
+#define THREADS_RANDOM_XORSHIFT1024( num_draws )                                \
+  TEST_F( threads, Random_XorShift1024 ) {   \
+      Impl::test_random<Kokkos::Random_XorShift1024_Pool<Kokkos::Threads> >(num_draws);                                   \
+  }
+
+#define THREADS_SORT_UNSIGNED( size )                                \
+  TEST_F( threads, SortUnsigned ) {   \
+      Impl::test_sort< Kokkos::Threads, double >(size);                                   \
+  }
+
+
+THREADS_RANDOM_XORSHIFT64( 10240000 )
+THREADS_RANDOM_XORSHIFT1024( 10130144 )
+THREADS_SORT_UNSIGNED(171)
+
+#undef THREADS_RANDOM_XORSHIFT64
+#undef THREADS_RANDOM_XORSHIFT1024
+#undef THREADS_SORT_UNSIGNED
+
+#endif
+} // namespace Test
+
+
diff --git a/lib/kokkos/algorithms/unit_tests/UnitTestMain.cpp b/lib/kokkos/algorithms/unit_tests/UnitTestMain.cpp
new file mode 100644
index 0000000000..f952ab3db5
--- /dev/null
+++ b/lib/kokkos/algorithms/unit_tests/UnitTestMain.cpp
@@ -0,0 +1,50 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+int main(int argc, char *argv[]) {
+  ::testing::InitGoogleTest(&argc,argv);
+  return RUN_ALL_TESTS();
+}
+
diff --git a/lib/kokkos/cmake/Dependencies.cmake b/lib/kokkos/cmake/Dependencies.cmake
new file mode 100644
index 0000000000..8c51eab4d7
--- /dev/null
+++ b/lib/kokkos/cmake/Dependencies.cmake
@@ -0,0 +1,10 @@
+TRIBITS_PACKAGE_DEFINE_DEPENDENCIES(
+  SUBPACKAGES_DIRS_CLASSIFICATIONS_OPTREQS
+    #SubPackageName       Directory         Class    Req/Opt
+    #
+    # New Kokkos subpackages:
+    Core                  core              PS       REQUIRED
+    Containers            containers        PS       OPTIONAL
+    Algorithms            algorithms        PS       OPTIONAL
+    Example               example           EX       OPTIONAL
+  )
diff --git a/lib/kokkos/cmake/deps/CUDA.cmake b/lib/kokkos/cmake/deps/CUDA.cmake
new file mode 100644
index 0000000000..801c20067b
--- /dev/null
+++ b/lib/kokkos/cmake/deps/CUDA.cmake
@@ -0,0 +1,79 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+# Check for CUDA support
+
+SET(_CUDA_FAILURE OFF)
+
+# Have CMake find CUDA
+IF(NOT _CUDA_FAILURE)
+  FIND_PACKAGE(CUDA 3.2)
+  IF (NOT CUDA_FOUND)
+    SET(_CUDA_FAILURE ON)
+  ENDIF()
+ENDIF()
+
+IF(NOT _CUDA_FAILURE)
+  # if we haven't met failure
+  macro(PACKAGE_ADD_CUDA_LIBRARY cuda_target)
+    TRIBITS_ADD_LIBRARY(${cuda_target} ${ARGN} CUDALIBRARY)
+  endmacro()
+  GLOBAL_SET(TPL_CUDA_LIBRARY_DIRS)
+  GLOBAL_SET(TPL_CUDA_INCLUDE_DIRS ${CUDA_TOOLKIT_INCLUDE})
+  GLOBAL_SET(TPL_CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY} ${CUDA_cublas_LIBRARY} ${CUDA_cufft_LIBRARY})
+  TIBITS_CREATE_IMPORTED_TPL_LIBRARY(CUSPARSE)
+ELSE()
+  SET(TPL_ENABLE_CUDA OFF)
+ENDIF()
diff --git a/lib/kokkos/cmake/deps/CUSPARSE.cmake b/lib/kokkos/cmake/deps/CUSPARSE.cmake
new file mode 100644
index 0000000000..205f5e2a98
--- /dev/null
+++ b/lib/kokkos/cmake/deps/CUSPARSE.cmake
@@ -0,0 +1,64 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+include(${TRIBITS_DEPS_DIR}/CUDA.cmake)
+
+IF (TPL_ENABLE_CUDA)
+  GLOBAL_SET(TPL_CUSPARSE_LIBRARY_DIRS)
+  GLOBAL_SET(TPL_CUSPARSE_INCLUDE_DIRS ${TPL_CUDA_INCLUDE_DIRS})
+  GLOBAL_SET(TPL_CUSPARSE_LIBRARIES    ${CUDA_cusparse_LIBRARY})
+  TIBITS_CREATE_IMPORTED_TPL_LIBRARY(CUSPARSE)
+ENDIF()
+
diff --git a/lib/kokkos/cmake/deps/HWLOC.cmake b/lib/kokkos/cmake/deps/HWLOC.cmake
new file mode 100644
index 0000000000..275abd3a5d
--- /dev/null
+++ b/lib/kokkos/cmake/deps/HWLOC.cmake
@@ -0,0 +1,70 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+
+#-----------------------------------------------------------------------------
+#  Hardware locality detection and control library.
+#
+#  Acquisition information:
+#    Date checked:  November 2011
+#    Checked by:    H. Carter Edwards <hcedwar AT sandia.gov>
+#    Source:        http://www.open-mpi.org/projects/hwloc/
+#    Version:       1.3
+#
+
+TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( HWLOC
+  REQUIRED_HEADERS hwloc.h
+  REQUIRED_LIBS_NAMES "hwloc"
+  )
diff --git a/lib/kokkos/cmake/deps/Pthread.cmake b/lib/kokkos/cmake/deps/Pthread.cmake
new file mode 100644
index 0000000000..46d0a939ca
--- /dev/null
+++ b/lib/kokkos/cmake/deps/Pthread.cmake
@@ -0,0 +1,83 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+
+SET(USE_THREADS FALSE)
+
+IF(NOT TPL_Pthread_INCLUDE_DIRS AND NOT TPL_Pthread_LIBRARY_DIRS AND NOT TPL_Pthread_LIBRARIES)
+  # Use CMake's Thread finder since it is a bit smarter in determining
+  # whether pthreads is already built into the compiler and doesn't need
+  # a library to link.
+  FIND_PACKAGE(Threads)
+  #If Threads found a copy of pthreads make sure it is one of the cases the tribits
+  #tpl system cannot handle.
+  IF(Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
+    IF(CMAKE_THREAD_LIBS_INIT STREQUAL "" OR CMAKE_THREAD_LIBS_INIT STREQUAL "-pthread")
+      SET(USE_THREADS TRUE)
+    ENDIF()
+  ENDIF()
+ENDIF()
+
+IF(USE_THREADS)
+  SET(TPL_Pthread_INCLUDE_DIRS "")
+  SET(TPL_Pthread_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
+  SET(TPL_Pthread_LIBRARY_DIRS "")
+  TIBITS_CREATE_IMPORTED_TPL_LIBRARY(Pthread)
+ELSE()
+  TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( Pthread
+    REQUIRED_HEADERS pthread.h
+    REQUIRED_LIBS_NAMES pthread
+      )
+ENDIF()
diff --git a/lib/kokkos/cmake/deps/QTHREAD.cmake b/lib/kokkos/cmake/deps/QTHREAD.cmake
new file mode 100644
index 0000000000..994b72b200
--- /dev/null
+++ b/lib/kokkos/cmake/deps/QTHREAD.cmake
@@ -0,0 +1,70 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+
+#-----------------------------------------------------------------------------
+#  Hardware locality detection and control library.
+#
+#  Acquisition information:
+#    Date checked:  July 2014
+#    Checked by:    H. Carter Edwards <hcedwar AT sandia.gov>
+#    Source:        https://code.google.com/p/qthreads
+#
+
+TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( QTHREAD
+  REQUIRED_HEADERS qthread.h
+  REQUIRED_LIBS_NAMES "qthread"
+  )
+
diff --git a/lib/kokkos/cmake/tpls/FindTPLCUSPARSE.cmake b/lib/kokkos/cmake/tpls/FindTPLCUSPARSE.cmake
new file mode 100644
index 0000000000..aad1e2bad7
--- /dev/null
+++ b/lib/kokkos/cmake/tpls/FindTPLCUSPARSE.cmake
@@ -0,0 +1,75 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+# Check for CUDA support
+
+IF (NOT TPL_ENABLE_CUDA OR CUDA_VERSION VERSION_LESS "4.1")
+  MESSAGE(FATAL_ERROR "\nCUSPARSE: did not find acceptable version of CUDA libraries (4.1 or greater)")
+ELSE()
+  IF(CMAKE_VERSION VERSION_LESS "2.8.8")
+    # FindCUDA before CMake 2.8.8 does not find cusparse library; therefore, we must
+    find_library(CUDA_cusparse_LIBRARY
+      cusparse
+      HINTS ${CUDA_TOOLKIT_ROOT_DIR}/lib
+      )
+    IF(CUDA_cusparse_LIBRARY STREQUAL "CUDA_cusparse_LIBRARY-NOTFOUND") 
+      MESSAGE(FATAL_ERROR "\nCUSPARSE: could not find cuspasre library.")
+    ENDIF()
+  ENDIF(CMAKE_VERSION VERSION_LESS "2.8.8")
+  GLOBAL_SET(TPL_CUSPARSE_LIBRARY_DIRS)
+  GLOBAL_SET(TPL_CUSPARSE_INCLUDE_DIRS ${TPL_CUDA_INCLUDE_DIRS})
+  GLOBAL_SET(TPL_CUSPARSE_LIBRARIES    ${CUDA_cusparse_LIBRARY})
+ENDIF()
+
diff --git a/lib/kokkos/cmake/tpls/FindTPLHWLOC.cmake b/lib/kokkos/cmake/tpls/FindTPLHWLOC.cmake
new file mode 100644
index 0000000000..715b3e9bde
--- /dev/null
+++ b/lib/kokkos/cmake/tpls/FindTPLHWLOC.cmake
@@ -0,0 +1,71 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+
+#-----------------------------------------------------------------------------
+#  Hardware locality detection and control library.
+#
+#  Acquisition information:
+#    Date checked:  November 2011
+#    Checked by:    H. Carter Edwards <hcedwar AT sandia.gov>
+#    Source:        http://www.open-mpi.org/projects/hwloc/
+#    Version:       1.3
+#
+
+TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( HWLOC
+  REQUIRED_HEADERS hwloc.h
+  REQUIRED_LIBS_NAMES "hwloc"
+  )
+
diff --git a/lib/kokkos/cmake/tpls/FindTPLPthread.cmake b/lib/kokkos/cmake/tpls/FindTPLPthread.cmake
new file mode 100644
index 0000000000..fc401d7543
--- /dev/null
+++ b/lib/kokkos/cmake/tpls/FindTPLPthread.cmake
@@ -0,0 +1,82 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+
+SET(USE_THREADS FALSE)
+
+IF(NOT TPL_Pthread_INCLUDE_DIRS AND NOT TPL_Pthread_LIBRARY_DIRS AND NOT TPL_Pthread_LIBRARIES)
+  # Use CMake's Thread finder since it is a bit smarter in determining
+  # whether pthreads is already built into the compiler and doesn't need
+  # a library to link.
+  FIND_PACKAGE(Threads)
+  #If Threads found a copy of pthreads make sure it is one of the cases the tribits
+  #tpl system cannot handle.
+  IF(Threads_FOUND AND CMAKE_USE_PTHREADS_INIT)
+    IF(CMAKE_THREAD_LIBS_INIT STREQUAL "" OR CMAKE_THREAD_LIBS_INIT STREQUAL "-pthread")
+      SET(USE_THREADS TRUE)
+    ENDIF()
+  ENDIF()
+ENDIF()
+
+IF(USE_THREADS)
+  SET(TPL_Pthread_INCLUDE_DIRS "")
+  SET(TPL_Pthread_LIBRARIES "${CMAKE_THREAD_LIBS_INIT}")
+  SET(TPL_Pthread_LIBRARY_DIRS "")
+ELSE()
+  TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( Pthread
+    REQUIRED_HEADERS pthread.h
+    REQUIRED_LIBS_NAMES pthread
+      )
+ENDIF()
diff --git a/lib/kokkos/cmake/tpls/FindTPLQTHREAD.cmake b/lib/kokkos/cmake/tpls/FindTPLQTHREAD.cmake
new file mode 100644
index 0000000000..994b72b200
--- /dev/null
+++ b/lib/kokkos/cmake/tpls/FindTPLQTHREAD.cmake
@@ -0,0 +1,70 @@
+# @HEADER
+# ************************************************************************
+#
+#            Trilinos: An Object-Oriented Solver Framework
+#                 Copyright (2001) Sandia Corporation
+#
+#
+# Copyright (2001) Sandia Corporation. Under the terms of Contract
+# DE-AC04-94AL85000, there is a non-exclusive license for use of this
+# work by or on behalf of the U.S. Government.  Export of this program
+# may require a license from the United States Government.
+#
+# 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.
+#
+# 3. Neither the name of the Corporation nor the names of the
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+# 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.
+#
+# NOTICE:  The United States Government is granted for itself and others
+# acting on its behalf a paid-up, nonexclusive, irrevocable worldwide
+# license in this data to reproduce, prepare derivative works, and
+# perform publicly and display publicly.  Beginning five (5) years from
+# July 25, 2001, the United States Government is granted for itself and
+# others acting on its behalf a paid-up, nonexclusive, irrevocable
+# worldwide license in this data to reproduce, prepare derivative works,
+# distribute copies to the public, perform publicly and display
+# publicly, and to permit others to do so.
+#
+# NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT
+# OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES
+# ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR
+# RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY
+# INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS
+# THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS.
+#
+# ************************************************************************
+# @HEADER
+
+
+#-----------------------------------------------------------------------------
+#  Hardware locality detection and control library.
+#
+#  Acquisition information:
+#    Date checked:  July 2014
+#    Checked by:    H. Carter Edwards <hcedwar AT sandia.gov>
+#    Source:        https://code.google.com/p/qthreads
+#
+
+TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES( QTHREAD
+  REQUIRED_HEADERS qthread.h
+  REQUIRED_LIBS_NAMES "qthread"
+  )
+
diff --git a/lib/kokkos/cmake/tribits.cmake b/lib/kokkos/cmake/tribits.cmake
new file mode 100644
index 0000000000..34cd216f81
--- /dev/null
+++ b/lib/kokkos/cmake/tribits.cmake
@@ -0,0 +1,485 @@
+INCLUDE(CMakeParseArguments)
+INCLUDE(CTest)
+
+FUNCTION(ASSERT_DEFINED VARS)
+  FOREACH(VAR ${VARS})
+    IF(NOT DEFINED ${VAR})
+      MESSAGE(SEND_ERROR "Error, the variable ${VAR} is not defined!")
+    ENDIF()
+  ENDFOREACH()
+ENDFUNCTION()
+
+MACRO(GLOBAL_SET VARNAME)
+  SET(${VARNAME} ${ARGN} CACHE INTERNAL "")
+ENDMACRO()
+
+MACRO(PREPEND_GLOBAL_SET VARNAME)
+  ASSERT_DEFINED(${VARNAME})
+  GLOBAL_SET(${VARNAME} ${ARGN} ${${VARNAME}})
+ENDMACRO()
+
+FUNCTION(REMOVE_GLOBAL_DUPLICATES VARNAME)
+  ASSERT_DEFINED(${VARNAME})
+  IF (${VARNAME})
+    SET(TMP ${${VARNAME}})
+    LIST(REMOVE_DUPLICATES TMP)
+    GLOBAL_SET(${VARNAME} ${TMP})
+  ENDIF()
+ENDFUNCTION()
+
+MACRO(TRIBITS_ADD_OPTION_AND_DEFINE  USER_OPTION_NAME  MACRO_DEFINE_NAME DOCSTRING  DEFAULT_VALUE)
+  MESSAGE(STATUS "TRIBITS_ADD_OPTION_AND_DEFINE: '${USER_OPTION_NAME}' '${MACRO_DEFINE_NAME}' '${DEFAULT_VALUE}'")
+  SET( ${USER_OPTION_NAME} "${DEFAULT_VALUE}" CACHE BOOL "${DOCSTRING}" )
+  IF(NOT ${MACRO_DEFINE_NAME} STREQUAL "")
+    IF(${USER_OPTION_NAME})
+      GLOBAL_SET(${MACRO_DEFINE_NAME} ON)
+    ELSE()
+      GLOBAL_SET(${MACRO_DEFINE_NAME} OFF)
+    ENDIF()
+  ENDIF()
+ENDMACRO()
+
+FUNCTION(TRIBITS_CONFIGURE_FILE  PACKAGE_NAME_CONFIG_FILE)
+
+  # Configure the file
+  CONFIGURE_FILE(
+    ${PACKAGE_SOURCE_DIR}/cmake/${PACKAGE_NAME_CONFIG_FILE}.in
+    ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME_CONFIG_FILE}
+    )
+
+ENDFUNCTION()
+
+MACRO(TRIBITS_ADD_DEBUG_OPTION)
+  TRIBITS_ADD_OPTION_AND_DEFINE(
+    ${PROJECT_NAME}_ENABLE_DEBUG
+    HAVE_${PROJECT_NAME_UC}_DEBUG
+    "Enable a host of runtime debug checking."
+    OFF
+    )
+ENDMACRO()
+
+
+MACRO(TRIBITS_ADD_TEST_DIRECTORIES)
+  FOREACH(TEST_DIR ${ARGN})
+    ADD_SUBDIRECTORY(${TEST_DIR})
+  ENDFOREACH()
+ENDMACRO()
+
+MACRO(TRIBITS_ADD_EXAMPLE_DIRECTORIES)
+
+  IF(${PACKAGE_NAME}_ENABLE_EXAMPLES OR ${PARENT_PACKAGE_NAME}_ENABLE_EXAMPLES)
+    FOREACH(EXAMPLE_DIR ${ARGN})
+      ADD_SUBDIRECTORY(${EXAMPLE_DIR})
+    ENDFOREACH()
+  ENDIF()
+
+ENDMACRO()
+
+MACRO(TARGET_TRANSFER_PROPERTY TARGET_NAME PROP_IN PROP_OUT)
+  SET(PROP_VALUES)
+  FOREACH(TARGET_X ${ARGN})
+    LIST(APPEND PROP_VALUES "$<TARGET_PROPERTY:${TARGET_X},${PROP_IN}>")
+  ENDFOREACH()
+  SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES ${PROP_OUT} "${PROP_VALUES}")
+ENDMACRO()
+
+MACRO(ADD_INTERFACE_LIBRARY LIB_NAME)
+  FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp "")
+  ADD_LIBRARY(${LIB_NAME} STATIC ${CMAKE_CURRENT_BINARY_DIR}/dummy.cpp)
+  SET_TARGET_PROPERTIES(${LIB_NAME} PROPERTIES INTERFACE TRUE)
+ENDMACRO()
+
+# Older versions of cmake does not make include directories transitive
+MACRO(TARGET_LINK_AND_INCLUDE_LIBRARIES TARGET_NAME)
+  TARGET_LINK_LIBRARIES(${TARGET_NAME} LINK_PUBLIC ${ARGN})
+  FOREACH(DEP_LIB ${ARGN})
+    TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC $<TARGET_PROPERTY:${DEP_LIB},INTERFACE_INCLUDE_DIRECTORIES>)
+    TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC $<TARGET_PROPERTY:${DEP_LIB},INCLUDE_DIRECTORIES>)
+  ENDFOREACH()
+ENDMACRO()
+
+FUNCTION(TRIBITS_ADD_LIBRARY LIBRARY_NAME)
+
+  SET(options STATIC SHARED TESTONLY NO_INSTALL_LIB_OR_HEADERS CUDALIBRARY)
+  SET(oneValueArgs)
+  SET(multiValueArgs HEADERS HEADERS_INSTALL_SUBDIR NOINSTALLHEADERS SOURCES DEPLIBS IMPORTEDLIBS DEFINES ADDED_LIB_TARGET_NAME_OUT)
+
+  CMAKE_PARSE_ARGUMENTS(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  IF(PARSE_HEADERS)
+    LIST(REMOVE_DUPLICATES PARSE_HEADERS)
+  ENDIF()
+  IF(PARSE_SOURCES)
+    LIST(REMOVE_DUPLICATES PARSE_SOURCES)
+  ENDIF()
+
+  # Local variable to hold all of the libraries that will be directly linked
+  # to this library.
+  SET(LINK_LIBS ${${PACKAGE_NAME}_DEPS})
+
+  # Add dependent libraries passed directly in
+
+  IF (PARSE_IMPORTEDLIBS)
+    LIST(APPEND LINK_LIBS ${PARSE_IMPORTEDLIBS})
+  ENDIF()
+
+  IF (PARSE_DEPLIBS)
+    LIST(APPEND LINK_LIBS ${PARSE_DEPLIBS})
+  ENDIF()
+
+  # Add the library and all the dependencies
+
+  IF (PARSE_DEFINES)
+    ADD_DEFINITIONS(${PARSE_DEFINES})
+  ENDIF()
+
+  IF (PARSE_STATIC)
+    SET(STATIC_KEYWORD "STATIC")
+  ELSE()
+    SET(STATIC_KEYWORD)
+  ENDIF()
+
+  IF (PARSE_SHARED)
+    SET(SHARED_KEYWORD "SHARED")
+  ELSE()
+    SET(SHARED_KEYWORD)
+  ENDIF()
+
+  IF (PARSE_TESTONLY)
+    SET(EXCLUDE_FROM_ALL_KEYWORD "EXCLUDE_FROM_ALL")
+  ELSE()
+    SET(EXCLUDE_FROM_ALL_KEYWORD)
+  ENDIF()
+  IF (NOT PARSE_CUDALIBRARY)
+    ADD_LIBRARY(
+      ${LIBRARY_NAME}
+      ${STATIC_KEYWORD}
+      ${SHARED_KEYWORD}
+      ${EXCLUDE_FROM_ALL_KEYWORD}
+      ${PARSE_HEADERS}
+      ${PARSE_NOINSTALLHEADERS}
+      ${PARSE_SOURCES}
+      )
+  ELSE()
+    CUDA_ADD_LIBRARY(
+      ${LIBRARY_NAME}
+      ${PARSE_HEADERS}
+      ${PARSE_NOINSTALLHEADERS}
+      ${PARSE_SOURCES}
+      )
+  ENDIF()
+
+  TARGET_LINK_AND_INCLUDE_LIBRARIES(${LIBRARY_NAME} ${LINK_LIBS})
+
+  IF (NOT PARSE_TESTONLY OR PARSE_NO_INSTALL_LIB_OR_HEADERS)
+
+    INSTALL(
+      TARGETS ${LIBRARY_NAME}
+      EXPORT ${PROJECT_NAME}
+      RUNTIME DESTINATION bin
+      LIBRARY DESTINATION lib
+      ARCHIVE DESTINATION lib
+      COMPONENT ${PACKAGE_NAME}
+      )
+
+    INSTALL(
+      FILES  ${PARSE_HEADERS}
+      EXPORT ${PROJECT_NAME}
+      DESTINATION include
+      COMPONENT ${PACKAGE_NAME}
+      )
+
+      INSTALL(
+      DIRECTORY  ${PARSE_HEADERS_INSTALL_SUBDIR}
+      EXPORT ${PROJECT_NAME}
+      DESTINATION include
+      COMPONENT ${PACKAGE_NAME}
+      )
+
+  ENDIF()
+
+  IF (NOT PARSE_TESTONLY)
+    PREPEND_GLOBAL_SET(${PACKAGE_NAME}_LIBS ${LIBRARY_NAME})
+    REMOVE_GLOBAL_DUPLICATES(${PACKAGE_NAME}_LIBS)
+  ENDIF()
+
+ENDFUNCTION()
+
+FUNCTION(TRIBITS_ADD_EXECUTABLE EXE_NAME)
+
+  SET(options NOEXEPREFIX NOEXESUFFIX ADD_DIR_TO_NAME INSTALLABLE TESTONLY)
+  SET(oneValueArgs ADDED_EXE_TARGET_NAME_OUT)
+  SET(multiValueArgs SOURCES CATEGORIES HOST XHOST HOSTTYPE XHOSTTYPE DIRECTORY TESTONLYLIBS IMPORTEDLIBS DEPLIBS COMM LINKER_LANGUAGE TARGET_DEFINES DEFINES)
+
+  CMAKE_PARSE_ARGUMENTS(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  IF (PARSE_TARGET_DEFINES)
+    TARGET_COMPILE_DEFINITIONS(${EXE_NAME} PUBLIC ${PARSE_TARGET_DEFINES})
+  ENDIF()
+
+  SET(LINK_LIBS PACKAGE_${PACKAGE_NAME})
+
+  IF (PARSE_TESTONLYLIBS)
+    LIST(APPEND LINK_LIBS ${PARSE_TESTONLYLIBS})
+  ENDIF()
+
+  IF (PARSE_IMPORTEDLIBS)
+    LIST(APPEND LINK_LIBS ${PARSE_IMPORTEDLIBS})
+  ENDIF()
+
+  SET (EXE_SOURCES)
+  IF(PARSE_DIRECTORY)
+    FOREACH( SOURCE_FILE ${PARSE_SOURCES} )
+      IF(IS_ABSOLUTE ${SOURCE_FILE})
+        SET (EXE_SOURCES ${EXE_SOURCES} ${SOURCE_FILE})
+      ELSE()
+        SET (EXE_SOURCES ${EXE_SOURCES} ${PARSE_DIRECTORY}/${SOURCE_FILE})
+      ENDIF()
+    ENDFOREACH( )
+  ELSE()
+    FOREACH( SOURCE_FILE ${PARSE_SOURCES} )
+      SET (EXE_SOURCES ${EXE_SOURCES} ${SOURCE_FILE})
+    ENDFOREACH( )
+  ENDIF()
+
+  SET(EXE_BINARY_NAME ${EXE_NAME})
+  IF(DEFINED PACKAGE_NAME AND NOT PARSE_NOEXEPREFIX)
+    SET(EXE_BINARY_NAME ${PACKAGE_NAME}_${EXE_BINARY_NAME})
+  ENDIF()
+
+  IF (PARSE_TESTONLY)
+    SET(EXCLUDE_FROM_ALL_KEYWORD "EXCLUDE_FROM_ALL")
+  ELSE()
+    SET(EXCLUDE_FROM_ALL_KEYWORD)
+  ENDIF()
+  ADD_EXECUTABLE(${EXE_BINARY_NAME} ${EXCLUDE_FROM_ALL_KEYWORD} ${EXE_SOURCES})
+
+  TARGET_LINK_AND_INCLUDE_LIBRARIES(${EXE_BINARY_NAME} ${LINK_LIBS})
+
+  IF(PARSE_ADDED_EXE_TARGET_NAME_OUT)
+    SET(${PARSE_ADDED_EXE_TARGET_NAME_OUT} ${EXE_BINARY_NAME} PARENT_SCOPE)
+  ENDIF()
+
+  IF(PARSE_INSTALLABLE)
+    INSTALL(
+      TARGETS ${EXE_BINARY_NAME}
+      EXPORT ${PROJECT_NAME}
+        DESTINATION bin
+    )
+  ENDIF()
+ENDFUNCTION()
+
+ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND} -VV -C ${CMAKE_CFG_INTDIR})
+
+FUNCTION(TRIBITS_ADD_EXECUTABLE_AND_TEST EXE_NAME)
+
+  SET(options STANDARD_PASS_OUTPUT WILL_FAIL)
+  SET(oneValueArgs PASS_REGULAR_EXPRESSION FAIL_REGULAR_EXPRESSION ENVIRONMENT TIMEOUT CATEGORIES ADDED_TESTS_NAMES_OUT ADDED_EXE_TARGET_NAME_OUT)
+  SET(multiValueArgs)
+
+  CMAKE_PARSE_ARGUMENTS(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  TRIBITS_ADD_EXECUTABLE(${EXE_NAME} TESTONLY ADDED_EXE_TARGET_NAME_OUT TEST_NAME ${PARSE_UNPARSED_ARGUMENTS})
+
+  IF(WIN32)
+    ADD_TEST(NAME ${TEST_NAME} WORKING_DIRECTORY ${LIBRARY_OUTPUT_PATH} COMMAND ${TEST_NAME}${CMAKE_EXECUTABLE_SUFFIX})
+  ELSE()
+    ADD_TEST(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
+  ENDIF()
+  ADD_DEPENDENCIES(check ${TEST_NAME})
+
+  IF(PARSE_FAIL_REGULAR_EXPRESSION)
+    SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES FAIL_REGULAR_EXPRESSION ${PARSE_FAIL_REGULAR_EXPRESSION})
+  ENDIF()
+
+  IF(PARSE_PASS_REGULAR_EXPRESSION)
+    SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES PASS_REGULAR_EXPRESSION ${PARSE_PASS_REGULAR_EXPRESSION})
+  ENDIF()
+
+  IF(PARSE_WILL_FAIL)
+    SET_TESTS_PROPERTIES(${TEST_NAME} PROPERTIES WILL_FAIL ${PARSE_WILL_FAIL})
+  ENDIF()
+
+  IF(PARSE_ADDED_TESTS_NAMES_OUT)
+    SET(${PARSE_ADDED_TESTS_NAMES_OUT} ${TEST_NAME} PARENT_SCOPE)
+  ENDIF()
+
+  IF(PARSE_ADDED_EXE_TARGET_NAME_OUT)
+    SET(${PARSE_ADDED_EXE_TARGET_NAME_OUT} ${TEST_NAME} PARENT_SCOPE)
+  ENDIF()
+
+ENDFUNCTION()
+
+MACRO(TIBITS_CREATE_IMPORTED_TPL_LIBRARY TPL_NAME)
+  ADD_INTERFACE_LIBRARY(TPL_LIB_${TPL_NAME})
+  TARGET_LINK_LIBRARIES(TPL_LIB_${TPL_NAME} LINK_PUBLIC ${TPL_${TPL_NAME}_LIBRARIES})
+  TARGET_INCLUDE_DIRECTORIES(TPL_LIB_${TPL_NAME} INTERFACE ${TPL_${TPL_NAME}_INCLUDE_DIRS})
+ENDMACRO()
+
+FUNCTION(TRIBITS_TPL_FIND_INCLUDE_DIRS_AND_LIBRARIES TPL_NAME)
+
+  SET(options MUST_FIND_ALL_LIBS MUST_FIND_ALL_HEADERS NO_PRINT_ENABLE_SUCCESS_FAIL)
+  SET(oneValueArgs)
+  SET(multiValueArgs REQUIRED_HEADERS REQUIRED_LIBS_NAMES)
+
+  CMAKE_PARSE_ARGUMENTS(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  SET(_${TPL_NAME}_ENABLE_SUCCESS TRUE)
+  IF (PARSE_REQUIRED_LIBS_NAMES)
+    FIND_LIBRARY(TPL_${TPL_NAME}_LIBRARIES NAMES ${PARSE_REQUIRED_LIBS_NAMES})
+    IF(NOT TPL_${TPL_NAME}_LIBRARIES)
+      SET(_${TPL_NAME}_ENABLE_SUCCESS FALSE)
+    ENDIF()
+  ENDIF()
+  IF (PARSE_REQUIRED_HEADERS)
+    FIND_PATH(TPL_${TPL_NAME}_INCLUDE_DIRS NAMES ${PARSE_REQUIRED_HEADERS})
+    IF(NOT TPL_${TPL_NAME}_INCLUDE_DIRS)
+      SET(_${TPL_NAME}_ENABLE_SUCCESS FALSE)
+    ENDIF()
+  ENDIF()
+
+
+  IF (_${TPL_NAME}_ENABLE_SUCCESS)
+    TIBITS_CREATE_IMPORTED_TPL_LIBRARY(${TPL_NAME})
+  ENDIF()
+
+ENDFUNCTION()
+
+MACRO(TRIBITS_PROCESS_TPL_DEP_FILE TPL_FILE)
+  GET_FILENAME_COMPONENT(TPL_NAME ${TPL_FILE} NAME_WE)
+  INCLUDE("${TPL_FILE}")
+  IF(TARGET TPL_LIB_${TPL_NAME})
+    MESSAGE(STATUS "Found tpl library: ${TPL_NAME}")
+    SET(TPL_ENABLE_${TPL_NAME} TRUE)
+  ELSE()
+    MESSAGE(STATUS "Tpl library not found: ${TPL_NAME}")
+    SET(TPL_ENABLE_${TPL_NAME} FALSE)
+  ENDIF()
+ENDMACRO()
+
+MACRO(PREPEND_TARGET_SET VARNAME TARGET_NAME TYPE)
+  IF(TYPE STREQUAL "REQUIRED")
+    SET(REQUIRED TRUE)
+  ELSE()
+    SET(REQUIRED FALSE)
+  ENDIF()
+  IF(TARGET ${TARGET_NAME})
+    PREPEND_GLOBAL_SET(${VARNAME} ${TARGET_NAME})
+  ELSE()
+    IF(REQUIRED)
+      MESSAGE(FATAL_ERROR "Missing dependency ${TARGET_NAME}")
+    ENDIF()
+  ENDIF()
+ENDMACRO()
+
+MACRO(TRIBITS_APPEND_PACKAGE_DEPS DEP_LIST TYPE)
+  FOREACH(DEP ${ARGN})
+    PREPEND_GLOBAL_SET(${DEP_LIST} PACKAGE_${DEP})
+  ENDFOREACH()
+ENDMACRO()
+
+MACRO(TRIBITS_APPEND_TPLS_DEPS DEP_LIST TYPE)
+  FOREACH(DEP ${ARGN})
+    PREPEND_TARGET_SET(${DEP_LIST} TPL_LIB_${DEP} ${TYPE})
+  ENDFOREACH()
+ENDMACRO()
+
+MACRO(TRIBITS_ENABLE_TPLS)
+  FOREACH(TPL ${ARGN})
+    IF(TARGET ${TPL})
+      GLOBAL_SET(${PACKAGE_NAME}_ENABLE_${TPL} TRUE)
+    ELSE()
+      GLOBAL_SET(${PACKAGE_NAME}_ENABLE_${TPL} FALSE)
+    ENDIF()
+  ENDFOREACH()
+ENDMACRO()
+
+MACRO(TRIBITS_PACKAGE_DEFINE_DEPENDENCIES)
+
+  SET(options)
+  SET(oneValueArgs)
+  SET(multiValueArgs 
+    LIB_REQUIRED_PACKAGES
+    LIB_OPTIONAL_PACKAGES
+    TEST_REQUIRED_PACKAGES
+    TEST_OPTIONAL_PACKAGES
+    LIB_REQUIRED_TPLS
+    LIB_OPTIONAL_TPLS
+    TEST_REQUIRED_TPLS
+    TEST_OPTIONAL_TPLS
+    REGRESSION_EMAIL_LIST
+    SUBPACKAGES_DIRS_CLASSIFICATIONS_OPTREQS
+  )
+  CMAKE_PARSE_ARGUMENTS(PARSE "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  GLOBAL_SET(${PACKAGE_NAME}_DEPS "")
+  TRIBITS_APPEND_PACKAGE_DEPS(${PACKAGE_NAME}_DEPS REQUIRED ${PARSE_LIB_REQUIRED_PACKAGES})
+  TRIBITS_APPEND_PACKAGE_DEPS(${PACKAGE_NAME}_DEPS OPTIONAL ${PARSE_LIB_OPTIONAL_PACKAGES})
+  TRIBITS_APPEND_TPLS_DEPS(${PACKAGE_NAME}_DEPS REQUIRED ${PARSE_LIB_REQUIRED_TPLS})
+  TRIBITS_APPEND_TPLS_DEPS(${PACKAGE_NAME}_DEPS OPTIONAL ${PARSE_LIB_OPTIONAL_TPLS})
+
+  GLOBAL_SET(${PACKAGE_NAME}_TEST_DEPS "")
+  TRIBITS_APPEND_PACKAGE_DEPS(${PACKAGE_NAME}_TEST_DEPS REQUIRED ${PARSE_TEST_REQUIRED_PACKAGES})
+  TRIBITS_APPEND_PACKAGE_DEPS(${PACKAGE_NAME}_TEST_DEPS OPTIONAL ${PARSE_TEST_OPTIONAL_PACKAGES})
+  TRIBITS_APPEND_TPLS_DEPS(${PACKAGE_NAME}_TEST_DEPS REQUIRED ${PARSE_TEST_REQUIRED_TPLS})
+  TRIBITS_APPEND_TPLS_DEPS(${PACKAGE_NAME}_TEST_DEPS OPTIONAL ${PARSE_TEST_OPTIONAL_TPLS})
+
+  TRIBITS_ENABLE_TPLS(${PARSE_LIB_REQUIRED_TPLS} ${PARSE_LIB_OPTIONAL_TPLS} ${PARSE_TEST_REQUIRED_TPLS} ${PARSE_TEST_OPTIONAL_TPLS})
+
+ENDMACRO()
+
+MACRO(TRIBITS_SUBPACKAGE NAME)
+  SET(PACKAGE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+  SET(PARENT_PACKAGE_NAME ${PACKAGE_NAME})
+  SET(PACKAGE_NAME ${PACKAGE_NAME}${NAME})
+  STRING(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UC)
+
+  ADD_INTERFACE_LIBRARY(PACKAGE_${PACKAGE_NAME})
+
+  GLOBAL_SET(${PACKAGE_NAME}_LIBS "")
+
+  INCLUDE(${PACKAGE_SOURCE_DIR}/cmake/Dependencies.cmake)
+
+ENDMACRO(TRIBITS_SUBPACKAGE)
+
+MACRO(TRIBITS_SUBPACKAGE_POSTPROCESS)
+  TARGET_LINK_AND_INCLUDE_LIBRARIES(PACKAGE_${PACKAGE_NAME} ${${PACKAGE_NAME}_LIBS})
+ENDMACRO(TRIBITS_SUBPACKAGE_POSTPROCESS)
+
+MACRO(TRIBITS_PACKAGE_DECL NAME)
+
+  PROJECT(${NAME})
+  STRING(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UC)
+  SET(PACKAGE_NAME ${PROJECT_NAME})
+  STRING(TOUPPER ${PACKAGE_NAME} PACKAGE_NAME_UC)
+
+  SET(TRIBITS_DEPS_DIR "${CMAKE_SOURCE_DIR}/cmake/deps")
+  FILE(GLOB TPLS_FILES "${TRIBITS_DEPS_DIR}/*.cmake")
+  FOREACH(TPL_FILE ${TPLS_FILES})
+    TRIBITS_PROCESS_TPL_DEP_FILE(${TPL_FILE})
+  ENDFOREACH()
+
+ENDMACRO()
+
+
+MACRO(TRIBITS_PROCESS_SUBPACKAGES)
+  FILE(GLOB SUBPACKAGES RELATIVE ${CMAKE_SOURCE_DIR} */cmake/Dependencies.cmake)
+  FOREACH(SUBPACKAGE ${SUBPACKAGES})
+    GET_FILENAME_COMPONENT(SUBPACKAGE_CMAKE ${SUBPACKAGE} DIRECTORY)
+    GET_FILENAME_COMPONENT(SUBPACKAGE_DIR ${SUBPACKAGE_CMAKE} DIRECTORY)
+    ADD_SUBDIRECTORY(${SUBPACKAGE_DIR})
+  ENDFOREACH()
+ENDMACRO(TRIBITS_PROCESS_SUBPACKAGES)
+
+MACRO(TRIBITS_PACKAGE_DEF)
+ENDMACRO(TRIBITS_PACKAGE_DEF)
+
+MACRO(TRIBITS_EXCLUDE_AUTOTOOLS_FILES)
+ENDMACRO(TRIBITS_EXCLUDE_AUTOTOOLS_FILES)
+
+MACRO(TRIBITS_EXCLUDE_FILES)
+ENDMACRO(TRIBITS_EXCLUDE_FILES)
+
+MACRO(TRIBITS_PACKAGE_POSTPROCESS)
+ENDMACRO(TRIBITS_PACKAGE_POSTPROCESS)
+
diff --git a/lib/kokkos/config/configure_compton_cpu.sh b/lib/kokkos/config/configure_compton_cpu.sh
new file mode 100755
index 0000000000..17287fb848
--- /dev/null
+++ b/lib/kokkos/config/configure_compton_cpu.sh
@@ -0,0 +1,190 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+# Additional command-line arguments given to this script will be
+# passed directly to CMake.
+#
+
+#
+# Force CMake to re-evaluate build options.
+#
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#-----------------------------------------------------------------------------
+# Incrementally construct cmake configure options:
+
+CMAKE_CONFIGURE=""
+
+#-----------------------------------------------------------------------------
+# Location of Trilinos source tree:
+
+CMAKE_PROJECT_DIR="${HOME}/Trilinos"
+
+# Location for installation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=/home/projects/kokkos/host/`date +%F`"
+
+#-----------------------------------------------------------------------------
+# General build options.
+# Use a variable so options can be propagated to CUDA compiler.
+
+CMAKE_VERBOSE_MAKEFILE=OFF
+CMAKE_BUILD_TYPE=RELEASE
+# CMAKE_BUILD_TYPE=DEBUG
+
+#-----------------------------------------------------------------------------
+# Build for CUDA architecture:
+
+CUDA_ARCH=""
+# CUDA_ARCH="20"
+# CUDA_ARCH="30"
+# CUDA_ARCH="35"
+
+# Build with Intel compiler
+
+INTEL=ON
+
+# Build for MIC architecture:
+
+# INTEL_XEON_PHI=ON
+
+# Build with HWLOC at location:
+
+HWLOC_BASE_DIR="/home/projects/libraries/host/hwloc/1.6.2"
+
+# Location for MPI to use in examples:
+
+MPI_BASE_DIR=""
+
+#-----------------------------------------------------------------------------
+# MPI configuation only used for examples:
+#
+# Must have the MPI_BASE_DIR so that the
+# include path can be passed to the Cuda compiler
+
+if [ -n "${MPI_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D MPI_BASE_DIR:PATH=${MPI_BASE_DIR}"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# Pthread configuation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# OpenMP configuation:
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Configure packages for kokkos-only:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Hardware locality cmake configuration:
+
+if [ -n "${HWLOC_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+fi
+
+#-----------------------------------------------------------------------------
+# Cuda cmake configuration:
+
+if [ -n "${CUDA_ARCH}" ] ;
+then
+
+  # Options to CUDA_NVCC_FLAGS must be semi-colon delimited,
+  # this is different than the standard CMAKE_CXX_FLAGS syntax.
+
+  CUDA_NVCC_FLAGS="-gencode;arch=compute_${CUDA_ARCH},code=sm_${CUDA_ARCH}"
+  CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi"
+
+  if [ "${CMAKE_BUILD_TYPE}" = "DEBUG" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-g"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-O3"
+  fi
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_VERBOSE_BUILD:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_NVCC_FLAGS:STRING=${CUDA_NVCC_FLAGS}"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+if [ "${INTEL}" = "ON" -o "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=icc"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=icpc"
+fi
+
+#-----------------------------------------------------------------------------
+
+# Cross-compile for Intel Xeon Phi:
+
+if [ "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_SYSTEM_NAME=Linux"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_Fortran_COMPILER:FILEPATH=ifort"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_DIRS:FILEPATH=${MKLROOT}/lib/mic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_NAMES='mkl_intel_lp64;mkl_sequential;mkl_core;pthread;m'"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CHECKED_STL:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_WARNINGS_AS_ERRORS_FLAGS:STRING=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BUILD_SHARED_LIBS:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D DART_TESTING_TIMEOUT:STRING=600"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_LIBRARY_NAMES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_LAPACK_LIBRARIES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_BinUtils=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_Pthread_LIBRARIES=pthread"
+
+  # Cannot cross-compile fortran compatibility checks on the MIC:
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+
+  # Tell cmake the answers to compile-and-execute tests
+  # to prevent cmake from executing a cross-compiled program.
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_GCC_ABI_DEMANGLE_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_TEUCHOS_BLASFLOAT_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_SLAPY2_WORKS_EXITCODE=0"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_VERBOSE_MAKEFILE:BOOL=${CMAKE_VERBOSE_MAKEFILE}"
+
+#-----------------------------------------------------------------------------
+
+echo "cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}"
+
+cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/configure_compton_mic.sh b/lib/kokkos/config/configure_compton_mic.sh
new file mode 100755
index 0000000000..7f9aee13f9
--- /dev/null
+++ b/lib/kokkos/config/configure_compton_mic.sh
@@ -0,0 +1,186 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+# Additional command-line arguments given to this script will be
+# passed directly to CMake.
+#
+
+#
+# Force CMake to re-evaluate build options.
+#
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#-----------------------------------------------------------------------------
+# Incrementally construct cmake configure options:
+
+CMAKE_CONFIGURE=""
+
+#-----------------------------------------------------------------------------
+# Location of Trilinos source tree:
+
+CMAKE_PROJECT_DIR="${HOME}/Trilinos"
+
+# Location for installation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=/home/projects/kokkos/mic/`date +%F`"
+
+#-----------------------------------------------------------------------------
+# General build options.
+# Use a variable so options can be propagated to CUDA compiler.
+
+CMAKE_VERBOSE_MAKEFILE=OFF
+CMAKE_BUILD_TYPE=RELEASE
+# CMAKE_BUILD_TYPE=DEBUG
+
+#-----------------------------------------------------------------------------
+# Build for CUDA architecture:
+
+CUDA_ARCH=""
+# CUDA_ARCH="20"
+# CUDA_ARCH="30"
+# CUDA_ARCH="35"
+
+# Build for MIC architecture:
+
+INTEL_XEON_PHI=ON
+
+# Build with HWLOC at location:
+
+HWLOC_BASE_DIR="/home/projects/libraries/mic/hwloc/1.6.2"
+
+# Location for MPI to use in examples:
+
+MPI_BASE_DIR=""
+
+#-----------------------------------------------------------------------------
+# MPI configuation only used for examples:
+#
+# Must have the MPI_BASE_DIR so that the
+# include path can be passed to the Cuda compiler
+
+if [ -n "${MPI_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D MPI_BASE_DIR:PATH=${MPI_BASE_DIR}"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# Pthread configuation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# OpenMP configuation:
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Configure packages for kokkos-only:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Hardware locality cmake configuration:
+
+if [ -n "${HWLOC_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+fi
+
+#-----------------------------------------------------------------------------
+# Cuda cmake configuration:
+
+if [ -n "${CUDA_ARCH}" ] ;
+then
+
+  # Options to CUDA_NVCC_FLAGS must be semi-colon delimited,
+  # this is different than the standard CMAKE_CXX_FLAGS syntax.
+
+  CUDA_NVCC_FLAGS="-gencode;arch=compute_${CUDA_ARCH},code=sm_${CUDA_ARCH}"
+  CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi"
+
+  if [ "${CMAKE_BUILD_TYPE}" = "DEBUG" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-g"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-O3"
+  fi
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_VERBOSE_BUILD:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_NVCC_FLAGS:STRING=${CUDA_NVCC_FLAGS}"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+if [ "${INTEL}" = "ON" -o "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=icc"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=icpc"
+fi
+
+#-----------------------------------------------------------------------------
+
+# Cross-compile for Intel Xeon Phi:
+
+if [ "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_SYSTEM_NAME=Linux"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_Fortran_COMPILER:FILEPATH=ifort"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_DIRS:FILEPATH=${MKLROOT}/lib/mic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_NAMES='mkl_intel_lp64;mkl_sequential;mkl_core;pthread;m'"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CHECKED_STL:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_WARNINGS_AS_ERRORS_FLAGS:STRING=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BUILD_SHARED_LIBS:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D DART_TESTING_TIMEOUT:STRING=600"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_LIBRARY_NAMES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_LAPACK_LIBRARIES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_BinUtils=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_Pthread_LIBRARIES=pthread"
+
+  # Cannot cross-compile fortran compatibility checks on the MIC:
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+
+  # Tell cmake the answers to compile-and-execute tests
+  # to prevent cmake from executing a cross-compiled program.
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_GCC_ABI_DEMANGLE_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_TEUCHOS_BLASFLOAT_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_SLAPY2_WORKS_EXITCODE=0"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_VERBOSE_MAKEFILE:BOOL=${CMAKE_VERBOSE_MAKEFILE}"
+
+#-----------------------------------------------------------------------------
+
+echo "cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}"
+
+cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/configure_kokkos.sh b/lib/kokkos/config/configure_kokkos.sh
new file mode 100755
index 0000000000..592e7f5936
--- /dev/null
+++ b/lib/kokkos/config/configure_kokkos.sh
@@ -0,0 +1,293 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# General build options.
+# Use a variable so options can be propagated to CUDA compiler.
+
+CMAKE_BUILD_TYPE=RELEASE
+# CMAKE_BUILD_TYPE=DEBUG
+
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+#-----------------------------------------------------------------------------
+
+USE_CUDA_ARCH=
+USE_THREAD=
+USE_OPENMP=
+USE_INTEL=
+USE_XEON_PHI=
+HWLOC_BASE_DIR=
+MPI_BASE_DIR=
+BLAS_LIB_DIR=
+LAPACK_LIB_DIR=
+
+if [ 1 ] ; then
+  # Platform 'kokkos-dev' with Cuda, OpenMP, hwloc, mpi, gnu
+  USE_CUDA_ARCH="35"
+  USE_OPENMP=ON
+  HWLOC_BASE_DIR="/home/projects/hwloc/1.7.1/host/gnu/4.4.7"
+  MPI_BASE_DIR="/home/projects/mvapich/2.0.0b/gnu/4.4.7"
+  BLAS_LIB_DIR="/home/projects/blas/host/gnu/lib"
+  LAPACK_LIB_DIR="/home/projects/lapack/host/gnu/lib"
+
+elif [ ] ; then
+  # Platform 'kokkos-dev' with Cuda, Threads, hwloc, mpi, gnu
+  USE_CUDA_ARCH="35"
+  USE_THREAD=ON
+  HWLOC_BASE_DIR="/home/projects/hwloc/1.7.1/host/gnu/4.4.7"
+  MPI_BASE_DIR="/home/projects/mvapich/2.0.0b/gnu/4.4.7"
+  BLAS_LIB_DIR="/home/projects/blas/host/gnu/lib"
+  LAPACK_LIB_DIR="/home/projects/lapack/host/gnu/lib"
+
+elif [ ] ; then
+  # Platform 'kokkos-dev' with Xeon Phi and hwloc
+  USE_OPENMP=ON
+  USE_INTEL=ON
+  USE_XEON_PHI=ON
+  HWLOC_BASE_DIR="/home/projects/hwloc/1.7.1/mic/intel/13.SP1.1.106"
+
+elif [ ] ; then
+  # Platform 'kokkos-nvidia' with Cuda, OpenMP, hwloc, mpi, gnu
+  USE_CUDA_ARCH="20"
+  USE_OPENMP=ON
+  HWLOC_BASE_DIR="/home/sems/common/hwloc/current"
+  MPI_BASE_DIR="/home/sems/common/openmpi/current"
+
+elif [ ] ; then
+  # Platform 'kokkos-nvidia' with Cuda, Threads, hwloc, mpi, gnu
+  USE_CUDA_ARCH="20"
+  USE_THREAD=ON
+  HWLOC_BASE_DIR="/home/sems/common/hwloc/current"
+  MPI_BASE_DIR="/home/sems/common/openmpi/current"
+
+fi
+
+#-----------------------------------------------------------------------------
+# Incrementally construct cmake configure command line options:
+
+CMAKE_CONFIGURE=""
+CMAKE_CXX_FLAGS=""
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+
+if [ 1 ] ; then
+
+  # Configure for Tpetra/Kokkos:
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_DIRS:FILEPATH=${BLAS_LIB_DIR}"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_LIBRARY_DIRS:FILEPATH=${LAPACK_LIB_DIR}"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Tpetra:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Kokkos:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraClassic:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TeuchosKokkosCompat:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TeuchosKokkosComm:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Tpetra_ENABLE_Kokkos_Refactor:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D KokkosClassic_DefaultNode:STRING=Kokkos::Compat::KokkosOpenMPWrapperNode"
+
+  CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS}-DKOKKOS_FAST_COMPILE"
+
+  if [ -n "${USE_CUDA_ARCH}" ] ; then
+
+    CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Cuda:BOOL=ON"
+
+  fi
+
+fi
+
+if [ 1 ] ; then
+
+  # Configure for Stokhos:
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Sacado:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Stokhos:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Stokhos_ENABLE_Belos:BOOL=ON"
+
+fi
+
+if [ 1 ] ; then
+
+  # Configure for TrilinosCouplings:
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TrilinosCouplings:BOOL=ON"
+
+fi
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_VERBOSE_MAKEFILE:BOOL=ON"
+
+if [ "${CMAKE_BUILD_TYPE}" == "DEBUG" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+fi
+
+#-----------------------------------------------------------------------------
+# Location for installation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# MPI configuation only used for examples:
+#
+# Must have the MPI_BASE_DIR so that the
+# include path can be passed to the Cuda compiler
+
+if [ -n "${MPI_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D MPI_BASE_DIR:PATH=${MPI_BASE_DIR}"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# Kokkos use pthread configuation:
+
+if [ "${USE_THREAD}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=ON"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# Kokkos use OpenMP configuation:
+
+if [ "${USE_OPENMP}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_OpenMP:BOOL=ON"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_OpenMP:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# Hardware locality configuration:
+
+if [ -n "${HWLOC_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+fi
+
+#-----------------------------------------------------------------------------
+# Cuda cmake configuration:
+
+if [ -n "${USE_CUDA_ARCH}" ] ;
+then
+
+  # Options to CUDA_NVCC_FLAGS must be semi-colon delimited,
+  # this is different than the standard CMAKE_CXX_FLAGS syntax.
+
+  CUDA_NVCC_FLAGS="-DKOKKOS_HAVE_CUDA_ARCH=${USE_CUDA_ARCH}0;-gencode;arch=compute_${USE_CUDA_ARCH},code=sm_${USE_CUDA_ARCH}"
+
+  if [ "${USE_OPENMP}" = "ON" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi,-fopenmp"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi"
+  fi
+
+  if [ "${CMAKE_BUILD_TYPE}" = "DEBUG" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-g"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-O3"
+  fi
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_VERBOSE_BUILD:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_NVCC_FLAGS:STRING=${CUDA_NVCC_FLAGS}"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+if [ "${USE_INTEL}" = "ON" -o "${USE_XEON_PHI}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=icc"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=icpc"
+fi
+
+# Cross-compile for Intel Xeon Phi:
+
+if [ "${USE_XEON_PHI}" = "ON" ] ;
+then
+
+  CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS} -mmic"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_SYSTEM_NAME=Linux"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_Fortran_COMPILER:FILEPATH=ifort"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_DIRS:FILEPATH=${MKLROOT}/lib/mic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_NAMES='mkl_intel_lp64;mkl_sequential;mkl_core;pthread;m'"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CHECKED_STL:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_WARNINGS_AS_ERRORS_FLAGS:STRING=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BUILD_SHARED_LIBS:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D DART_TESTING_TIMEOUT:STRING=600"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_LIBRARY_NAMES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_LAPACK_LIBRARIES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_BinUtils=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_Pthread_LIBRARIES=pthread"
+
+  # Cannot cross-compile fortran compatibility checks on the MIC:
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+
+  # Tell cmake the answers to compile-and-execute tests
+  # to prevent cmake from executing a cross-compiled program.
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_GCC_ABI_DEMANGLE_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_TEUCHOS_BLASFLOAT_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_SLAPY2_WORKS_EXITCODE=0"
+
+fi
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+
+if [ -n "${CMAKE_CXX_FLAGS}" ] ; then
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING='${CMAKE_CXX_FLAGS}'"
+
+fi
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo "cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}"
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/configure_kokkos_bgq.sh b/lib/kokkos/config/configure_kokkos_bgq.sh
new file mode 100755
index 0000000000..73236937ea
--- /dev/null
+++ b/lib/kokkos/config/configure_kokkos_bgq.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+# Additional command-line arguments given to this script will be
+# passed directly to CMake.
+#
+
+# to build:
+# build on bgq-b[1-12]
+# module load sierra-devel
+# run this configure file
+# make
+
+# to run:
+# ssh bgq-login
+# cd /scratch/username/...
+# export OMP_PROC_BIND and XLSMPOPTS environment variables
+# run with srun
+
+# Note: hwloc does not work to get or set cpubindings on bgq.
+# Use the openmp backend and the openmp environment variables.
+#
+# Only the mpi wrappers seem to be setup for cross-compile,
+# so it is important that this configure enables MPI and uses mpigcc wrappers.
+
+
+
+#
+# Force CMake to re-evaluate build options.
+#
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#-----------------------------------------------------------------------------
+# Incrementally construct cmake configure options:
+
+CMAKE_CONFIGURE=""
+
+#-----------------------------------------------------------------------------
+# Location of Trilinos source tree:
+
+CMAKE_PROJECT_DIR="../Trilinos"
+
+# Location for installation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=../TrilinosInstall/`date +%F`"
+
+#-----------------------------------------------------------------------------
+# General build options.
+# Use a variable so options can be propagated to CUDA compiler.
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=mpigcc-4.7.2"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=mpig++-4.7.2"
+
+CMAKE_VERBOSE_MAKEFILE=OFF
+CMAKE_BUILD_TYPE=RELEASE
+# CMAKE_BUILD_TYPE=DEBUG
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Configure packages for kokkos-only:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_VERBOSE_MAKEFILE:BOOL=${CMAKE_VERBOSE_MAKEFILE}"
+
+#-----------------------------------------------------------------------------
+
+echo "cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}"
+
+cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/configure_kokkos_dev.sh b/lib/kokkos/config/configure_kokkos_dev.sh
new file mode 100755
index 0000000000..ac61dec602
--- /dev/null
+++ b/lib/kokkos/config/configure_kokkos_dev.sh
@@ -0,0 +1,216 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+# Additional command-line arguments given to this script will be
+# passed directly to CMake.
+#
+
+#
+# Force CMake to re-evaluate build options.
+#
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#-----------------------------------------------------------------------------
+# Incrementally construct cmake configure options:
+
+CMAKE_CONFIGURE=""
+
+#-----------------------------------------------------------------------------
+# Location of Trilinos source tree:
+
+CMAKE_PROJECT_DIR="${HOME}/Trilinos"
+
+# Location for installation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${HOME}/TrilinosInstall/`date +%F`"
+
+#-----------------------------------------------------------------------------
+# General build options.
+# Use a variable so options can be propagated to CUDA compiler.
+
+CMAKE_VERBOSE_MAKEFILE=OFF
+CMAKE_BUILD_TYPE=RELEASE
+#CMAKE_BUILD_TYPE=DEBUG
+#CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Build for CUDA architecture:
+
+#CUDA_ARCH=""
+#CUDA_ARCH="20"
+#CUDA_ARCH="30"
+CUDA_ARCH="35"
+
+# Build with OpenMP
+
+OPENMP=ON
+PTHREADS=ON
+
+# Build host code with Intel compiler:
+
+INTEL=OFF
+
+# Build for MIC architecture:
+
+INTEL_XEON_PHI=OFF
+
+# Build with HWLOC at location:
+
+#HWLOC_BASE_DIR=""
+#HWLOC_BASE_DIR="/home/projects/hwloc/1.7.1/host/gnu/4.4.7"
+HWLOC_BASE_DIR="/home/projects/hwloc/1.7.1/host/gnu/4.7.3"
+
+# Location for MPI to use in examples:
+
+#MPI_BASE_DIR=""
+#MPI_BASE_DIR="/home/projects/mvapich/2.0.0b/gnu/4.4.7"
+MPI_BASE_DIR="/home/projects/mvapich/2.0.0b/gnu/4.7.3"
+#MPI_BASE_DIR="/home/projects/openmpi/1.7.3/llvm/2013-12-02/"
+
+#-----------------------------------------------------------------------------
+# MPI configuation only used for examples:
+#
+# Must have the MPI_BASE_DIR so that the
+# include path can be passed to the Cuda compiler
+
+if [ -n "${MPI_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D MPI_BASE_DIR:PATH=${MPI_BASE_DIR}"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# Pthread configuation:
+
+if [ "${PTHREADS}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# OpenMP configuation:
+
+if [ "${OPENMP}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Configure packages for kokkos-only:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Hardware locality cmake configuration:
+
+if [ -n "${HWLOC_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+fi
+
+#-----------------------------------------------------------------------------
+# Cuda cmake configuration:
+
+if [ -n "${CUDA_ARCH}" ] ;
+then
+
+  # Options to CUDA_NVCC_FLAGS must be semi-colon delimited,
+  # this is different than the standard CMAKE_CXX_FLAGS syntax.
+
+  CUDA_NVCC_FLAGS="-gencode;arch=compute_${CUDA_ARCH},code=sm_${CUDA_ARCH}"
+
+  if [ "${OPENMP}" = "ON" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi,-fopenmp"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi"
+  fi
+
+  if [ "${CMAKE_BUILD_TYPE}" = "DEBUG" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-g"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-O3"
+  fi
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_VERBOSE_BUILD:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_NVCC_FLAGS:STRING=${CUDA_NVCC_FLAGS}"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+if [ "${INTEL}" = "ON" -o "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=icc"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=icpc"
+fi
+
+#-----------------------------------------------------------------------------
+
+# Cross-compile for Intel Xeon Phi:
+
+if [ "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_SYSTEM_NAME=Linux"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_Fortran_COMPILER:FILEPATH=ifort"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_DIRS:FILEPATH=${MKLROOT}/lib/mic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_NAMES='mkl_intel_lp64;mkl_sequential;mkl_core;pthread;m'"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CHECKED_STL:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_WARNINGS_AS_ERRORS_FLAGS:STRING=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BUILD_SHARED_LIBS:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D DART_TESTING_TIMEOUT:STRING=600"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_LIBRARY_NAMES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_LAPACK_LIBRARIES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_BinUtils=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_Pthread_LIBRARIES=pthread"
+
+  # Cannot cross-compile fortran compatibility checks on the MIC:
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+
+  # Tell cmake the answers to compile-and-execute tests
+  # to prevent cmake from executing a cross-compiled program.
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_GCC_ABI_DEMANGLE_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_TEUCHOS_BLASFLOAT_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_SLAPY2_WORKS_EXITCODE=0"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_VERBOSE_MAKEFILE:BOOL=${CMAKE_VERBOSE_MAKEFILE}"
+
+#-----------------------------------------------------------------------------
+
+echo "cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}"
+
+cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/configure_kokkos_nvidia.sh b/lib/kokkos/config/configure_kokkos_nvidia.sh
new file mode 100755
index 0000000000..f78b7dce78
--- /dev/null
+++ b/lib/kokkos/config/configure_kokkos_nvidia.sh
@@ -0,0 +1,204 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+# Additional command-line arguments given to this script will be
+# passed directly to CMake.
+#
+
+#
+# Force CMake to re-evaluate build options.
+#
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#-----------------------------------------------------------------------------
+# Incrementally construct cmake configure options:
+
+CMAKE_CONFIGURE=""
+
+#-----------------------------------------------------------------------------
+# Location of Trilinos source tree:
+
+CMAKE_PROJECT_DIR="${HOME}/Trilinos"
+
+# Location for installation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=/home/sems/common/kokkos/`date +%F`"
+
+#-----------------------------------------------------------------------------
+# General build options.
+# Use a variable so options can be propagated to CUDA compiler.
+
+CMAKE_VERBOSE_MAKEFILE=OFF
+CMAKE_BUILD_TYPE=RELEASE
+# CMAKE_BUILD_TYPE=DEBUG
+
+#-----------------------------------------------------------------------------
+# Build for CUDA architecture:
+
+# CUDA_ARCH=""
+CUDA_ARCH="20"
+# CUDA_ARCH="30"
+# CUDA_ARCH="35"
+
+# Build with OpenMP
+
+OPENMP=ON
+
+# Build host code with Intel compiler:
+
+# INTEL=ON
+
+# Build for MIC architecture:
+
+# INTEL_XEON_PHI=ON
+
+# Build with HWLOC at location:
+
+HWLOC_BASE_DIR="/home/sems/common/hwloc/current"
+
+# Location for MPI to use in examples:
+
+MPI_BASE_DIR="/home/sems/common/openmpi/current"
+
+#-----------------------------------------------------------------------------
+# MPI configuation only used for examples:
+#
+# Must have the MPI_BASE_DIR so that the
+# include path can be passed to the Cuda compiler
+
+if [ -n "${MPI_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D MPI_BASE_DIR:PATH=${MPI_BASE_DIR}"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# Pthread configuation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# OpenMP configuation:
+
+if [ "${OPENMP}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Configure packages for kokkos-only:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Hardware locality cmake configuration:
+
+if [ -n "${HWLOC_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+fi
+
+#-----------------------------------------------------------------------------
+# Cuda cmake configuration:
+
+if [ -n "${CUDA_ARCH}" ] ;
+then
+
+  # Options to CUDA_NVCC_FLAGS must be semi-colon delimited,
+  # this is different than the standard CMAKE_CXX_FLAGS syntax.
+
+  CUDA_NVCC_FLAGS="-gencode;arch=compute_${CUDA_ARCH},code=sm_${CUDA_ARCH}"
+
+  if [ "${OPENMP}" = "ON" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi,-fopenmp"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi"
+  fi
+
+  if [ "${CMAKE_BUILD_TYPE}" = "DEBUG" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-g"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-O3"
+  fi
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_VERBOSE_BUILD:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_NVCC_FLAGS:STRING=${CUDA_NVCC_FLAGS}"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+if [ "${INTEL}" = "ON" -o "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=icc"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=icpc"
+fi
+
+#-----------------------------------------------------------------------------
+
+# Cross-compile for Intel Xeon Phi:
+
+if [ "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_SYSTEM_NAME=Linux"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_Fortran_COMPILER:FILEPATH=ifort"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_DIRS:FILEPATH=${MKLROOT}/lib/mic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_NAMES='mkl_intel_lp64;mkl_sequential;mkl_core;pthread;m'"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CHECKED_STL:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_WARNINGS_AS_ERRORS_FLAGS:STRING=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BUILD_SHARED_LIBS:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D DART_TESTING_TIMEOUT:STRING=600"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_LIBRARY_NAMES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_LAPACK_LIBRARIES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_BinUtils=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_Pthread_LIBRARIES=pthread"
+
+  # Cannot cross-compile fortran compatibility checks on the MIC:
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+
+  # Tell cmake the answers to compile-and-execute tests
+  # to prevent cmake from executing a cross-compiled program.
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_GCC_ABI_DEMANGLE_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_TEUCHOS_BLASFLOAT_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_SLAPY2_WORKS_EXITCODE=0"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_VERBOSE_MAKEFILE:BOOL=${CMAKE_VERBOSE_MAKEFILE}"
+
+#-----------------------------------------------------------------------------
+
+echo "cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}"
+
+cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/configure_shannon.sh b/lib/kokkos/config/configure_shannon.sh
new file mode 100755
index 0000000000..8bd175b031
--- /dev/null
+++ b/lib/kokkos/config/configure_shannon.sh
@@ -0,0 +1,190 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+# Additional command-line arguments given to this script will be
+# passed directly to CMake.
+#
+
+#
+# Force CMake to re-evaluate build options.
+#
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#-----------------------------------------------------------------------------
+# Incrementally construct cmake configure options:
+
+CMAKE_CONFIGURE=""
+
+#-----------------------------------------------------------------------------
+# Location of Trilinos source tree:
+
+CMAKE_PROJECT_DIR="${HOME}/Trilinos"
+
+# Location for installation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=/home/projects/kokkos/`date +%F`"
+
+#-----------------------------------------------------------------------------
+# General build options.
+# Use a variable so options can be propagated to CUDA compiler.
+
+CMAKE_VERBOSE_MAKEFILE=OFF
+CMAKE_BUILD_TYPE=RELEASE
+# CMAKE_BUILD_TYPE=DEBUG
+
+#-----------------------------------------------------------------------------
+# Build for CUDA architecture:
+
+# CUDA_ARCH=""
+# CUDA_ARCH="20"
+# CUDA_ARCH="30"
+CUDA_ARCH="35"
+
+# Build host code with Intel compiler:
+
+INTEL=ON
+
+# Build for MIC architecture:
+
+# INTEL_XEON_PHI=ON
+
+# Build with HWLOC at location:
+
+HWLOC_BASE_DIR="/home/projects/hwloc/1.6.2"
+
+# Location for MPI to use in examples:
+
+MPI_BASE_DIR=""
+
+#-----------------------------------------------------------------------------
+# MPI configuation only used for examples:
+#
+# Must have the MPI_BASE_DIR so that the
+# include path can be passed to the Cuda compiler
+
+if [ -n "${MPI_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D MPI_BASE_DIR:PATH=${MPI_BASE_DIR}"
+else
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_MPI:BOOL=OFF"
+fi
+
+#-----------------------------------------------------------------------------
+# Pthread configuation:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# OpenMP configuation:
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Configure packages for kokkos-only:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#-----------------------------------------------------------------------------
+# Hardware locality cmake configuration:
+
+if [ -n "${HWLOC_BASE_DIR}" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+fi
+
+#-----------------------------------------------------------------------------
+# Cuda cmake configuration:
+
+if [ -n "${CUDA_ARCH}" ] ;
+then
+
+  # Options to CUDA_NVCC_FLAGS must be semi-colon delimited,
+  # this is different than the standard CMAKE_CXX_FLAGS syntax.
+
+  CUDA_NVCC_FLAGS="-gencode;arch=compute_${CUDA_ARCH},code=sm_${CUDA_ARCH}"
+  CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi"
+
+  if [ "${CMAKE_BUILD_TYPE}" = "DEBUG" ] ;
+  then
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-g"
+  else
+    CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-O3"
+  fi
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_VERBOSE_BUILD:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CUDA_NVCC_FLAGS:STRING=${CUDA_NVCC_FLAGS}"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+if [ "${INTEL}" = "ON" -o "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=icc"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=icpc"
+fi
+
+#-----------------------------------------------------------------------------
+
+# Cross-compile for Intel Xeon Phi:
+
+if [ "${INTEL_XEON_PHI}" = "ON" ] ;
+then
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_SYSTEM_NAME=Linux"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_FLAGS:STRING=-mmic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_Fortran_COMPILER:FILEPATH=ifort"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_DIRS:FILEPATH=${MKLROOT}/lib/mic"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BLAS_LIBRARY_NAMES='mkl_intel_lp64;mkl_sequential;mkl_core;pthread;m'"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CHECKED_STL:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_WARNINGS_AS_ERRORS_FLAGS:STRING=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D BUILD_SHARED_LIBS:BOOL=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D DART_TESTING_TIMEOUT:STRING=600"
+
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_LIBRARY_NAMES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_LAPACK_LIBRARIES=''"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_BinUtils=OFF"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_Pthread_LIBRARIES=pthread"
+
+  # Cannot cross-compile fortran compatibility checks on the MIC:
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+
+  # Tell cmake the answers to compile-and-execute tests
+  # to prevent cmake from executing a cross-compiled program.
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_GCC_ABI_DEMANGLE_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HAVE_TEUCHOS_BLASFLOAT_EXITCODE=0"
+  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D LAPACK_SLAPY2_WORKS_EXITCODE=0"
+
+fi
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_VERBOSE_MAKEFILE:BOOL=${CMAKE_VERBOSE_MAKEFILE}"
+
+#-----------------------------------------------------------------------------
+
+echo "cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}"
+
+cmake ${CMAKE_CONFIGURE} ${CMAKE_PROJECT_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/configure_tpetra_kokkos_cuda_nvcc_wrapper.sh b/lib/kokkos/config/configure_tpetra_kokkos_cuda_nvcc_wrapper.sh
new file mode 100755
index 0000000000..0baa83aefe
--- /dev/null
+++ b/lib/kokkos/config/configure_tpetra_kokkos_cuda_nvcc_wrapper.sh
@@ -0,0 +1,140 @@
+#!/bin/bash
+#
+# This script uses CUDA, OpenMP, and MPI.
+#
+# Before invoking this script, set the OMPI_CXX environment variable
+# to point to nvcc_wrapper, wherever it happens to live.  (If you use
+# an MPI implementation other than OpenMPI, set the corresponding
+# environment variable instead.)
+#
+
+rm -f CMakeCache.txt;
+rm -rf CMakeFiles
+EXTRA_ARGS=$@
+MPI_PATH="/opt/mpi/openmpi/1.8.2/nvcc-gcc/4.8.3-6.5"
+CUDA_PATH="/opt/nvidia/cuda/6.5.14"
+
+#
+# As long as there are any .cu files in Trilinos, we'll need to set
+# CUDA_NVCC_FLAGS.  If Trilinos gets rid of all of its .cu files and
+# lets nvcc_wrapper handle them as .cpp files, then we won't need to
+# set CUDA_NVCC_FLAGS.  As it is, given that we need to set
+# CUDA_NVCC_FLAGS, we must make sure that they are the same flags as
+# nvcc_wrapper passes to nvcc.
+#
+CUDA_NVCC_FLAGS="-gencode;arch=compute_35,code=sm_35;-I${MPI_PATH}/include"
+CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-Xcompiler;-Wall,-ansi,-fopenmp"
+CUDA_NVCC_FLAGS="${CUDA_NVCC_FLAGS};-O3;-DKOKKOS_USE_CUDA_UVM"
+
+cmake \
+  -D CMAKE_INSTALL_PREFIX:PATH="$PWD/../install/" \
+  -D CMAKE_BUILD_TYPE:STRING=DEBUG \
+  -D CMAKE_CXX_FLAGS:STRING="-g -Wall" \
+  -D CMAKE_C_FLAGS:STRING="-g -Wall" \
+  -D CMAKE_FORTRAN_FLAGS:STRING="" \
+  -D CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS="" \
+  -D Trilinos_ENABLE_Triutils=OFF \
+  -D Trilinos_ENABLE_INSTALL_CMAKE_CONFIG_FILES:BOOL=OFF \
+  -D Trilinos_ENABLE_DEBUG:BOOL=OFF \
+  -D Trilinos_ENABLE_CHECKED_STL:BOOL=OFF \
+  -D Trilinos_ENABLE_EXPLICIT_INSTANTIATION:BOOL=OFF \
+  -D Trilinos_WARNINGS_AS_ERRORS_FLAGS:STRING="" \
+  -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF \
+  -D Trilinos_ENABLE_ALL_OPTIONAL_PACKAGES:BOOL=OFF \
+  -D BUILD_SHARED_LIBS:BOOL=OFF \
+  -D DART_TESTING_TIMEOUT:STRING=600 \
+  -D CMAKE_VERBOSE_MAKEFILE:BOOL=OFF \
+  \
+  \
+  -D CMAKE_CXX_COMPILER:FILEPATH="${MPI_PATH}/bin/mpicxx" \
+  -D CMAKE_C_COMPILER:FILEPATH="${MPI_PATH}/bin/mpicc" \
+  -D MPI_CXX_COMPILER:FILEPATH="${MPI_PATH}/bin/mpicxx" \
+  -D MPI_C_COMPILER:FILEPATH="${MPI_PATH}/bin/mpicc" \
+  -D CMAKE_Fortran_COMPILER:FILEPATH="${MPI_PATH}/bin/mpif77" \
+  -D MPI_EXEC:FILEPATH="${MPI_PATH}/bin/mpirun" \
+  -D MPI_EXEC_POST_NUMPROCS_FLAGS:STRING="-bind-to;socket;--map-by;socket;env;CUDA_MANAGED_FORCE_DEVICE_ALLOC=1;CUDA_LAUNCH_BLOCKING=1;OMP_NUM_THREADS=2" \
+  \
+  \
+  -D Trilinos_ENABLE_CXX11:BOOL=OFF \
+  -D TPL_ENABLE_MPI:BOOL=ON \
+  -D Trilinos_ENABLE_OpenMP:BOOL=ON \
+  -D Trilinos_ENABLE_ThreadPool:BOOL=ON \
+  \
+  \
+  -D TPL_ENABLE_CUDA:BOOL=ON \
+  -D CUDA_TOOLKIT_ROOT_DIR:FILEPATH="${CUDA_PATH}" \
+  -D CUDA_PROPAGATE_HOST_FLAGS:BOOL=OFF \
+  -D TPL_ENABLE_Thrust:BOOL=OFF \
+  -D Thrust_INCLUDE_DIRS:FILEPATH="${CUDA_PATH}/include" \
+  -D TPL_ENABLE_CUSPARSE:BOOL=OFF \
+  -D TPL_ENABLE_Cusp:BOOL=OFF \
+  -D Cusp_INCLUDE_DIRS="/home/crtrott/Software/cusp" \
+  -D CUDA_VERBOSE_BUILD:BOOL=OFF \
+  -D CUDA_NVCC_FLAGS:STRING=${CUDA_NVCC_FLAGS} \
+  \
+  \
+  -D TPL_ENABLE_HWLOC=OFF \
+  -D HWLOC_INCLUDE_DIRS="/usr/local/software/hwloc/current/include" \
+  -D HWLOC_LIBRARY_DIRS="/usr/local/software/hwloc/current/lib" \
+  -D TPL_ENABLE_BinUtils=OFF \
+  -D TPL_ENABLE_BLAS:STRING=ON \
+  -D TPL_ENABLE_LAPACK:STRING=ON \
+  -D TPL_ENABLE_MKL:STRING=OFF \
+  -D TPL_ENABLE_HWLOC:STRING=OFF \
+  -D TPL_ENABLE_GTEST:STRING=ON \
+  -D TPL_ENABLE_SuperLU=ON \
+  -D TPL_ENABLE_BLAS=ON \
+  -D TPL_ENABLE_LAPACK=ON \
+  -D TPL_SuperLU_LIBRARIES="/home/crtrott/Software/SuperLU_4.3/lib/libsuperlu_4.3.a" \
+  -D TPL_SuperLU_INCLUDE_DIRS="/home/crtrott/Software/SuperLU_4.3/SRC" \
+  \
+  \
+  -D Trilinos_Enable_Kokkos:BOOL=ON \
+  -D Trilinos_ENABLE_KokkosCore:BOOL=ON \
+  -D Trilinos_ENABLE_TeuchosKokkosCompat:BOOL=ON \
+  -D Trilinos_ENABLE_KokkosContainers:BOOL=ON \
+  -D Trilinos_ENABLE_TpetraKernels:BOOL=ON \
+  -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON \
+  -D Trilinos_ENABLE_TeuchosKokkosComm:BOOL=ON \
+  -D Trilinos_ENABLE_KokkosExample:BOOL=ON \
+  -D Kokkos_ENABLE_EXAMPLES:BOOL=ON \
+  -D Kokkos_ENABLE_TESTS:BOOL=OFF \
+  -D KokkosClassic_DefaultNode:STRING="Kokkos::Compat::KokkosCudaWrapperNode" \
+  -D TpetraClassic_ENABLE_OpenMPNode=OFF \
+  -D TpetraClassic_ENABLE_TPINode=OFF \
+  -D TpetraClassic_ENABLE_MKL=OFF \
+  -D Kokkos_ENABLE_Cuda_UVM=ON \
+  \
+  \
+  -D Trilinos_ENABLE_Teuchos:BOOL=ON \
+  -D Teuchos_ENABLE_COMPLEX:BOOL=OFF \
+  \
+  \
+  -D Trilinos_ENABLE_Tpetra:BOOL=ON \
+  -D Tpetra_ENABLE_KokkosCore=ON \
+  -D Tpetra_ENABLE_Kokkos_DistObject=OFF \
+  -D Tpetra_ENABLE_Kokkos_Refactor=ON \
+  -D Tpetra_ENABLE_TESTS=ON \
+  -D Tpetra_ENABLE_EXAMPLES=ON \
+  -D Tpetra_ENABLE_MPI_CUDA_RDMA:BOOL=ON \
+  \
+  \
+  -D Trilinos_ENABLE_Belos=OFF \
+  -D Trilinos_ENABLE_Amesos=OFF \
+  -D Trilinos_ENABLE_Amesos2=OFF \
+  -D Trilinos_ENABLE_Ifpack=OFF \
+  -D Trilinos_ENABLE_Ifpack2=OFF \
+  -D Trilinos_ENABLE_Epetra=OFF \
+  -D Trilinos_ENABLE_EpetraExt=OFF \
+  -D Trilinos_ENABLE_Zoltan=OFF \
+  -D Trilinos_ENABLE_Zoltan2=OFF \
+  -D Trilinos_ENABLE_MueLu=OFF \
+  -D Belos_ENABLE_TESTS=ON \
+  -D Belos_ENABLE_EXAMPLES=ON \
+  -D MueLu_ENABLE_TESTS=ON \
+  -D MueLu_ENABLE_EXAMPLES=ON \
+  -D Ifpack2_ENABLE_TESTS=ON \
+  -D Ifpack2_ENABLE_EXAMPLES=ON \
+  $EXTRA_ARGS \
+${HOME}/Trilinos
+
diff --git a/lib/kokkos/config/kokkos-trilinos-integration-procedure.txt b/lib/kokkos/config/kokkos-trilinos-integration-procedure.txt
new file mode 100644
index 0000000000..9f56f2fd48
--- /dev/null
+++ b/lib/kokkos/config/kokkos-trilinos-integration-procedure.txt
@@ -0,0 +1,153 @@
+// -------------------------------------------------------------------------------- //
+
+The following steps are for workstations/servers with the SEMS environment installed.
+
+// -------------------------------------------------------------------------------- //
+Summary:
+
+- Step 1: Rigorous testing of Kokkos' develop branch for each backend (Serial, OpenMP, Threads, Cuda) with all supported compilers.
+
+- Step 2: Snapshot Kokkos' develop branch into current Trilinos develop branch.
+
+- Step 3: Build and test Trilinos with combinations of compilers, types, backends.
+
+- Step 4: Promote Kokkos develop branch to master if the snapshot does not cause any new tests to fail; else track/fix causes of new failures.
+
+- Step 5: Snapshot Kokkos tagged master branch into Trilinos and push Trilinos.
+// -------------------------------------------------------------------------------- //
+
+
+// -------------------------------------------------------------------------------- //
+
+Step 1:
+  1.1. Update kokkos develop branch (NOT a fork)
+
+         (From kokkos directory):
+         git fetch --all
+         git checkout develop
+         git reset --hard origin/develop
+
+  1.2. Create a testing directory - here the directory is created within the kokkos directory
+
+         mkdir testing
+         cd testing
+
+  1.3. Run the test_all_sandia script; various compiler and build-list options can be specified
+
+         ../config/test_all_sandia
+
+  1.4 Clean repository of untracked files
+
+        cd ../
+        git clean -df
+
+// -------------------------------------------------------------------------------- //
+
+Step 2:
+  2.1 Update Trilinos develop branch
+
+        (From Trilinos directory):
+        git checkout develop
+        git fetch --all
+        git reset --hard origin/develop
+        git clean -df
+
+  2.2 Snapshot Kokkos into Trilinos - this requires python/2.7.9 and that both Trilinos and Kokkos be clean - no untracked or modified files
+
+        module load python/2.7.9
+        python KOKKOS_PATH/config/snapshot.py KOKKOS_PATH TRILINOS_PATH/packages
+
+// -------------------------------------------------------------------------------- //
+
+Step 3:
+  3.1. Build and test Trilinos with 3 different configurations; a configure-all script is provided in Trilinos and should be modified to test each of the following 3 configurations with appropriate environment variable(s):
+
+      - GCC/4.7.2-OpenMP/Complex
+          Run tests with the following environment variable:
+
+            export OMP_NUM_THREADS=2
+
+
+      - Intel/15.0.2-Serial/NoComplex
+
+
+      - GCC/4.8.4/CUDA/7.5.18-Cuda/Serial/NoComplex
+          Run tests with the following environment variables:
+
+            export CUDA_LAUNCH_BLOCKING=1
+            export CUDA_MANAGED_FORCE_DEVICE_ALLOC=1
+
+
+        mkdir Build
+        cd Build
+        cp TRILINOS_PATH/sampleScripts/Sandia-SEMS/configure-all ./
+            ** Set the path to Trilinos appropriately within the configure-all script **
+        source $SEMS_MODULE_ROOT/utils/sems-modules-init.sh kokkos
+        source configure-all
+        make -k  (-k means "keep going" to get past build errors; -j12 can also be specified to build with 12 threads, for example)
+        ctest
+
+  3.2. Compare the failed test output to the test output on the dashboard ( testing.sandia.gov/cdash select Trilinos ); investigate and fix problems if new tests fail after the Kokkos snapshot
+
+// -------------------------------------------------------------------------------- //
+
+Step 4:
+  4.1. Once all Trilinos tests pass promote Kokkos develop branch to master on Github
+
+       - DO NOT fast-forward the merge!!!!
+
+       (From kokkos directory):
+       git checkout master
+       git fetch --all
+       # Ensure we are on the current origin/master
+       git reset --hard origin/master
+       git merge --no-ff origin/develop
+
+  4.2. Update the tag in kokkos/config/master_history.txt
+       Tag description: MajorNumber.MinorNumber.WeeksSinceMinorNumberUpdate
+       Tag format: #.#.##
+
+       # Prepend master_history.txt with 
+       
+       # tag: #.#.##
+       # date: mm/dd/yyyy
+       # master: sha1
+       # develop: sha1
+       # -----------------------
+
+       git commit --amend -a
+
+       git tag -a #.#.##
+         tag: #.#.##
+         date: mm/dd/yyyy
+         master: sha1
+         develop: sha1
+
+       git push --follow-tags origin master
+
+// -------------------------------------------------------------------------------- //
+
+Step 5:
+  5.1. Make sure Trilinos is up-to-date - chances are other changes have been committed since the integration testing process began. If a substantial change has occurred that may be affected by the snapshot the testing procedure may need to be repeated
+
+       (From Trilinos directory):
+       git checkout develop
+       git fetch --all
+       git reset --hard origin/develop
+       git clean -df
+
+  5.2. Snapshot Kokkos master branch into Trilinos
+
+       (From kokkos directory):
+       git fetch --all
+       git checkout tags/#.#.##
+       git clean -df
+
+       python KOKKOS_PATH/config/snapshot.py KOKKOS_PATH TRILINOS_PATH/packages
+       
+  5.3. Push the updated develop branch of Trilinos to Github - congratulations!!!
+
+       (From Trilinos directory):
+       git push
+
+// -------------------------------------------------------------------------------- //
diff --git a/lib/kokkos/config/kokkos_dev/config-core-all.sh b/lib/kokkos/config/kokkos_dev/config-core-all.sh
new file mode 100755
index 0000000000..fa588c778f
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-all.sh
@@ -0,0 +1,113 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   Cuda, OpenMP, Threads, Qthread, hwloc
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  gcc/4.8.3  cuda/6.5.14  nvcc-wrapper/gnu
+#
+# The 'nvcc-wrapper' module should load a script that matches
+# kokkos/config/nvcc_wrapper
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=gcc"
+
+#-----------------------------------------------------------------------------
+# Cuda using GNU, use the nvcc_wrapper to build CUDA source
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=g++"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=nvcc_wrapper"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Hardware locality configuration:
+
+HWLOC_BASE_DIR="/home/projects/hwloc/1.7.1/host/gnu/4.7.3"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+
+#-----------------------------------------------------------------------------
+# Pthread
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# OpenMP
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_OpenMP:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Qthread
+
+QTHREAD_BASE_DIR="/home/projects/qthreads/2014-07-08/host/gnu/4.7.3"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_QTHREAD:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D QTHREAD_INCLUDE_DIRS:FILEPATH=${QTHREAD_BASE_DIR}/include"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D QTHREAD_LIBRARY_DIRS:FILEPATH=${QTHREAD_BASE_DIR}/lib"
+
+#-----------------------------------------------------------------------------
+# C++11
+
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CXX11:BOOL=ON"
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_CXX11:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/kokkos_dev/config-core-cuda-omp-hwloc.sh b/lib/kokkos/config/kokkos_dev/config-core-cuda-omp-hwloc.sh
new file mode 100755
index 0000000000..c2e17bb944
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-cuda-omp-hwloc.sh
@@ -0,0 +1,104 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   Cuda, OpenMP, hwloc
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  gcc/4.8.3  cuda/6.5.14  nvcc-wrapper/gnu
+#
+# The 'nvcc-wrapper' module should load a script that matches
+# kokkos/config/nvcc_wrapper
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=gcc"
+
+#-----------------------------------------------------------------------------
+# Cuda using GNU, use the nvcc_wrapper to build CUDA source
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=g++"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=nvcc_wrapper"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Hardware locality configuration:
+
+HWLOC_BASE_DIR="/home/projects/hwloc/1.7.1/host/gnu/4.7.3"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+
+#-----------------------------------------------------------------------------
+# Pthread explicitly OFF so tribits doesn't automatically turn it on
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# OpenMP
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_OpenMP:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# C++11
+
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CXX11:BOOL=ON"
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_CXX11:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/kokkos_dev/config-core-cuda.sh b/lib/kokkos/config/kokkos_dev/config-core-cuda.sh
new file mode 100755
index 0000000000..39b72d5ce1
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-cuda.sh
@@ -0,0 +1,88 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   Cuda
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  gcc/4.8.3  cuda/6.5.14  nvcc-wrapper/gnu
+#
+# The 'nvcc-wrapper' module should load a script that matches
+# kokkos/config/nvcc_wrapper
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=gcc"
+
+#-----------------------------------------------------------------------------
+# Cuda using GNU, use the nvcc_wrapper to build CUDA source
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=g++"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=nvcc_wrapper"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+
+# Pthread explicitly OFF, otherwise tribits will automatically turn it on
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# C++11
+
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CXX11:BOOL=ON"
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_CXX11:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/kokkos_dev/config-core-cxx11-omp.sh b/lib/kokkos/config/kokkos_dev/config-core-cxx11-omp.sh
new file mode 100755
index 0000000000..b83a535416
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-cxx11-omp.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   C++11, OpenMP
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  gcc/4.8.3
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=gcc"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=g++"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Pthread explicitly OFF so tribits doesn't automatically activate
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# OpenMP
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_OpenMP:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# C++11
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CXX11:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_CXX11:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/kokkos_dev/config-core-dbg-none.sh b/lib/kokkos/config/kokkos_dev/config-core-dbg-none.sh
new file mode 100755
index 0000000000..d2e06a4ebd
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-dbg-none.sh
@@ -0,0 +1,78 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   <none>
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  gcc/4.8.3
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=gcc"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=g++"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Kokkos Pthread explicitly OFF, TPL Pthread ON for gtest
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# C++11
+
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CXX11:BOOL=ON"
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_CXX11:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/kokkos_dev/config-core-intel-cuda-omp.sh b/lib/kokkos/config/kokkos_dev/config-core-intel-cuda-omp.sh
new file mode 100755
index 0000000000..e2ab1f1c00
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-intel-cuda-omp.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   Intel, OpenMP, Cuda
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  cuda/7.0.4  intel/2015.0.090  nvcc-wrapper/intel
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=icc"
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=icpc"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=nvcc_wrapper"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUDA:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_CUSPARSE:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Pthread explicitly OFF
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# OpenMP
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_OpenMP:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# C++11
+
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CXX11:BOOL=ON"
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_CXX11:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/kokkos_dev/config-core-intel-omp.sh b/lib/kokkos/config/kokkos_dev/config-core-intel-omp.sh
new file mode 100755
index 0000000000..fd56d41161
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-intel-omp.sh
@@ -0,0 +1,84 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   Intel, OpenMP
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  intel/13.SP1.1.106
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=icc"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=icpc"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Pthread explicitly OFF
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+# OpenMP
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_OpenMP:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# C++11
+
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CXX11:BOOL=ON"
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_CXX11:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/kokkos_dev/config-core-omp.sh b/lib/kokkos/config/kokkos_dev/config-core-omp.sh
new file mode 100755
index 0000000000..f91ecd5254
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-omp.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   OpenMP
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  gcc/4.8.3
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=gcc"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=g++"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# OpenMP
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_OpenMP:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_OpenMP:BOOL=ON"
+
+# Pthread explicitly OFF, otherwise tribits will automatically turn it on
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=OFF"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/kokkos_dev/config-core-threads-hwloc.sh b/lib/kokkos/config/kokkos_dev/config-core-threads-hwloc.sh
new file mode 100755
index 0000000000..19ab969023
--- /dev/null
+++ b/lib/kokkos/config/kokkos_dev/config-core-threads-hwloc.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+#
+# Copy this script, put it outside the Trilinos source directory, and
+# build there.
+#
+#-----------------------------------------------------------------------------
+# Building on 'kokkos-dev.sandia.gov' with enabled capabilities:
+#
+#   Threads, hwloc
+#
+# module loaded on 'kokkos-dev.sandia.gov' for this build
+#
+#  module load  cmake/2.8.11.2  gcc/4.8.3
+#
+#-----------------------------------------------------------------------------
+# Source and installation directories:
+
+TRILINOS_SOURCE_DIR=${HOME}/Trilinos
+TRILINOS_INSTALL_DIR=${HOME}/TrilinosInstall/`date +%F`
+
+CMAKE_CONFIGURE=""
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_INSTALL_PREFIX=${TRILINOS_INSTALL_DIR}"
+
+#-----------------------------------------------------------------------------
+# Debug/optimized
+
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=DEBUG"
+# CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_BOUNDS_CHECK:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_BUILD_TYPE:STRING=RELEASE"
+
+#-----------------------------------------------------------------------------
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_FLAGS:STRING=-Wall"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_C_COMPILER=gcc"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D CMAKE_CXX_COMPILER=g++"
+
+#-----------------------------------------------------------------------------
+# Configure for Kokkos subpackages and tests:
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_Fortran:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_ALL_PACKAGES:BOOL=OFF"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_EXAMPLES:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TESTS:BOOL=ON"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosCore:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosContainers:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosAlgorithms:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_TpetraKernels:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_KokkosExample:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# Hardware locality configuration:
+
+HWLOC_BASE_DIR="/home/projects/hwloc/1.7.1/host/gnu/4.7.3"
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_HWLOC:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_INCLUDE_DIRS:FILEPATH=${HWLOC_BASE_DIR}/include"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D HWLOC_LIBRARY_DIRS:FILEPATH=${HWLOC_BASE_DIR}/lib"
+
+#-----------------------------------------------------------------------------
+# Pthread
+
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D TPL_ENABLE_Pthread:BOOL=ON"
+CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_Pthread:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+# C++11
+
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Trilinos_ENABLE_CXX11:BOOL=ON"
+#  CMAKE_CONFIGURE="${CMAKE_CONFIGURE} -D Kokkos_ENABLE_CXX11:BOOL=ON"
+
+#-----------------------------------------------------------------------------
+#
+# Remove CMake output files to force reconfigure from scratch.
+#
+
+rm -rf CMake* Trilinos* packages Dart* Testing cmake_install.cmake MakeFile*
+
+#
+
+echo cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+cmake ${CMAKE_CONFIGURE} ${TRILINOS_SOURCE_DIR}
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/config/master_history.txt b/lib/kokkos/config/master_history.txt
new file mode 100644
index 0000000000..f2eb674578
--- /dev/null
+++ b/lib/kokkos/config/master_history.txt
@@ -0,0 +1,3 @@
+tag:  2.01.00    date: 07:21:2016    master: xxxxxxxx    develop: fa6dfcc4
+tag:  2.01.06    date: 09:02:2016    master: 9afaa87f    develop: 555f1a3a
+
diff --git a/lib/kokkos/config/nvcc_wrapper b/lib/kokkos/config/nvcc_wrapper
new file mode 100755
index 0000000000..6093cb61bd
--- /dev/null
+++ b/lib/kokkos/config/nvcc_wrapper
@@ -0,0 +1,280 @@
+#!/bin/bash
+#
+# This shell script (nvcc_wrapper) wraps both the host compiler and
+# NVCC, if you are building legacy C or C++ code with CUDA enabled.
+# The script remedies some differences between the interface of NVCC
+# and that of the host compiler, in particular for linking.
+# It also means that a legacy code doesn't need separate .cu files;
+# it can just use .cpp files.
+#
+# Default settings: change those according to your machine.  For
+# example, you may have have two different wrappers with either icpc
+# or g++ as their back-end compiler.  The defaults can be overwritten
+# by using the usual arguments (e.g., -arch=sm_30 -ccbin icpc).
+
+default_arch="sm_35"
+#default_arch="sm_50"
+
+#
+# The default C++ compiler.
+#
+host_compiler=${NVCC_WRAPPER_DEFAULT_COMPILER:-"g++"}
+#host_compiler="icpc"
+#host_compiler="/usr/local/gcc/4.8.3/bin/g++"
+#host_compiler="/usr/local/gcc/4.9.1/bin/g++"
+
+#
+# Internal variables
+#
+
+# C++ files
+cpp_files=""
+
+# Host compiler arguments
+xcompiler_args=""
+
+# Cuda (NVCC) only arguments
+cuda_args=""
+
+# Arguments for both NVCC and Host compiler
+shared_args=""
+
+# Linker arguments
+xlinker_args=""
+
+# Object files passable to NVCC
+object_files=""
+
+# Link objects for the host linker only
+object_files_xlinker=""
+
+# Shared libraries with version numbers are not handled correctly by NVCC
+shared_versioned_libraries_host=""
+shared_versioned_libraries=""
+
+# Does the User set the architecture 
+arch_set=0
+
+# Does the user overwrite the host compiler
+ccbin_set=0
+
+#Error code of compilation
+error_code=0
+
+# Do a dry run without actually compiling
+dry_run=0
+
+# Skip NVCC compilation and use host compiler directly
+host_only=0
+
+# Enable workaround for CUDA 6.5 for pragma ident 
+replace_pragma_ident=0
+
+# Mark first host compiler argument
+first_xcompiler_arg=1
+
+temp_dir=${TMPDIR:-/tmp}
+
+# Check if we have an optimization argument already
+optimization_applied=0
+
+#echo "Arguments: $# $@"
+
+while [ $# -gt 0 ]
+do
+  case $1 in
+  #show the executed command
+  --show|--nvcc-wrapper-show)
+    dry_run=1
+    ;;
+  #run host compilation only
+  --host-only)
+    host_only=1
+    ;;
+  #replace '#pragma ident' with '#ident' this is needed to compile OpenMPI due to a configure script bug and a non standardized behaviour of pragma with macros
+  --replace-pragma-ident)
+    replace_pragma_ident=1
+    ;;
+  #handle source files to be compiled as cuda files
+  *.cpp|*.cxx|*.cc|*.C|*.c++|*.cu)
+    cpp_files="$cpp_files $1"
+    ;;
+   # Ensure we only have one optimization flag because NVCC doesn't allow muliple
+  -O*)
+    if [ $optimization_applied -eq 1 ]; then
+       echo "nvcc_wrapper - *warning* you have set multiple optimization flags (-O*), only the first is used because nvcc can only accept a single optimization setting."
+    else
+       shared_args="$shared_args $1"
+       optimization_applied=1
+    fi
+    ;;
+  #Handle shared args (valid for both nvcc and the host compiler)
+  -D*|-c|-I*|-L*|-l*|-g|--help|--version|-E|-M|-shared)
+    shared_args="$shared_args $1"
+    ;;
+  #Handle shared args that have an argument
+  -o|-MT)
+    shared_args="$shared_args $1 $2"
+    shift
+    ;;
+  #Handle known nvcc args
+  -gencode*|--dryrun|--verbose|--keep|--keep-dir*|-G|--relocatable-device-code*|-lineinfo|-expt-extended-lambda|--resource-usage|-Xptxas*)
+    cuda_args="$cuda_args $1"
+    ;;
+  #Handle known nvcc args that have an argument
+  -rdc|-maxrregcount|--default-stream)
+    cuda_args="$cuda_args $1 $2"
+    shift
+    ;;
+  #Handle c++11 setting
+  --std=c++11|-std=c++11)
+    shared_args="$shared_args $1"
+    ;;
+  #strip of -std=c++98 due to nvcc warnings and Tribits will place both -std=c++11 and -std=c++98
+  -std=c++98|--std=c++98)
+    ;;
+  #strip of pedantic because it produces endless warnings about #LINE added by the preprocessor
+  -pedantic|-Wpedantic|-ansi)
+    ;;
+  #strip -Xcompiler because we add it
+  -Xcompiler)
+    if [ $first_xcompiler_arg -eq 1 ]; then
+      xcompiler_args="$2"
+      first_xcompiler_arg=0
+    else
+      xcompiler_args="$xcompiler_args,$2"
+    fi
+    shift
+    ;;
+  #strip of "-x cu" because we add that
+  -x)
+    if [[ $2 != "cu" ]]; then
+      if [ $first_xcompiler_arg -eq 1 ]; then
+        xcompiler_args="-x,$2"
+        first_xcompiler_arg=0
+      else
+        xcompiler_args="$xcompiler_args,-x,$2"
+      fi
+    fi
+    shift
+    ;;
+  #Handle -ccbin (if its not set we can set it to a default value)
+  -ccbin)
+    cuda_args="$cuda_args $1 $2"
+    ccbin_set=1
+    host_compiler=$2
+    shift
+    ;;
+  #Handle -arch argument (if its not set use a default
+  -arch*)
+    cuda_args="$cuda_args $1"
+    arch_set=1
+    ;;
+  #Handle -Xcudafe argument
+  -Xcudafe)
+    cuda_args="$cuda_args -Xcudafe $2"
+    shift
+    ;;
+  #Handle args that should be sent to the linker
+  -Wl*)
+    xlinker_args="$xlinker_args -Xlinker ${1:4:${#1}}"
+    host_linker_args="$host_linker_args ${1:4:${#1}}"
+    ;;
+  #Handle object files: -x cu applies to all input files, so give them to linker, except if only linking
+  *.a|*.so|*.o|*.obj)
+    object_files="$object_files $1"
+    object_files_xlinker="$object_files_xlinker -Xlinker $1"
+    ;;
+  #Handle object files which always need to use "-Xlinker": -x cu applies to all input files, so give them to linker, except if only linking
+  *.dylib)
+    object_files="$object_files -Xlinker $1"
+    object_files_xlinker="$object_files_xlinker -Xlinker $1"
+    ;;
+  #Handle shared libraries with *.so.* names which nvcc can't do.
+  *.so.*)
+    shared_versioned_libraries_host="$shared_versioned_libraries_host $1"
+    shared_versioned_libraries="$shared_versioned_libraries -Xlinker $1"
+  ;;
+  #All other args are sent to the host compiler
+  *)
+    if [ $first_xcompiler_arg -eq 1 ]; then
+      xcompiler_args=$1
+      first_xcompiler_arg=0
+    else 
+      xcompiler_args="$xcompiler_args,$1"
+    fi
+    ;;
+  esac
+
+  shift
+done
+
+#Add default host compiler if necessary
+if [ $ccbin_set -ne 1 ]; then
+  cuda_args="$cuda_args -ccbin $host_compiler"
+fi
+
+#Add architecture command
+if [ $arch_set -ne 1 ]; then
+  cuda_args="$cuda_args -arch=$default_arch"
+fi
+
+#Compose compilation command
+nvcc_command="nvcc $cuda_args $shared_args $xlinker_args $shared_versioned_libraries"
+if [ $first_xcompiler_arg -eq 0 ]; then
+  nvcc_command="$nvcc_command -Xcompiler $xcompiler_args"
+fi
+
+#Compose host only command
+host_command="$host_compiler $shared_args $xcompiler_args $host_linker_args $shared_versioned_libraries_host"
+
+#nvcc does not accept '#pragma ident SOME_MACRO_STRING' but it does accept '#ident SOME_MACRO_STRING'
+if [ $replace_pragma_ident -eq 1 ]; then
+  cpp_files2=""
+  for file in $cpp_files
+  do
+    var=`grep pragma ${file} | grep ident | grep "#"`
+    if [ "${#var}" -gt 0 ]
+    then
+      sed 's/#[\ \t]*pragma[\ \t]*ident/#ident/g' $file > $temp_dir/nvcc_wrapper_tmp_$file
+      cpp_files2="$cpp_files2 $temp_dir/nvcc_wrapper_tmp_$file"
+    else
+      cpp_files2="$cpp_files2 $file"
+    fi
+  done
+  cpp_files=$cpp_files2
+  #echo $cpp_files
+fi
+
+if [ "$cpp_files" ]; then
+  nvcc_command="$nvcc_command $object_files_xlinker -x cu $cpp_files"
+else
+  nvcc_command="$nvcc_command $object_files"
+fi
+
+if [ "$cpp_files" ]; then
+  host_command="$host_command $object_files $cpp_files"
+else
+  host_command="$host_command $object_files"
+fi
+
+#Print command for dryrun
+if [ $dry_run -eq 1 ]; then
+  if [ $host_only -eq 1 ]; then
+    echo $host_command
+  else
+    echo $nvcc_command
+  fi
+  exit 0
+fi
+
+#Run compilation command
+if [ $host_only -eq 1 ]; then
+  $host_command
+else
+  $nvcc_command
+fi
+error_code=$?
+
+#Report error code
+exit $error_code
diff --git a/lib/kokkos/config/snapshot.py b/lib/kokkos/config/snapshot.py
new file mode 100755
index 0000000000..d816cd0c9c
--- /dev/null
+++ b/lib/kokkos/config/snapshot.py
@@ -0,0 +1,279 @@
+#! /usr/bin/env python
+
+"""
+Snapshot a project into another project and perform the necessary repo actions
+to provide a commit message that can be used to trace back to the exact point
+in the source repository.
+"""
+
+#todo:
+#  Support svn
+#  Allow renaming of the source dir in the destination path
+#  Check if a new snapshot is necessary?
+#
+
+import sys
+
+#check the version number so that there is a good error message when argparse is not available.
+#This checks for exactly 2.7 which is bad, but it is a python 2 script and argparse was introduced
+#in 2.7 which is also the last version of python 2. If this script is updated for python 3 this
+#will need to change, but for now it is not safe to allow 3.x to run this.
+if sys.version_info[:2] != (2, 7):
+  print "Error snapshot requires python 2.7 detected version is %d.%d." % (sys.version_info[0], sys.version_info[1])
+  sys.exit(1)
+
+import subprocess, argparse, re, doctest, os, datetime, traceback
+
+def parse_cmdline(description):
+  parser = argparse.ArgumentParser(usage="snapshot.py [options] source destination", description=description)
+
+  parser.add_argument("-n", "--no-comit", action="store_false", dest="create_commit", default=True,
+                      help="Do not perform a commit or create a commit message.")
+  parser.add_argument("-v", "--verbose", action="store_true", dest="verbose_mode", default=False,
+                      help="Enable verbose mode.")
+  parser.add_argument("-d", "--debug", action="store_true", dest="debug_mode", default=False,
+                      help="Enable debugging output.")
+  parser.add_argument("--no-validate-repo", action="store_true", dest="no_validate_repo", default=False,
+                      help="Reduce the validation that the source and destination repos are clean to a warning.")
+  parser.add_argument("--source-repo", choices=["git","none"], default="",
+                      help="Type of repository of the source, use none to skip all repository operations.")
+  parser.add_argument("--dest-repo", choices=["git","none"], default="",
+                      help="Type of repository of the destination, use none to skip all repository operations.")
+
+  parser.add_argument("source",      help="Source project to snapshot from.")
+  parser.add_argument("destination", help="Destination to snapshot too.")
+
+  options = parser.parse_args()
+  options = validate_options(options)
+  return options
+#end parseCmdline
+
+def validate_options(options):
+  apparent_source_repo_type="none"
+  apparent_dest_repo_type="none"
+
+  #prevent user from accidentally giving us a path that rsync will treat differently than expected.
+  options.source      = options.source.rstrip(os.sep)
+  options.destination = options.destination.rstrip(os.sep)
+
+  options.source      = os.path.abspath(options.source)
+  options.destination = os.path.abspath(options.destination)
+  
+  if os.path.exists(options.source):
+    apparent_source_repo_type, source_root = deterimine_repo_type(options.source)
+  else:
+    raise RuntimeError("Could not find source directory of %s." % options.source)
+  options.source_root = source_root
+
+  if not os.path.exists(options.destination):
+    print "Could not find destination directory of %s so it will be created." % options.destination
+    os.makedirs(options.destination)
+
+  apparent_dest_repo_type, dest_root = deterimine_repo_type(options.destination)
+  options.dest_root = dest_root
+
+  #error on svn repo types for now
+  if apparent_source_repo_type == "svn" or apparent_dest_repo_type == "svn":
+    raise RuntimeError("SVN repositories are not supported at this time.")
+
+  if options.source_repo == "":
+    #source repo type is not specified to just using the apparent type.
+    options.source_repo = apparent_source_repo_type
+  else:
+    if options.source_repo != "none" and options.source_repo != apparent_source_repo_type:
+      raise RuntimeError("Specified source repository type of %s conflicts with determined type of %s" % \
+        (options.source_repo, apparent_source_repo_type))
+
+  if options.dest_repo == "":
+    #destination repo type is not specified to just using the apparent type.
+    options.dest_repo = apparent_dest_repo_type
+  else:
+    if options.dest_repo != "none" and options.dest_repo != apparent_dest_repo_type:
+      raise RuntimeError("Specified destination repository type of %s conflicts with determined type of %s" % \
+        (options.dest_repo, apparent_dest_repo_type))
+
+  return options
+#end validate_options
+
+def run_cmd(cmd, options, working_dir="."):
+  cmd_str = " ".join(cmd)
+  if options.verbose_mode:
+    print "Running command '%s' in dir %s." % (cmd_str, working_dir)
+
+  proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=working_dir)
+  proc_stdout, proc_stderr = proc.communicate()
+  ret_val = proc.wait()
+
+  if options.debug_mode:
+    print "==== %s stdout start ====" % cmd_str
+    print proc_stdout
+    print "==== %s stdout end ====" % cmd_str
+    print "==== %s stderr ====" % cmd_str
+    print proc_stderr
+    print "==== %s stderr ====" % cmd_str
+ 
+  if ret_val != 0:
+    raise RuntimeError("Command '%s' failed with error code %d. Error message:%s%s%sstdout:%s" % \
+      (cmd_str, ret_val, os.linesep, proc_stderr, os.linesep, proc_stdout))
+
+  return proc_stdout, proc_stderr
+#end run_cmd
+
+def deterimine_repo_type(location):
+  apparent_repo_type = "none"
+
+  while location != "":
+    if os.path.exists(os.path.join(location, ".git")):
+      apparent_repo_type = "git"
+      break
+    elif os.path.exists(os.path.join(location, ".svn")):
+      apparent_repo_type = "svn"
+      break
+    else:
+      location = location[:location.rfind(os.sep)]
+
+  return apparent_repo_type, location
+
+#end deterimine_repo_type
+
+def rsync(source, dest, options):
+  rsync_cmd = ["rsync", "-ar", "--delete"]
+  if options.debug_mode:
+    rsync_cmd.append("-v")
+
+  if options.source_repo == "git":
+    rsync_cmd.append("--exclude=.git")
+
+  rsync_cmd.append(options.source)
+  rsync_cmd.append(options.destination)
+  run_cmd(rsync_cmd, options)
+#end rsync
+
+def create_commit_message(commit_id, commit_log, project_name, project_location):
+  eol = os.linesep
+  message = "Snapshot of %s from commit %s" % (project_name, commit_id)
+  message += eol * 2
+  message += "From repository at %s" % project_location
+  message += eol * 2
+  message += "At commit:" + eol
+  message += commit_log
+  return message
+#end create_commit_message
+
+def find_git_commit_information(options):
+  r"""
+  >>> class fake_options:
+  ...   source="."
+  ...   verbose_mode=False
+  ...   debug_mode=False
+  >>> myoptions = fake_options()
+  >>> find_git_commit_information(myoptions)[2:]
+  ('sems', 'software.sandia.gov:/git/sems')
+  """
+  git_log_cmd = ["git", "log", "-1"]
+  
+  output, error = run_cmd(git_log_cmd, options, options.source)
+  
+  commit_match = re.match("commit ([0-9a-fA-F]+)", output)
+  commit_id = commit_match.group(1)
+  commit_log = output
+  
+  git_remote_cmd = ["git", "remote", "-v"]
+  output, error = run_cmd(git_remote_cmd, options, options.source)
+  
+  remote_match = re.search("origin\s([^ ]*/([^ ]+))", output, re.MULTILINE)
+  if not remote_match:
+    raise RuntimeError("Could not find origin of repo at %s. Consider using none for source repo type." % (options.source))
+
+  source_location = remote_match.group(1)
+  source_name     = remote_match.group(2).strip()
+  
+  if source_name[-1] == "/":
+    source_name = source_name[:-1]
+
+  return commit_id, commit_log, source_name, source_location
+
+#end find_git_commit_information
+
+def do_git_commit(message, options):
+  if options.verbose_mode:
+    print "Commiting to destination repository."
+
+  git_add_cmd = ["git", "add", "-A"]
+  run_cmd(git_add_cmd, options, options.destination)
+  
+  git_commit_cmd = ["git", "commit", "-m%s" % message]
+  run_cmd(git_commit_cmd, options, options.destination)
+  
+  git_log_cmd = ["git", "log", "--format=%h", "-1"]
+  commit_sha1, error = run_cmd(git_log_cmd, options, options.destination)
+
+  print "Commit %s was made to %s." % (commit_sha1.strip(), options.dest_root)
+#end do_git_commit
+
+def verify_git_repo_clean(location, options):
+  git_status_cmd = ["git", "status", "--porcelain"]
+  output, error = run_cmd(git_status_cmd, options, location)
+  
+  if output != "":
+    if options.no_validate_repo == False:
+      raise RuntimeError("%s is not clean.%sPlease commit or stash all changes before running snapshot."
+        % (location, os.linesep))
+    else:
+      print "WARNING: %s is not clean. Proceeding anyway." % location
+      print "WARNING:   This could lead to differences in the source and destination."
+      print "WARNING:   It could also lead to extra files being included in the snapshot commit."
+
+#end verify_git_repo_clean
+
+def main(options):
+  if options.verbose_mode:
+    print "Snapshotting %s to %s." % (options.source, options.destination)
+
+  if options.source_repo == "git":
+    verify_git_repo_clean(options.source, options)
+    commit_id, commit_log, repo_name, repo_location = find_git_commit_information(options)
+  elif options.source_repo == "none":
+    commit_id     = "N/A"
+    commit_log    = "Unknown commit from %s snapshotted at: %s" % (options.source, datetime.datetime.now())
+    repo_name     = options.source
+    repo_location = options.source
+    
+  commit_message = create_commit_message(commit_id, commit_log, repo_name, repo_location) + os.linesep*2
+  
+  if options.dest_repo == "git":
+    verify_git_repo_clean(options.destination, options)
+
+  rsync(options.source, options.destination, options)
+  
+  if options.dest_repo == "git":
+    do_git_commit(commit_message, options)
+  elif options.dest_repo == "none":
+    file_name = "snapshot_message.txt"
+    message_file = open(file_name, "w")
+    message_file.write(commit_message)
+    message_file.close()
+    cwd = os.getcwd()
+    print "No commit done by request. Please use file at:"
+    print "%s%sif you wish to commit this to a repo later." % (cwd+"/"+file_name, os.linesep)
+  
+  
+  
+  
+#end main
+
+if (__name__ == "__main__"):
+  if ("--test" in sys.argv):
+    doctest.testmod()
+    sys.exit(0)
+
+  try:    
+    options = parse_cmdline(__doc__)
+    main(options)
+  except RuntimeError, e:
+    print "Error occured:", e
+    if "--debug" in sys.argv:
+      traceback.print_exc()
+    sys.exit(1)
+  else:  
+    sys.exit(0)
diff --git a/lib/kokkos/config/test_all_sandia b/lib/kokkos/config/test_all_sandia
new file mode 100755
index 0000000000..aac036a8f3
--- /dev/null
+++ b/lib/kokkos/config/test_all_sandia
@@ -0,0 +1,539 @@
+#!/bin/bash -e
+
+#
+# Global config
+#
+
+set -o pipefail
+
+# Determine current machine
+
+MACHINE=""
+HOSTNAME=$(hostname)
+if [[ "$HOSTNAME" =~ (white|ride).* ]]; then
+    MACHINE=white
+elif [[ "$HOSTNAME" =~ .*bowman.* ]]; then
+    MACHINE=bowman
+elif [[ "$HOSTNAME" =~ node.* ]]; then # Warning: very generic name
+    MACHINE=shepard
+elif [ ! -z "$SEMS_MODULEFILES_ROOT" ]; then
+    MACHINE=sems
+else
+    echo "Unrecognized machine" >&2
+    exit 1
+fi
+
+GCC_BUILD_LIST="OpenMP,Pthread,Serial,OpenMP_Serial,Pthread_Serial"
+IBM_BUILD_LIST="OpenMP,Serial,OpenMP_Serial"
+INTEL_BUILD_LIST="OpenMP,Pthread,Serial,OpenMP_Serial,Pthread_Serial"
+CLANG_BUILD_LIST="Pthread,Serial,Pthread_Serial"
+CUDA_BUILD_LIST="Cuda_OpenMP,Cuda_Pthread,Cuda_Serial"
+
+GCC_WARNING_FLAGS="-Wall,-Wshadow,-pedantic,-Werror,-Wsign-compare,-Wtype-limits,-Wignored-qualifiers,-Wempty-body,-Wclobbered,-Wuninitialized"
+IBM_WARNING_FLAGS="-Wall,-Wshadow,-pedantic,-Werror,-Wsign-compare,-Wtype-limits,-Wuninitialized"
+CLANG_WARNING_FLAGS="-Wall,-Wshadow,-pedantic,-Werror,-Wsign-compare,-Wtype-limits,-Wuninitialized"
+INTEL_WARNING_FLAGS="-Wall,-Wshadow,-pedantic,-Werror,-Wsign-compare,-Wtype-limits,-Wuninitialized"
+CUDA_WARNING_FLAGS=""
+
+# Default. Machine specific can override
+DEBUG=False
+ARGS=""
+CUSTOM_BUILD_LIST=""
+DRYRUN=False
+BUILD_ONLY=False
+declare -i NUM_JOBS_TO_RUN_IN_PARALLEL=3
+TEST_SCRIPT=False
+SKIP_HWLOC=False
+
+ARCH_FLAG=""
+
+#
+# Machine specific config
+#
+
+if [ "$MACHINE" = "sems" ]; then
+    source /projects/modulefiles/utils/sems-modules-init.sh
+    source /projects/modulefiles/utils/kokkos-modules-init.sh
+
+    BASE_MODULE_LIST="<COMPILER_NAME>/<COMPILER_VERSION>/base,hwloc/1.10.1/<COMPILER_NAME>/<COMPILER_VERSION>/base"
+    CUDA_MODULE_LIST="<COMPILER_NAME>/<COMPILER_VERSION>,gcc/4.7.2/base"
+
+    # Format: (compiler module-list build-list exe-name warning-flag)
+    COMPILERS=("gcc/4.7.2 $BASE_MODULE_LIST $GCC_BUILD_LIST g++ $GCC_WARNING_FLAGS"
+               "gcc/4.8.4 $BASE_MODULE_LIST $GCC_BUILD_LIST g++ $GCC_WARNING_FLAGS"
+               "gcc/4.9.2 $BASE_MODULE_LIST $GCC_BUILD_LIST g++ $GCC_WARNING_FLAGS"
+               "gcc/5.1.0 $BASE_MODULE_LIST $GCC_BUILD_LIST g++ $GCC_WARNING_FLAGS"
+               "intel/14.0.4 $BASE_MODULE_LIST $INTEL_BUILD_LIST icpc $INTEL_WARNING_FLAGS"
+               "intel/15.0.2 $BASE_MODULE_LIST $INTEL_BUILD_LIST icpc $INTEL_WARNING_FLAGS"
+               "intel/16.0.1 $BASE_MODULE_LIST $INTEL_BUILD_LIST icpc $INTEL_WARNING_FLAGS"
+               "clang/3.5.2 $BASE_MODULE_LIST $CLANG_BUILD_LIST clang++ $CLANG_WARNING_FLAGS"
+               "clang/3.6.1 $BASE_MODULE_LIST $CLANG_BUILD_LIST clang++ $CLANG_WARNING_FLAGS"
+               "cuda/6.5.14 $CUDA_MODULE_LIST $CUDA_BUILD_LIST $KOKKOS_PATH/config/nvcc_wrapper $CUDA_WARNING_FLAGS"
+               "cuda/7.0.28 $CUDA_MODULE_LIST $CUDA_BUILD_LIST $KOKKOS_PATH/config/nvcc_wrapper $CUDA_WARNING_FLAGS"
+               "cuda/7.5.18 $CUDA_MODULE_LIST $CUDA_BUILD_LIST $KOKKOS_PATH/config/nvcc_wrapper $CUDA_WARNING_FLAGS"
+    )
+
+elif [ "$MACHINE" = "white" ]; then
+    source /etc/profile.d/modules.sh
+    SKIP_HWLOC=True
+    export SLURM_TASKS_PER_NODE=32
+
+    BASE_MODULE_LIST="<COMPILER_NAME>/<COMPILER_VERSION>"
+    IBM_MODULE_LIST="<COMPILER_NAME>/xl/<COMPILER_VERSION>"
+    CUDA_MODULE_LIST="<COMPILER_NAME>/<COMPILER_VERSION>,gcc/4.9.2"
+
+    # Don't do pthread on white
+    GCC_BUILD_LIST="OpenMP,Serial,OpenMP_Serial"
+
+    # Format: (compiler module-list build-list exe-name warning-flag)
+    COMPILERS=("gcc/4.9.2 $BASE_MODULE_LIST $IBM_BUILD_LIST g++ $GCC_WARNING_FLAGS"
+               "gcc/5.3.0 $BASE_MODULE_LIST $IBM_BUILD_LIST g++ $GCC_WARNING_FLAGS"
+               "ibm/13.1.3 $IBM_MODULE_LIST $IBM_BUILD_LIST xlC $IBM_WARNING_FLAGS"
+    )
+
+    ARCH_FLAG="--arch=Power8"
+    NUM_JOBS_TO_RUN_IN_PARALLEL=8
+
+elif [ "$MACHINE" = "bowman" ]; then
+    source /etc/profile.d/modules.sh
+    SKIP_HWLOC=True
+    export SLURM_TASKS_PER_NODE=32
+
+    BASE_MODULE_LIST="<COMPILER_NAME>/compilers/<COMPILER_VERSION>"
+
+    OLD_INTEL_BUILD_LIST="Pthread,Serial,Pthread_Serial"
+
+    # Format: (compiler module-list build-list exe-name warning-flag)
+    COMPILERS=("intel/16.2.181 $BASE_MODULE_LIST $OLD_INTEL_BUILD_LIST icpc $INTEL_WARNING_FLAGS"
+               "intel/17.0.064 $BASE_MODULE_LIST $INTEL_BUILD_LIST icpc $INTEL_WARNING_FLAGS"
+    )
+
+    ARCH_FLAG="--arch=KNL"
+    NUM_JOBS_TO_RUN_IN_PARALLEL=8
+
+elif [ "$MACHINE" = "shepard" ]; then
+    source /etc/profile.d/modules.sh
+    SKIP_HWLOC=True
+    export SLURM_TASKS_PER_NODE=32
+
+    BASE_MODULE_LIST="<COMPILER_NAME>/compilers/<COMPILER_VERSION>"
+
+    OLD_INTEL_BUILD_LIST="Pthread,Serial,Pthread_Serial"
+
+    # Format: (compiler module-list build-list exe-name warning-flag)
+    COMPILERS=("intel/16.2.181 $BASE_MODULE_LIST $OLD_INTEL_BUILD_LIST icpc $INTEL_WARNING_FLAGS"
+               "intel/17.0.064 $BASE_MODULE_LIST $INTEL_BUILD_LIST icpc $INTEL_WARNING_FLAGS"
+    )
+
+    ARCH_FLAG="--arch=HSW"
+    NUM_JOBS_TO_RUN_IN_PARALLEL=8
+
+else
+    echo "Unhandled machine $MACHINE" >&2
+    exit 1
+fi
+
+export OMP_NUM_THREADS=4
+
+declare -i NUM_RESULTS_TO_KEEP=7
+
+RESULT_ROOT_PREFIX=TestAll
+
+SCRIPT_KOKKOS_ROOT=$( cd "$( dirname "$0" )" && cd .. && pwd )
+
+#
+# Handle arguments
+#
+
+while [[ $# > 0 ]]
+do
+key="$1"
+case $key in
+--kokkos-path*)
+KOKKOS_PATH="${key#*=}"
+;;
+--build-list*)
+CUSTOM_BUILD_LIST="${key#*=}"
+;;
+--debug*)
+DEBUG=True
+;;
+--build-only*)
+BUILD_ONLY=True
+;;
+--test-script*)
+TEST_SCRIPT=True
+;;
+--skip-hwloc*)
+SKIP_HWLOC=True
+;;
+--num*)
+NUM_JOBS_TO_RUN_IN_PARALLEL="${key#*=}"
+;;
+--dry-run*)
+DRYRUN=True
+;;
+--help)
+echo "test_all_sandia <ARGS> <OPTIONS>:"
+echo "--kokkos-path=/Path/To/Kokkos: Path to the Kokkos root directory"
+echo "    Defaults to root repo containing this script"
+echo "--debug: Run tests in debug. Defaults to False"
+echo "--test-script: Test this script, not Kokkos"
+echo "--skip-hwloc: Do not do hwloc tests"
+echo "--num=N: Number of jobs to run in parallel "
+echo "--dry-run: Just print what would be executed"
+echo "--build-only: Just do builds, don't run anything"
+echo "--build-list=BUILD,BUILD,BUILD..."
+echo "    Provide a comma-separated list of builds instead of running all builds"
+echo "    Valid items:"
+echo "      OpenMP, Pthread, Serial, OpenMP_Serial, Pthread_Serial"
+echo "      Cuda_OpenMP, Cuda_Pthread, Cuda_Serial"
+echo ""
+
+echo "ARGS: list of expressions matching compilers to test"
+echo "  supported compilers sems"
+for COMPILER_DATA in "${COMPILERS[@]}"; do
+    ARR=($COMPILER_DATA)
+    COMPILER=${ARR[0]}
+    echo "    $COMPILER"
+done
+echo ""
+
+echo "Examples:"
+echo "  Run all tests"
+echo "  % test_all_sandia"
+echo ""
+echo "  Run all gcc tests"
+echo "  % test_all_sandia gcc"
+echo ""
+echo "  Run all gcc/4.7.2 and all intel tests"
+echo "  % test_all_sandia gcc/4.7.2 intel"
+echo ""
+echo "  Run all tests in debug"
+echo "  % test_all_sandia --debug"
+echo ""
+echo "  Run gcc/4.7.2 and only do OpenMP and OpenMP_Serial builds"
+echo "  % test_all_sandia gcc/4.7.2 --build-list=OpenMP,OpenMP_Serial"
+echo ""
+echo "If you want to kill the tests, do:"
+echo "  hit ctrl-z"
+echo "  % kill -9 %1"
+echo
+exit 0
+;;
+*)
+# args, just append
+ARGS="$ARGS $1"
+;;
+esac
+shift
+done
+
+# set kokkos path
+if [ -z "$KOKKOS_PATH" ]; then
+    KOKKOS_PATH=$SCRIPT_KOKKOS_ROOT
+else
+    # Ensure KOKKOS_PATH is abs path
+    KOKKOS_PATH=$( cd $KOKKOS_PATH && pwd )
+fi
+
+# set build type
+if [ "$DEBUG" = "True" ]; then
+    BUILD_TYPE=debug
+else
+    BUILD_TYPE=release
+fi
+
+# If no args provided, do all compilers
+if [ -z "$ARGS" ]; then
+    ARGS='?'
+fi
+
+# Process args to figure out which compilers to test
+COMPILERS_TO_TEST=""
+for ARG in $ARGS; do
+    for COMPILER_DATA in "${COMPILERS[@]}"; do
+        ARR=($COMPILER_DATA)
+        COMPILER=${ARR[0]}
+        if [[ "$COMPILER" = $ARG* ]]; then
+            if [[ "$COMPILERS_TO_TEST" != *${COMPILER}* ]]; then
+                COMPILERS_TO_TEST="$COMPILERS_TO_TEST $COMPILER"
+            else
+                echo "Tried to add $COMPILER twice"
+            fi
+        fi
+    done
+done
+
+#
+# Functions
+#
+
+# get_compiler_name <COMPILER>
+get_compiler_name() {
+    echo $1 | cut -d/ -f1
+}
+
+# get_compiler_version <COMPILER>
+get_compiler_version() {
+    echo $1 | cut -d/ -f2
+}
+
+# Do not call directly
+get_compiler_data() {
+    local compiler=$1
+    local item=$2
+    local compiler_name=$(get_compiler_name $compiler)
+    local compiler_vers=$(get_compiler_version $compiler)
+
+    local compiler_data
+    for compiler_data in "${COMPILERS[@]}" ; do
+        local arr=($compiler_data)
+        if [ "$compiler" = "${arr[0]}" ]; then
+            echo "${arr[$item]}" | tr , ' ' | sed -e "s/<COMPILER_NAME>/$compiler_name/g" -e "s/<COMPILER_VERSION>/$compiler_vers/g"
+            return 0
+        fi
+    done
+
+    # Not found
+    echo "Unreconized compiler $compiler" >&2
+    exit 1
+}
+
+#
+# For all getters, usage: <GETTER> <COMPILER>
+#
+
+get_compiler_modules() {
+    get_compiler_data $1 1
+}
+
+get_compiler_build_list() {
+    get_compiler_data $1 2
+}
+
+get_compiler_exe_name() {
+    get_compiler_data $1 3
+}
+
+get_compiler_warning_flags() {
+    get_compiler_data $1 4
+}
+
+run_cmd() {
+    echo "RUNNING: $*"
+    if [ "$DRYRUN" != "True" ]; then
+	eval "$* 2>&1"
+    fi
+}
+
+# report_and_log_test_results <SUCCESS> <DESC> <COMMENT>
+report_and_log_test_result() {
+    # Use sane var names
+    local success=$1; local desc=$2; local comment=$3;
+
+    if [ "$success" = "0" ]; then
+	echo "  PASSED $desc"
+        echo $comment > $PASSED_DIR/$desc
+    else
+        # For failures, comment should be the name of the phase that failed
+	echo "  FAILED $desc" >&2
+        echo $comment > $FAILED_DIR/$desc
+        cat ${desc}.${comment}.log
+    fi
+}
+
+setup_env() {
+    local compiler=$1
+    local compiler_modules=$(get_compiler_modules $compiler)
+
+    module purge
+
+    local mod
+    for mod in $compiler_modules; do
+        echo "Loading module $mod"
+	module load $mod 2>&1
+        # It is ridiculously hard to check for the success of a loaded
+        # module. Module does not return error codes and piping to grep
+        # causes module to run in a subshell.
+        module list 2>&1 | grep "$mod" >& /dev/null || return 1
+    done
+
+    return 0
+}
+
+# single_build_and_test <COMPILER> <BUILD> <BUILD_TYPE>
+single_build_and_test() {
+    # Use sane var names
+    local compiler=$1; local build=$2; local build_type=$3;
+
+    # set up env
+    mkdir -p $ROOT_DIR/$compiler/"${build}-$build_type"
+    cd $ROOT_DIR/$compiler/"${build}-$build_type"
+    local desc=$(echo "${compiler}-${build}-${build_type}" | sed 's:/:-:g')
+    setup_env $compiler >& ${desc}.configure.log || { report_and_log_test_result 1 ${desc} configure && return 0; }
+
+    # Set up flags
+    local compiler_warning_flags=$(get_compiler_warning_flags $compiler)
+    local compiler_exe=$(get_compiler_exe_name $compiler)
+
+    if [[ "$build_type" = hwloc* ]]; then
+        local extra_args=--with-hwloc=$(dirname $(dirname $(which hwloc-info)))
+    fi
+
+    if [[ "$build_type" = *debug* ]]; then
+        local extra_args="$extra_args --debug"
+        local cxxflags="-g $compiler_warning_flags"
+    else
+        local cxxflags="-O3 $compiler_warning_flags"
+    fi
+
+    if [[ "$compiler" == cuda* ]]; then
+        cxxflags="--keep --keep-dir=$(pwd) $cxxflags"
+        export TMPDIR=$(pwd)
+    fi
+
+    # cxxflags="-DKOKKOS_USING_EXP_VIEW=1 $cxxflags"
+
+    echo "  Starting job $desc"
+
+    local comment="no_comment"
+
+    if [ "$TEST_SCRIPT" = "True" ]; then
+        local rand=$[ 1 + $[ RANDOM % 10 ]]
+        sleep $rand
+        if [ $rand -gt 5 ]; then
+            run_cmd ls fake_problem >& ${desc}.configure.log || { report_and_log_test_result 1 $desc configure && return 0; }
+        fi
+    else
+        run_cmd ${KOKKOS_PATH}/generate_makefile.bash --with-devices=$build $ARCH_FLAG --compiler=$(which $compiler_exe) --cxxflags=\"$cxxflags\" $extra_args &>> ${desc}.configure.log || { report_and_log_test_result 1 ${desc} configure && return 0; }
+        local -i build_start_time=$(date +%s)
+        run_cmd make build-test >& ${desc}.build.log || { report_and_log_test_result 1 ${desc} build && return 0; }
+        local -i build_end_time=$(date +%s)
+        comment="build_time=$(($build_end_time-$build_start_time))"
+        if [[ "$BUILD_ONLY" == False ]]; then
+            run_cmd make test >& ${desc}.test.log || { report_and_log_test_result 1 ${desc} test && return 0; }
+            local -i run_end_time=$(date +%s)
+            comment="$comment run_time=$(($run_end_time-$build_end_time))"
+        fi
+    fi
+
+    report_and_log_test_result 0 $desc "$comment"
+
+    return 0
+}
+
+# wait_for_jobs <NUM-JOBS>
+wait_for_jobs() {
+    local -i max_jobs=$1
+    local -i num_active_jobs=$(jobs | wc -l)
+    while [ $num_active_jobs -ge $max_jobs ]
+    do
+        sleep 1
+        num_active_jobs=$(jobs | wc -l)
+        jobs >& /dev/null
+    done
+}
+
+# run_in_background <COMPILER> <BUILD> <BUILD_TYPE>
+run_in_background() {
+    local compiler=$1
+
+    local -i num_jobs=$NUM_JOBS_TO_RUN_IN_PARALLEL
+    if [[ "$BUILD_ONLY" == True ]]; then
+        num_jobs=8
+    else
+        if [[ "$compiler" == cuda* ]]; then
+            num_jobs=1
+        fi
+    fi
+    wait_for_jobs $num_jobs
+
+    single_build_and_test $* &
+}
+
+# build_and_test_all <COMPILER>
+build_and_test_all() {
+    # Get compiler data
+    local compiler=$1
+    if [ -z "$CUSTOM_BUILD_LIST" ]; then
+	local compiler_build_list=$(get_compiler_build_list $compiler)
+    else
+	local compiler_build_list=$(echo "$CUSTOM_BUILD_LIST" | tr , ' ')
+    fi
+
+    # do builds
+    local build
+    for build in $compiler_build_list
+    do
+	run_in_background $compiler $build $BUILD_TYPE
+
+        # If not cuda, do a hwloc test too
+        if [[ "$compiler" != cuda* && "$SKIP_HWLOC" == False ]]; then
+            run_in_background $compiler $build "hwloc-$BUILD_TYPE"
+        fi
+    done
+
+    return 0
+}
+
+get_test_root_dir() {
+    local existing_results=$(find . -maxdepth 1 -name "$RESULT_ROOT_PREFIX*" | sort)
+    local -i num_existing_results=$(echo $existing_results | tr ' ' '\n' | wc -l)
+    local -i num_to_delete=${num_existing_results}-${NUM_RESULTS_TO_KEEP}
+
+    if [ $num_to_delete -gt 0 ]; then
+        /bin/rm -rf $(echo $existing_results | tr ' ' '\n' | head -n $num_to_delete)
+    fi
+
+    echo $(pwd)/${RESULT_ROOT_PREFIX}_$(date +"%Y-%m-%d_%H.%M.%S")
+}
+
+wait_summarize_and_exit() {
+    wait_for_jobs 1
+
+    echo "#######################################################"
+    echo "PASSED TESTS"
+    echo "#######################################################"
+
+    local passed_test
+    for passed_test in $(\ls -1 $PASSED_DIR | sort)
+    do
+        echo $passed_test $(cat $PASSED_DIR/$passed_test)
+    done
+
+    echo "#######################################################"
+    echo "FAILED TESTS"
+    echo "#######################################################"
+
+    local failed_test
+    local -i rv=0
+    for failed_test in $(\ls -1 $FAILED_DIR | sort)
+    do
+        echo $failed_test "("$(cat $FAILED_DIR/$failed_test)" failed)"
+        rv=$rv+1
+    done
+
+    exit $rv
+}
+
+#
+# Main
+#
+
+ROOT_DIR=$(get_test_root_dir)
+mkdir -p $ROOT_DIR
+cd $ROOT_DIR
+
+PASSED_DIR=$ROOT_DIR/results/passed
+FAILED_DIR=$ROOT_DIR/results/failed
+mkdir -p $PASSED_DIR
+mkdir -p $FAILED_DIR
+
+echo "Going to test compilers: " $COMPILERS_TO_TEST
+for COMPILER in $COMPILERS_TO_TEST; do
+    echo "Testing compiler $COMPILER"
+    build_and_test_all $COMPILER
+done
+
+wait_summarize_and_exit
diff --git a/lib/kokkos/config/testing_scripts/README b/lib/kokkos/config/testing_scripts/README
new file mode 100644
index 0000000000..455afffd84
--- /dev/null
+++ b/lib/kokkos/config/testing_scripts/README
@@ -0,0 +1,5 @@
+jenkins_test_driver is designed to be run through Jenkins as a
+multiconfiguration job. It relies on a number of environment variables that will
+only be set when run in that context. It is possible to override these if you
+know the Jenkins job setup. It is not recommended that a non-expert try to run
+this script directly.
diff --git a/lib/kokkos/config/testing_scripts/jenkins_test_driver b/lib/kokkos/config/testing_scripts/jenkins_test_driver
new file mode 100755
index 0000000000..9cba7fa518
--- /dev/null
+++ b/lib/kokkos/config/testing_scripts/jenkins_test_driver
@@ -0,0 +1,83 @@
+#!/bin/bash -x
+
+echo "Building for BUILD_TYPE = ${BUILD_TYPE}"
+echo "Building with HOST_COMPILER = ${HOST_COMPILER}"
+echo "Building in ${WORKSPACE}"
+
+module use /home/projects/modulefiles
+
+BUILD_TYPE=`echo $BUILD_TYPE | tr "~" " "`
+build_options=""
+for item in ${BUILD_TYPE}; do
+  build_options="$build_options --with-$item"
+done
+
+kokkos_path=${WORKSPACE}/kokkos
+gtest_path=${WORKSPACE}/kokkos/tpls/gtest
+
+echo ${WORKSPACE}
+pwd
+
+#extract information from the provided parameters.
+host_compiler_brand=`echo $HOST_COMPILER | grep -o "^[a-zA-Z]*"`
+cuda_compiler=`echo $BUILD_TYPE | grep -o "cuda_[^ ]*"`
+
+host_compiler_module=`echo $HOST_COMPILER | tr "_" "/"`
+cuda_compiler_module=`echo $cuda_compiler | tr "_" "/"`
+build_path=`echo $BUILD_TYPE | tr " " "_"`
+
+module load $host_compiler_module
+module load $cuda_compiler_module
+
+case $host_compiler_brand in
+  gcc)
+    module load nvcc-wrapper/gnu
+    compiler=g++
+    ;;
+  intel)
+    module load nvcc-wrapper/intel
+    compiler=icpc
+    ;;
+  *)
+    echo "Unrecognized compiler brand."
+    exit 1
+    ;;
+esac
+
+#if cuda is on we need to set the host compiler for the
+#nvcc wrapper and make the wrapper the compiler.
+if [ $cuda_compiler != "" ]; then
+  export NVCC_WRAPPER_DEFAULT_COMPILER=$compiler
+  compiler=$kokkos_path/config/nvcc_wrapper
+fi
+
+if [ $host_compiler_brand == "intel" -a $cuda_compiler != "" ]; then
+  echo "Intel compilers are not supported with cuda at this time."
+  exit 0
+fi
+
+rm -rf test-$build_path
+mkdir test-$build_path
+cd test-$build_path
+
+/bin/bash $kokkos_path/generate_makefile.bash $build_options --kokkos-path="$kokkos_path" --with-gtest="$gtest_path" --compiler=$compiler 2>&1 |tee configure.out
+
+if [ ${PIPESTATUS[0]} != 0 ]; then
+  echo "Configure failed."
+  exit 1
+fi
+
+make build-test 2>&1 | tee build.log
+
+if [ ${PIPESTATUS[0]} != 0 ]; then
+  echo "Build failed."
+  exit 1
+fi
+
+make test 2>&1 | tee test.log
+
+grep "FAIL" test.log
+if [ $? == 0 ]; then
+  echo "Tests failed."
+  exit 1
+fi
diff --git a/lib/kokkos/config/testing_scripts/obj_size_opt_check b/lib/kokkos/config/testing_scripts/obj_size_opt_check
new file mode 100755
index 0000000000..47c84d1a92
--- /dev/null
+++ b/lib/kokkos/config/testing_scripts/obj_size_opt_check
@@ -0,0 +1,287 @@
+#! /usr/bin/env python
+
+"""
+Compute the size at which the current compiler will start to
+significantly scale back optimization.
+
+The CPP file being modified will need the following tags.
+// JGF_DUPLICATE_BEGIN - Put before start of function to duplicate
+// JGF_DUPLICATE_END - Put after end of function to duplcate
+// JGF_DUPE function_name(args); - Put anywhere where it's legal to
+put a function call but not in your timing section.
+
+The program will need to output the string:
+FOM: <number>
+This will represent the program's performance
+"""
+
+import argparse, sys, os, doctest, subprocess, re, time
+
+VERBOSE = False
+
+###############################################################################
+def parse_command_line(args, description):
+###############################################################################
+    parser = argparse.ArgumentParser(
+        usage="""\n%s <cppfile> <build-command> <run-command> [--verbose]
+OR
+%s --help
+OR
+%s --test
+
+\033[1mEXAMPLES:\033[0m
+    > %s foo.cpp 'make -j4' foo
+""" % ((os.path.basename(args[0]), ) * 4),
+
+description=description,
+
+formatter_class=argparse.ArgumentDefaultsHelpFormatter
+)
+
+    parser.add_argument("cppfile", help="Name of file to modify.")
+
+    parser.add_argument("buildcmd", help="Build command")
+
+    parser.add_argument("execmd", help="Run command")
+
+    parser.add_argument("-v", "--verbose", action="store_true",
+                        help="Print extra information")
+
+    parser.add_argument("-s", "--start", type=int, default=1,
+                        help="Starting number of dupes")
+
+    parser.add_argument("-e", "--end", type=int, default=1000,
+                        help="Ending number of dupes")
+
+    parser.add_argument("-n", "--repeat", type=int, default=10,
+                        help="Number of times to repeat an individial execution. Best value will be taken.")
+
+    parser.add_argument("-t", "--template", action="store_true",
+                        help="Use templating instead of source copying to increase object size")
+
+    parser.add_argument("-c", "--csv", action="store_true",
+                        help="Print results as CSV")
+
+    args = parser.parse_args(args[1:])
+
+    if (args.verbose):
+        global VERBOSE
+        VERBOSE = True
+
+    return args.cppfile, args.buildcmd, args.execmd, args.start, args.end, args.repeat, args.template, args.csv
+
+###############################################################################
+def verbose_print(msg, override=None):
+###############################################################################
+    if ( (VERBOSE and not override is False) or override):
+        print msg
+
+###############################################################################
+def error_print(msg):
+###############################################################################
+    print >> sys.stderr, msg
+
+###############################################################################
+def expect(condition, error_msg):
+###############################################################################
+    """
+    Similar to assert except doesn't generate an ugly stacktrace. Useful for
+    checking user error, not programming error.
+    """
+    if (not condition):
+        raise SystemExit("FAIL: %s" % error_msg)
+
+###############################################################################
+def run_cmd(cmd, ok_to_fail=False, input_str=None, from_dir=None, verbose=None,
+            arg_stdout=subprocess.PIPE, arg_stderr=subprocess.PIPE):
+###############################################################################
+    verbose_print("RUN: %s" % cmd, verbose)
+
+    if (input_str is not None):
+        stdin = subprocess.PIPE
+    else:
+        stdin = None
+
+    proc = subprocess.Popen(cmd,
+                            shell=True,
+                            stdout=arg_stdout,
+                            stderr=arg_stderr,
+                            stdin=stdin,
+                            cwd=from_dir)
+    output, errput = proc.communicate(input_str)
+    output = output.strip() if output is not None else output
+    stat = proc.wait()
+
+    if (ok_to_fail):
+        return stat, output, errput
+    else:
+        if (arg_stderr is not None):
+            errput = errput if errput is not None else open(arg_stderr.name, "r").read()
+            expect(stat == 0, "Command: '%s' failed with error '%s'" % (cmd, errput))
+        else:
+            expect(stat == 0, "Command: '%s' failed. See terminal output" % cmd)
+        return output
+
+###############################################################################
+def build_and_run(source, cppfile, buildcmd, execmd, repeat):
+###############################################################################
+    open(cppfile, 'w').writelines(source)
+
+    run_cmd(buildcmd)
+
+    best = None
+    for i in xrange(repeat):
+        wait_for_quiet_machine()
+        output = run_cmd(execmd)
+
+        current = None
+        fom_regex = re.compile(r'^FOM: ([0-9.]+)$')
+        for line in output.splitlines():
+            m = fom_regex.match(line)
+            if (m is not None):
+                current = float(m.groups()[0])
+                break
+
+        expect(current is not None, "No lines in output matched FOM regex")
+
+        if (best is None or best < current):
+            best = current
+
+    return best
+
+###############################################################################
+def wait_for_quiet_machine():
+###############################################################################
+    while(True):
+        time.sleep(2)
+
+        # The first iteration of top gives garbage results
+        idle_pct_raw = run_cmd("top -bn2 | grep 'Cpu(s)' | tr ',' ' ' | tail -n 1 | awk '{print $5}'")
+
+        idle_pct_re = re.compile(r'^([0-9.]+)%id$')
+        m = idle_pct_re.match(idle_pct_raw)
+
+        expect(m is not None, "top not returning output in expected form")
+
+        idle_pct = float(m.groups()[0])
+        if (idle_pct < 95):
+            error_print("Machine is too busy, waiting for it to become free")
+        else:
+            break
+
+###############################################################################
+def add_n_dupes(curr_lines, num_dupes, template):
+###############################################################################
+    function_name  = None
+    function_invocation = None
+    function_lines = []
+
+    function_re = re.compile(r'^.* (\w+) *[(]')
+    function_inv_re = re.compile(r'^.*JGF_DUPE: +(.+)$')
+
+    # Get function lines
+    record = False
+    definition_insertion_point = None
+    invocation_insertion_point = None
+    for idx, line in enumerate(curr_lines):
+        if ("JGF_DUPLICATE_BEGIN" in line):
+            record = True
+            m = function_re.match(curr_lines[idx+1])
+            expect(m is not None, "Could not find function in line '%s'" % curr_lines[idx+1])
+            function_name = m.groups()[0]
+
+        elif ("JGF_DUPLICATE_END" in line):
+            record = False
+            definition_insertion_point = idx + 1
+
+        elif (record):
+            function_lines.append(line)
+
+        elif ("JGF_DUPE" in line):
+            m = function_inv_re.match(line)
+            expect(m is not None, "Could not find function invocation example in line '%s'" % line)
+            function_invocation = m.groups()[0]
+            invocation_insertion_point = idx + 1
+
+    expect(function_name is not None, "Could not find name of dupe function")
+    expect(function_invocation is not None, "Could not find function invocation point")
+
+    expect(definition_insertion_point < invocation_insertion_point, "fix me")
+
+    dupe_func_defs = []
+    dupe_invocations = ["int jgf_rand = std::rand();\n", "if (false) {}\n"]
+
+    for i in xrange(num_dupes):
+        if (not template):
+            dupe_func = list(function_lines)
+            dupe_func[0] = dupe_func[0].replace(function_name, "%s%d" % (function_name, i))
+            dupe_func_defs.extend(dupe_func)
+
+        dupe_invocations.append("else if (jgf_rand == %d) " % i)
+        if (template):
+            dupe_call = function_invocation.replace(function_name, "%s<%d>" % (function_name, i)) + "\n"
+        else:
+            dupe_call = function_invocation.replace(function_name, "%s%d" % (function_name, i))  + "\n"
+        dupe_invocations.append(dupe_call)
+
+    curr_lines[invocation_insertion_point:invocation_insertion_point] = dupe_invocations
+    curr_lines[definition_insertion_point:definition_insertion_point] = dupe_func_defs
+
+###############################################################################
+def report(num_dupes, curr_lines, object_file, orig_fom, curr_fom, csv=False, is_first_report=False):
+###############################################################################
+    fom_change = (curr_fom - orig_fom) / orig_fom
+
+    if (csv):
+        if (is_first_report):
+            print "num_dupes, obj_byte_size, loc, fom, pct_diff"
+
+        print "%s, %s, %s, %s, %s" % (num_dupes, os.path.getsize(object_file), len(curr_lines), curr_fom, fom_change*100)
+    else:
+        print "========================================================"
+        print "For number of dupes:", num_dupes
+        print "Object file size (bytes):", os.path.getsize(object_file)
+        print "Lines of code:", len(curr_lines)
+        print "Field of merit:", curr_fom
+        print "Change pct:", fom_change*100
+
+###############################################################################
+def obj_size_opt_check(cppfile, buildcmd, execmd, start, end, repeat, template, csv=False):
+###############################################################################
+    orig_source_lines = open(cppfile, 'r').readlines()
+
+    backup_file = "%s.orig" % cppfile
+    object_file = "%s.o" % os.path.splitext(cppfile)[0]
+    os.rename(cppfile, backup_file)
+
+    orig_fom = build_and_run(orig_source_lines, cppfile, buildcmd, execmd, repeat)
+    report(0, orig_source_lines, object_file, orig_fom, orig_fom, csv=csv, is_first_report=True)
+
+    i = start
+    while (i < end):
+        curr_lines = list(orig_source_lines)
+        add_n_dupes(curr_lines, i, template)
+
+        curr_fom = build_and_run(curr_lines, cppfile, buildcmd, execmd, repeat)
+
+        report(i, curr_lines, object_file, orig_fom, curr_fom, csv=csv)
+
+        i *= 2 # make growth function configurable?
+
+    os.remove(cppfile)
+    os.rename(backup_file, cppfile)
+
+###############################################################################
+def _main_func(description):
+###############################################################################
+    if ("--test" in sys.argv):
+        test_results = doctest.testmod(verbose=True)
+        sys.exit(1 if test_results.failed > 0 else 0)
+
+    cppfile, buildcmd, execmd, start, end, repeat, template, csv = parse_command_line(sys.argv, description)
+
+    obj_size_opt_check(cppfile, buildcmd, execmd, start, end, repeat, template, csv)
+
+###############################################################################
+if (__name__ == "__main__"):
+    _main_func(__doc__)
diff --git a/lib/kokkos/containers/CMakeLists.txt b/lib/kokkos/containers/CMakeLists.txt
new file mode 100644
index 0000000000..894935fa01
--- /dev/null
+++ b/lib/kokkos/containers/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+
+TRIBITS_SUBPACKAGE(Containers)
+
+ADD_SUBDIRECTORY(src)
+
+TRIBITS_ADD_TEST_DIRECTORIES(unit_tests)
+TRIBITS_ADD_TEST_DIRECTORIES(performance_tests)
+
+TRIBITS_SUBPACKAGE_POSTPROCESS()
diff --git a/lib/kokkos/containers/cmake/Dependencies.cmake b/lib/kokkos/containers/cmake/Dependencies.cmake
new file mode 100644
index 0000000000..1d71d8af34
--- /dev/null
+++ b/lib/kokkos/containers/cmake/Dependencies.cmake
@@ -0,0 +1,5 @@
+TRIBITS_PACKAGE_DEFINE_DEPENDENCIES(
+  LIB_REQUIRED_PACKAGES KokkosCore
+  LIB_OPTIONAL_TPLS Pthread CUDA HWLOC
+  TEST_OPTIONAL_TPLS CUSPARSE
+  )
diff --git a/lib/kokkos/containers/cmake/KokkosContainers_config.h.in b/lib/kokkos/containers/cmake/KokkosContainers_config.h.in
new file mode 100644
index 0000000000..d91fdda1e3
--- /dev/null
+++ b/lib/kokkos/containers/cmake/KokkosContainers_config.h.in
@@ -0,0 +1,4 @@
+#ifndef KOKKOS_CONTAINERS_CONFIG_H
+#define KOKKOS_CONTAINERS_CONFIG_H
+
+#endif
diff --git a/lib/kokkos/containers/performance_tests/CMakeLists.txt b/lib/kokkos/containers/performance_tests/CMakeLists.txt
new file mode 100644
index 0000000000..726d403452
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/CMakeLists.txt
@@ -0,0 +1,37 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../src )
+
+SET(SOURCES
+  TestMain.cpp 
+  TestCuda.cpp
+  )
+
+IF(Kokkos_ENABLE_Pthread)
+  LIST( APPEND SOURCES TestThreads.cpp)
+ENDIF()
+
+IF(Kokkos_ENABLE_OpenMP)
+  LIST( APPEND SOURCES TestOpenMP.cpp)
+ENDIF()
+
+# Per #374, we always want to build this test, but we only want to run
+# it as a PERFORMANCE test.  That's why we separate building the test
+# from running the test.
+
+TRIBITS_ADD_EXECUTABLE(
+  PerfTestExec
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  TESTONLYLIBS kokkos_gtest
+  )
+
+TRIBITS_ADD_TEST(
+  PerformanceTest
+  NAME PerfTestExec
+  COMM serial mpi
+  NUM_MPI_PROCS 1
+  CATEGORIES PERFORMANCE
+  FAIL_REGULAR_EXPRESSION "  FAILED  "
+  )
diff --git a/lib/kokkos/containers/performance_tests/Makefile b/lib/kokkos/containers/performance_tests/Makefile
new file mode 100644
index 0000000000..e7abaf44ce
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/Makefile
@@ -0,0 +1,81 @@
+KOKKOS_PATH = ../..
+
+GTEST_PATH = ../../TPL/gtest
+
+vpath %.cpp ${KOKKOS_PATH}/containers/performance_tests
+
+default: build_all
+	echo "End Build"
+
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?= -lpthread
+endif
+
+KOKKOS_CXXFLAGS += -I$(GTEST_PATH) -I${KOKKOS_PATH}/containers/performance_tests
+
+TEST_TARGETS = 
+TARGETS = 
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	OBJ_CUDA = TestCuda.o TestMain.o gtest-all.o
+	TARGETS += KokkosContainers_PerformanceTest_Cuda
+	TEST_TARGETS += test-cuda
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+	OBJ_THREADS = TestThreads.o TestMain.o gtest-all.o
+	TARGETS += KokkosContainers_PerformanceTest_Threads
+	TEST_TARGETS += test-threads
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+	OBJ_OPENMP = TestOpenMP.o TestMain.o gtest-all.o
+	TARGETS += KokkosContainers_PerformanceTest_OpenMP
+	TEST_TARGETS += test-openmp
+endif
+
+KokkosContainers_PerformanceTest_Cuda: $(OBJ_CUDA) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_CUDA) $(KOKKOS_LIBS) $(LIB) -o KokkosContainers_PerformanceTest_Cuda
+
+KokkosContainers_PerformanceTest_Threads: $(OBJ_THREADS) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_THREADS) $(KOKKOS_LIBS) $(LIB) -o KokkosContainers_PerformanceTest_Threads
+
+KokkosContainers_PerformanceTest_OpenMP: $(OBJ_OPENMP) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_OPENMP) $(KOKKOS_LIBS) $(LIB) -o KokkosContainers_PerformanceTest_OpenMP
+
+test-cuda: KokkosContainers_PerformanceTest_Cuda
+	./KokkosContainers_PerformanceTest_Cuda
+
+test-threads: KokkosContainers_PerformanceTest_Threads
+	./KokkosContainers_PerformanceTest_Threads
+
+test-openmp: KokkosContainers_PerformanceTest_OpenMP
+	./KokkosContainers_PerformanceTest_OpenMP
+
+
+build_all: $(TARGETS)
+
+test: $(TEST_TARGETS)
+
+clean: kokkos-clean 
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
+gtest-all.o:$(GTEST_PATH)/gtest/gtest-all.cc 
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $(GTEST_PATH)/gtest/gtest-all.cc
+
diff --git a/lib/kokkos/containers/performance_tests/TestCuda.cpp b/lib/kokkos/containers/performance_tests/TestCuda.cpp
new file mode 100644
index 0000000000..8183adaa60
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/TestCuda.cpp
@@ -0,0 +1,109 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdint.h>
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <fstream>
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+#include <TestDynRankView.hpp>
+
+#include <Kokkos_UnorderedMap.hpp>
+
+#include <TestGlobal2LocalIds.hpp>
+
+#include <TestUnorderedMapPerformance.hpp>
+
+namespace Performance {
+
+class cuda : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+    Kokkos::HostSpace::execution_space::initialize();
+    Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice(0) );
+  }
+  static void TearDownTestCase()
+  {
+    Kokkos::Cuda::finalize();
+    Kokkos::HostSpace::execution_space::finalize();
+  }
+};
+
+TEST_F( cuda, dynrankview_perf ) 
+{
+  std::cout << "Cuda" << std::endl;
+  std::cout << " DynRankView vs View: Initialization Only " << std::endl;
+  test_dynrankview_op_perf<Kokkos::Cuda>( 4096 );
+}
+
+TEST_F( cuda, global_2_local)
+{
+  std::cout << "Cuda" << std::endl;
+  std::cout << "size, create, generate, fill, find" << std::endl;
+  for (unsigned i=Performance::begin_id_size; i<=Performance::end_id_size; i *= Performance::id_step)
+    test_global_to_local_ids<Kokkos::Cuda>(i);
+}
+
+TEST_F( cuda, unordered_map_performance_near)
+{
+  Perf::run_performance_tests<Kokkos::Cuda,true>("cuda-near");
+}
+
+TEST_F( cuda, unordered_map_performance_far)
+{
+  Perf::run_performance_tests<Kokkos::Cuda,false>("cuda-far");
+}
+
+}
+
+#endif  /* #if defined( KOKKOS_HAVE_CUDA ) */
diff --git a/lib/kokkos/containers/performance_tests/TestDynRankView.hpp b/lib/kokkos/containers/performance_tests/TestDynRankView.hpp
new file mode 100644
index 0000000000..aab6e6988f
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/TestDynRankView.hpp
@@ -0,0 +1,265 @@
+
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_TEST_DYNRANKVIEW_HPP
+#define KOKKOS_TEST_DYNRANKVIEW_HPP
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_DynRankView.hpp>
+#include <vector>
+
+#include <impl/Kokkos_Timer.hpp>
+
+// Compare performance of DynRankView to View, specific focus on the parenthesis operators
+
+namespace Performance {
+
+//View functor
+template <typename DeviceType>
+struct InitViewFunctor {
+  typedef Kokkos::View<double***, DeviceType> inviewtype;
+  inviewtype _inview;
+
+  InitViewFunctor( inviewtype &inview_ ) : _inview(inview_)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(const int i) const {
+    for (unsigned j = 0; j < _inview.dimension(1); ++j) {
+      for (unsigned k = 0; k < _inview.dimension(2); ++k) {
+        _inview(i,j,k) = i/2 -j*j + k/3;
+      }
+    }
+  }
+
+  struct SumComputationTest
+  {
+    typedef Kokkos::View<double***, DeviceType> inviewtype;
+    inviewtype _inview;
+
+    typedef Kokkos::View<double*, DeviceType> outviewtype;
+    outviewtype _outview;
+
+    KOKKOS_INLINE_FUNCTION
+    SumComputationTest(inviewtype &inview_ , outviewtype &outview_) : _inview(inview_), _outview(outview_) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()(const int i) const {
+      for (unsigned j = 0; j < _inview.dimension(1); ++j) {
+        for (unsigned k = 0; k < _inview.dimension(2); ++k) {
+          _outview(i) += _inview(i,j,k) ;
+        }
+      }
+    }
+  };
+
+};
+
+template <typename DeviceType>
+struct InitStrideViewFunctor {
+  typedef Kokkos::View<double***, Kokkos::LayoutStride, DeviceType> inviewtype;
+  inviewtype _inview;
+
+  InitStrideViewFunctor( inviewtype &inview_ ) : _inview(inview_)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(const int i) const {
+    for (unsigned j = 0; j < _inview.dimension(1); ++j) {
+      for (unsigned k = 0; k < _inview.dimension(2); ++k) {
+        _inview(i,j,k) = i/2 -j*j + k/3;
+      }
+    }
+  }
+
+};
+
+template <typename DeviceType>
+struct InitViewRank7Functor {
+  typedef Kokkos::View<double*******, DeviceType> inviewtype;
+  inviewtype _inview;
+
+  InitViewRank7Functor( inviewtype &inview_ ) : _inview(inview_)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(const int i) const {
+    for (unsigned j = 0; j < _inview.dimension(1); ++j) {
+      for (unsigned k = 0; k < _inview.dimension(2); ++k) {
+        _inview(i,j,k,0,0,0,0) = i/2 -j*j + k/3;
+      }
+    }
+  }
+
+};
+
+//DynRankView functor
+template <typename DeviceType>
+struct InitDynRankViewFunctor {
+  typedef Kokkos::DynRankView<double, DeviceType> inviewtype;
+  inviewtype _inview;
+
+  InitDynRankViewFunctor( inviewtype &inview_ ) : _inview(inview_)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(const int i) const {
+    for (unsigned j = 0; j < _inview.dimension(1); ++j) {
+      for (unsigned k = 0; k < _inview.dimension(2); ++k) {
+        _inview(i,j,k) = i/2 -j*j + k/3;
+      }
+    }
+  }
+
+  struct SumComputationTest
+  {
+    typedef Kokkos::DynRankView<double, DeviceType> inviewtype;
+    inviewtype _inview;
+
+    typedef Kokkos::DynRankView<double, DeviceType> outviewtype;
+    outviewtype _outview;
+
+    KOKKOS_INLINE_FUNCTION
+    SumComputationTest(inviewtype &inview_ , outviewtype &outview_) : _inview(inview_), _outview(outview_) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()(const int i) const {
+      for (unsigned j = 0; j < _inview.dimension(1); ++j) {
+        for (unsigned k = 0; k < _inview.dimension(2); ++k) {
+          _outview(i) += _inview(i,j,k) ;
+        }
+      }
+    }
+  };
+
+};
+
+
+template <typename DeviceType>
+void test_dynrankview_op_perf( const int par_size )
+{
+
+  typedef DeviceType execution_space;
+  typedef typename execution_space::size_type size_type;
+  const size_type dim2 = 900;
+  const size_type dim3 = 300;
+
+  double elapsed_time_view = 0;
+  double elapsed_time_compview = 0;
+  double elapsed_time_strideview = 0;
+  double elapsed_time_view_rank7 = 0;
+  double elapsed_time_drview = 0;
+  double elapsed_time_compdrview = 0;
+  Kokkos::Timer timer;
+  {
+    Kokkos::View<double***,DeviceType> testview("testview",par_size,dim2,dim3);
+    typedef InitViewFunctor<DeviceType> FunctorType;
+
+    timer.reset();
+    Kokkos::RangePolicy<DeviceType> policy(0,par_size);
+    Kokkos::parallel_for( policy , FunctorType(testview) );
+    DeviceType::fence();
+    elapsed_time_view = timer.seconds();
+    std::cout << " View time (init only): " << elapsed_time_view << std::endl;
+
+
+    timer.reset();
+    Kokkos::View<double*,DeviceType> sumview("sumview",par_size);
+    Kokkos::parallel_for( policy , typename FunctorType::SumComputationTest(testview, sumview) );
+    DeviceType::fence();
+    elapsed_time_compview = timer.seconds();
+    std::cout << " View sum computation time: " << elapsed_time_view << std::endl;
+
+
+    Kokkos::View<double***,Kokkos::LayoutStride, DeviceType> teststrideview = Kokkos::subview(testview, Kokkos::ALL, Kokkos::ALL,Kokkos::ALL);
+    typedef InitStrideViewFunctor<DeviceType> FunctorStrideType;
+
+    timer.reset();
+    Kokkos::parallel_for( policy , FunctorStrideType(teststrideview) );
+    DeviceType::fence();
+    elapsed_time_strideview = timer.seconds();
+    std::cout << " Strided View time (init only): " << elapsed_time_strideview << std::endl;
+  }
+  {
+    Kokkos::View<double*******,DeviceType> testview("testview",par_size,dim2,dim3,1,1,1,1);
+    typedef InitViewRank7Functor<DeviceType> FunctorType;
+
+    timer.reset();
+    Kokkos::RangePolicy<DeviceType> policy(0,par_size);
+    Kokkos::parallel_for( policy , FunctorType(testview) );
+    DeviceType::fence();
+    elapsed_time_view_rank7 = timer.seconds();
+    std::cout << " View Rank7 time (init only): " << elapsed_time_view_rank7 << std::endl;
+  }
+  {
+    Kokkos::DynRankView<double,DeviceType> testdrview("testdrview",par_size,dim2,dim3);
+    typedef InitDynRankViewFunctor<DeviceType> FunctorType;
+
+    timer.reset();
+    Kokkos::RangePolicy<DeviceType> policy(0,par_size);
+    Kokkos::parallel_for( policy , FunctorType(testdrview) );
+    DeviceType::fence();
+    elapsed_time_drview = timer.seconds();
+    std::cout << " DynRankView time (init only): " << elapsed_time_drview << std::endl;
+
+    timer.reset();
+    Kokkos::DynRankView<double,DeviceType> sumview("sumview",par_size);
+    Kokkos::parallel_for( policy , typename FunctorType::SumComputationTest(testdrview, sumview) );
+    DeviceType::fence();
+    elapsed_time_compdrview = timer.seconds();
+    std::cout << " DynRankView sum computation time: " << elapsed_time_compdrview << std::endl;
+
+  }
+
+  std::cout << " Ratio of View to DynRankView time: " << elapsed_time_view / elapsed_time_drview << std::endl; //expect < 1
+  std::cout << " Ratio of View to DynRankView sum computation time: " << elapsed_time_compview / elapsed_time_compdrview << std::endl; //expect < 1
+  std::cout << " Ratio of View to View Rank7  time: " << elapsed_time_view / elapsed_time_view_rank7 << std::endl; //expect < 1
+  std::cout << " Ratio of StrideView to DynRankView time: " << elapsed_time_strideview / elapsed_time_drview << std::endl; //expect < 1
+  std::cout << " Ratio of DynRankView to View Rank7  time: " << elapsed_time_drview / elapsed_time_view_rank7 << std::endl; //expect ?
+
+  timer.reset();
+
+} //end test_dynrankview
+
+
+} //end Performance
+#endif
diff --git a/lib/kokkos/containers/performance_tests/TestGlobal2LocalIds.hpp b/lib/kokkos/containers/performance_tests/TestGlobal2LocalIds.hpp
new file mode 100644
index 0000000000..66f1fbf092
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/TestGlobal2LocalIds.hpp
@@ -0,0 +1,231 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_TEST_GLOBAL_TO_LOCAL_IDS_HPP
+#define KOKKOS_TEST_GLOBAL_TO_LOCAL_IDS_HPP
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_UnorderedMap.hpp>
+#include <vector>
+#include <algorithm>
+
+#include <impl/Kokkos_Timer.hpp>
+
+// This test will simulate global ids
+
+namespace Performance {
+
+static const unsigned begin_id_size = 256u;
+static const unsigned end_id_size = 1u << 22;
+static const unsigned id_step = 2u;
+
+union helper
+{
+  uint32_t word;
+  uint8_t byte[4];
+};
+
+
+template <typename Device>
+struct generate_ids
+{
+  typedef Device execution_space;
+  typedef typename execution_space::size_type size_type;
+  typedef Kokkos::View<uint32_t*,execution_space> local_id_view;
+
+  local_id_view local_2_global;
+
+  generate_ids( local_id_view & ids)
+    : local_2_global(ids)
+  {
+    Kokkos::parallel_for(local_2_global.dimension_0(), *this);
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(size_type i) const
+  {
+
+    helper x = {static_cast<uint32_t>(i)};
+
+    // shuffle the bytes of i to create a unique, semi-random global_id
+    x.word = ~x.word;
+
+    uint8_t tmp = x.byte[3];
+    x.byte[3] = x.byte[1];
+    x.byte[1] = tmp;
+
+    tmp = x.byte[2];
+    x.byte[2] = x.byte[0];
+    x.byte[0] = tmp;
+
+    local_2_global[i] = x.word;
+  }
+
+};
+
+template <typename Device>
+struct fill_map
+{
+  typedef Device execution_space;
+  typedef typename execution_space::size_type size_type;
+  typedef Kokkos::View<const uint32_t*,execution_space, Kokkos::MemoryRandomAccess> local_id_view;
+  typedef Kokkos::UnorderedMap<uint32_t,size_type,execution_space> global_id_view;
+
+  global_id_view global_2_local;
+  local_id_view local_2_global;
+
+  fill_map( global_id_view gIds, local_id_view lIds)
+    : global_2_local(gIds) , local_2_global(lIds)
+  {
+    Kokkos::parallel_for(local_2_global.dimension_0(), *this);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(size_type i) const
+  {
+    global_2_local.insert( local_2_global[i], i);
+  }
+
+};
+
+template <typename Device>
+struct find_test
+{
+  typedef Device execution_space;
+  typedef typename execution_space::size_type size_type;
+  typedef Kokkos::View<const uint32_t*,execution_space, Kokkos::MemoryRandomAccess> local_id_view;
+  typedef Kokkos::UnorderedMap<const uint32_t, const size_type,execution_space> global_id_view;
+
+  global_id_view global_2_local;
+  local_id_view local_2_global;
+
+  typedef size_t value_type;
+
+  find_test( global_id_view gIds, local_id_view lIds, value_type & num_errors)
+    : global_2_local(gIds) , local_2_global(lIds)
+  {
+    Kokkos::parallel_reduce(local_2_global.dimension_0(), *this, num_errors);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init(value_type & v) const
+  { v = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type & dst, volatile value_type const & src) const
+  { dst += src; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(size_type i, value_type & num_errors) const
+  {
+    uint32_t index = global_2_local.find( local_2_global[i] );
+
+    if ( global_2_local.value_at(index) != i) ++num_errors;
+  }
+
+};
+
+template <typename Device>
+void test_global_to_local_ids(unsigned num_ids)
+{
+
+  typedef Device execution_space;
+  typedef typename execution_space::size_type size_type;
+
+  typedef Kokkos::View<uint32_t*,execution_space> local_id_view;
+  typedef Kokkos::UnorderedMap<uint32_t,size_type,execution_space> global_id_view;
+
+  //size
+  std::cout << num_ids << ", ";
+
+  double elasped_time = 0;
+  Kokkos::Timer timer;
+
+  local_id_view local_2_global("local_ids", num_ids);
+  global_id_view global_2_local((3u*num_ids)/2u);
+
+  //create
+  elasped_time = timer.seconds();
+  std::cout << elasped_time << ", ";
+  timer.reset();
+
+  // generate unique ids
+  {
+    generate_ids<Device> gen(local_2_global);
+  }
+  Device::fence();
+  // generate
+  elasped_time = timer.seconds();
+  std::cout << elasped_time << ", ";
+  timer.reset();
+
+  {
+    fill_map<Device> fill(global_2_local, local_2_global);
+  }
+  Device::fence();
+
+  // fill
+  elasped_time = timer.seconds();
+  std::cout << elasped_time << ", ";
+  timer.reset();
+
+
+  size_t num_errors = 0;
+  for (int i=0; i<100; ++i)
+  {
+    find_test<Device> find(global_2_local, local_2_global,num_errors);
+  }
+  Device::fence();
+
+  // find
+  elasped_time = timer.seconds();
+  std::cout << elasped_time << std::endl;
+
+  ASSERT_EQ( num_errors, 0u);
+}
+
+
+} // namespace Performance
+
+
+#endif //KOKKOS_TEST_GLOBAL_TO_LOCAL_IDS_HPP
+
diff --git a/lib/kokkos/containers/performance_tests/TestMain.cpp b/lib/kokkos/containers/performance_tests/TestMain.cpp
new file mode 100644
index 0000000000..f952ab3db5
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/TestMain.cpp
@@ -0,0 +1,50 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+int main(int argc, char *argv[]) {
+  ::testing::InitGoogleTest(&argc,argv);
+  return RUN_ALL_TESTS();
+}
+
diff --git a/lib/kokkos/containers/performance_tests/TestOpenMP.cpp b/lib/kokkos/containers/performance_tests/TestOpenMP.cpp
new file mode 100644
index 0000000000..da74d32ac1
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/TestOpenMP.cpp
@@ -0,0 +1,140 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#include <Kokkos_UnorderedMap.hpp>
+
+#include <TestGlobal2LocalIds.hpp>
+#include <TestUnorderedMapPerformance.hpp>
+
+#include <TestDynRankView.hpp>
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <fstream>
+
+
+namespace Performance {
+
+class openmp : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+
+    unsigned num_threads = 4;
+
+    if (Kokkos::hwloc::available()) {
+      num_threads = Kokkos::hwloc::get_available_numa_count()
+                    * Kokkos::hwloc::get_available_cores_per_numa()
+                    * Kokkos::hwloc::get_available_threads_per_core()
+                    ;
+
+    }
+
+    std::cout << "OpenMP: " << num_threads << std::endl;
+
+    Kokkos::OpenMP::initialize( num_threads );
+
+    std::cout << "available threads: " << omp_get_max_threads() << std::endl;
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::OpenMP::finalize();
+
+    omp_set_num_threads(1);
+
+    ASSERT_EQ( 1 , omp_get_max_threads() );
+  }
+};
+
+TEST_F( openmp, dynrankview_perf ) 
+{
+  std::cout << "OpenMP" << std::endl;
+  std::cout << " DynRankView vs View: Initialization Only " << std::endl;
+  test_dynrankview_op_perf<Kokkos::OpenMP>( 8192 );
+}
+
+TEST_F( openmp, global_2_local)
+{
+  std::cout << "OpenMP" << std::endl;
+  std::cout << "size, create, generate, fill, find" << std::endl;
+  for (unsigned i=Performance::begin_id_size; i<=Performance::end_id_size; i *= Performance::id_step)
+    test_global_to_local_ids<Kokkos::OpenMP>(i);
+}
+
+TEST_F( openmp, unordered_map_performance_near)
+{
+  unsigned num_openmp = 4;
+  if (Kokkos::hwloc::available()) {
+    num_openmp = Kokkos::hwloc::get_available_numa_count() *
+                  Kokkos::hwloc::get_available_cores_per_numa() *
+                  Kokkos::hwloc::get_available_threads_per_core();
+
+  }
+  std::ostringstream base_file_name;
+  base_file_name << "openmp-" << num_openmp << "-near";
+  Perf::run_performance_tests<Kokkos::OpenMP,true>(base_file_name.str());
+}
+
+TEST_F( openmp, unordered_map_performance_far)
+{
+  unsigned num_openmp = 4;
+  if (Kokkos::hwloc::available()) {
+    num_openmp = Kokkos::hwloc::get_available_numa_count() *
+                  Kokkos::hwloc::get_available_cores_per_numa() *
+                  Kokkos::hwloc::get_available_threads_per_core();
+
+  }
+  std::ostringstream base_file_name;
+  base_file_name << "openmp-" << num_openmp << "-far";
+  Perf::run_performance_tests<Kokkos::OpenMP,false>(base_file_name.str());
+}
+
+} // namespace test
+
diff --git a/lib/kokkos/containers/performance_tests/TestThreads.cpp b/lib/kokkos/containers/performance_tests/TestThreads.cpp
new file mode 100644
index 0000000000..4179b7de4c
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/TestThreads.cpp
@@ -0,0 +1,135 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#include <Kokkos_UnorderedMap.hpp>
+
+#include <iomanip>
+
+#include <TestGlobal2LocalIds.hpp>
+#include <TestUnorderedMapPerformance.hpp>
+
+#include <TestDynRankView.hpp>
+
+#include <iomanip>
+#include <sstream>
+#include <string>
+#include <fstream>
+
+namespace Performance {
+
+class threads : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+
+    unsigned num_threads = 4;
+
+    if (Kokkos::hwloc::available()) {
+      num_threads = Kokkos::hwloc::get_available_numa_count() *
+                    Kokkos::hwloc::get_available_cores_per_numa() *
+                    Kokkos::hwloc::get_available_threads_per_core();
+
+    }
+
+    std::cout << "Threads: " << num_threads << std::endl;
+
+    Kokkos::Threads::initialize( num_threads );
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::Threads::finalize();
+  }
+};
+
+TEST_F( threads, dynrankview_perf ) 
+{
+  std::cout << "Threads" << std::endl;
+  std::cout << " DynRankView vs View: Initialization Only " << std::endl;
+  test_dynrankview_op_perf<Kokkos::Threads>( 8192 );
+}
+
+TEST_F( threads, global_2_local)
+{
+  std::cout << "Threads" << std::endl;
+  std::cout << "size, create, generate, fill, find" << std::endl;
+  for (unsigned i=Performance::begin_id_size; i<=Performance::end_id_size; i *= Performance::id_step)
+    test_global_to_local_ids<Kokkos::Threads>(i);
+}
+
+TEST_F( threads, unordered_map_performance_near)
+{
+  unsigned num_threads = 4;
+  if (Kokkos::hwloc::available()) {
+    num_threads = Kokkos::hwloc::get_available_numa_count() *
+                  Kokkos::hwloc::get_available_cores_per_numa() *
+                  Kokkos::hwloc::get_available_threads_per_core();
+
+  }
+  std::ostringstream base_file_name;
+  base_file_name << "threads-" << num_threads << "-near";
+  Perf::run_performance_tests<Kokkos::Threads,true>(base_file_name.str());
+}
+
+TEST_F( threads, unordered_map_performance_far)
+{
+  unsigned num_threads = 4;
+  if (Kokkos::hwloc::available()) {
+    num_threads = Kokkos::hwloc::get_available_numa_count() *
+                  Kokkos::hwloc::get_available_cores_per_numa() *
+                  Kokkos::hwloc::get_available_threads_per_core();
+
+  }
+  std::ostringstream base_file_name;
+  base_file_name << "threads-" << num_threads << "-far";
+  Perf::run_performance_tests<Kokkos::Threads,false>(base_file_name.str());
+}
+
+} // namespace Performance
+
+
diff --git a/lib/kokkos/containers/performance_tests/TestUnorderedMapPerformance.hpp b/lib/kokkos/containers/performance_tests/TestUnorderedMapPerformance.hpp
new file mode 100644
index 0000000000..71d1182cbe
--- /dev/null
+++ b/lib/kokkos/containers/performance_tests/TestUnorderedMapPerformance.hpp
@@ -0,0 +1,262 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_TEST_UNORDERED_MAP_PERFORMANCE_HPP
+#define KOKKOS_TEST_UNORDERED_MAP_PERFORMANCE_HPP
+
+#include <impl/Kokkos_Timer.hpp>
+
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <string>
+#include <sstream>
+
+
+namespace Perf {
+
+template <typename Device, bool Near>
+struct UnorderedMapTest
+{
+  typedef Device execution_space;
+  typedef Kokkos::UnorderedMap<uint32_t, uint32_t, execution_space> map_type;
+  typedef typename map_type::histogram_type histogram_type;
+
+  struct value_type {
+    uint32_t failed_count;
+    uint32_t max_list;
+  };
+
+  uint32_t capacity;
+  uint32_t inserts;
+  uint32_t collisions;
+  double   seconds;
+  map_type map;
+  histogram_type histogram;
+
+  UnorderedMapTest( uint32_t arg_capacity, uint32_t arg_inserts, uint32_t arg_collisions)
+    : capacity(arg_capacity)
+    , inserts(arg_inserts)
+    , collisions(arg_collisions)
+    , seconds(0)
+    , map(capacity)
+    , histogram(map.get_histogram())
+  {
+    Kokkos::Timer wall_clock ;
+    wall_clock.reset();
+
+    value_type v = {};
+    int loop_count = 0;
+    do {
+      ++loop_count;
+
+      v = value_type();
+      Kokkos::parallel_reduce(inserts, *this, v);
+
+      if (v.failed_count > 0u) {
+        const uint32_t new_capacity = map.capacity() + ((map.capacity()*3ull)/20u) + v.failed_count/collisions ;
+        map.rehash( new_capacity );
+      }
+    } while (v.failed_count > 0u);
+
+    seconds = wall_clock.seconds();
+
+    switch (loop_count)
+    {
+    case 1u: std::cout << " \033[0;32m" << loop_count << "\033[0m "; break;
+    case 2u: std::cout << " \033[1;31m" << loop_count << "\033[0m "; break;
+    default: std::cout << " \033[0;31m" << loop_count << "\033[0m "; break;
+    }
+    std::cout << std::setprecision(2) << std::fixed << std::setw(5) << (1e9*(seconds/(inserts))) << "; " << std::flush;
+
+    histogram.calculate();
+    Device::fence();
+  }
+
+  void print(std::ostream & metrics_out, std::ostream & length_out, std::ostream & distance_out, std::ostream & block_distance_out)
+  {
+    metrics_out << map.capacity() << " , ";
+    metrics_out << inserts/collisions << " , ";
+    metrics_out << (100.0 * inserts/collisions) / map.capacity() << " , ";
+    metrics_out << inserts << " , ";
+    metrics_out << (map.failed_insert() ? "true" : "false") << " , ";
+    metrics_out << collisions << " , ";
+    metrics_out << 1e9*(seconds/inserts) << " , ";
+    metrics_out << seconds << std::endl;
+
+    length_out << map.capacity() << " , ";
+    length_out << ((100.0 *inserts/collisions) / map.capacity()) << " , ";
+    length_out << collisions << " , ";
+    histogram.print_length(length_out);
+
+    distance_out << map.capacity() << " , ";
+    distance_out << ((100.0 *inserts/collisions) / map.capacity()) << " , ";
+    distance_out << collisions << " , ";
+    histogram.print_distance(distance_out);
+
+    block_distance_out << map.capacity() << " , ";
+    block_distance_out << ((100.0 *inserts/collisions) / map.capacity()) << " , ";
+    block_distance_out << collisions << " , ";
+    histogram.print_block_distance(block_distance_out);
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & v ) const
+  {
+    v.failed_count = 0;
+    v.max_list = 0;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst, const volatile value_type & src ) const
+  {
+    dst.failed_count += src.failed_count;
+    dst.max_list = src.max_list < dst.max_list ? dst.max_list : src.max_list;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(uint32_t i, value_type & v) const
+  {
+    const uint32_t key = Near ? i/collisions : i%(inserts/collisions);
+    typename map_type::insert_result result = map.insert(key,i);
+    v.failed_count += !result.failed() ? 0 : 1;
+    v.max_list = result.list_position() < v.max_list ? v.max_list : result.list_position();
+  }
+
+};
+
+//#define KOKKOS_COLLECT_UNORDERED_MAP_METRICS
+
+template <typename Device, bool Near>
+void run_performance_tests(std::string const & base_file_name)
+{
+#if defined(KOKKOS_COLLECT_UNORDERED_MAP_METRICS)
+  std::string metrics_file_name = base_file_name + std::string("-metrics.csv");
+  std::string length_file_name = base_file_name  + std::string("-length.csv");
+  std::string distance_file_name = base_file_name + std::string("-distance.csv");
+  std::string block_distance_file_name = base_file_name + std::string("-block_distance.csv");
+
+  std::ofstream metrics_out( metrics_file_name.c_str(), std::ofstream::out );
+  std::ofstream length_out( length_file_name.c_str(), std::ofstream::out );
+  std::ofstream distance_out( distance_file_name.c_str(), std::ofstream::out );
+  std::ofstream block_distance_out( block_distance_file_name.c_str(), std::ofstream::out );
+
+
+  /*
+  const double test_ratios[] = {
+     0.50
+   , 0.75
+   , 0.80
+   , 0.85
+   , 0.90
+   , 0.95
+   , 1.00
+   , 1.25
+   , 2.00
+  };
+  */
+
+  const double test_ratios[] = { 1.00 };
+
+  const int num_ratios = sizeof(test_ratios) / sizeof(double);
+
+  /*
+  const uint32_t collisions[] {
+      1
+    , 4
+    , 16
+    , 64
+  };
+  */
+
+  const uint32_t collisions[] = { 16 };
+
+  const int num_collisions = sizeof(collisions) / sizeof(uint32_t);
+
+  // set up file headers
+  metrics_out << "Capacity , Unique , Percent Full , Attempted Inserts , Failed Inserts , Collision Ratio , Nanoseconds/Inserts, Seconds" << std::endl;
+  length_out << "Capacity , Percent Full , ";
+  distance_out << "Capacity , Percent Full , ";
+  block_distance_out << "Capacity , Percent Full , ";
+
+  for (int i=0; i<100; ++i) {
+    length_out << i << " , ";
+    distance_out << i << " , ";
+    block_distance_out << i << " , ";
+  }
+
+  length_out << "\b\b\b   " << std::endl;
+  distance_out << "\b\b\b   " << std::endl;
+  block_distance_out << "\b\b\b   " << std::endl;
+
+  Kokkos::Timer wall_clock ;
+  for (int i=0;  i < num_collisions ; ++i) {
+    wall_clock.reset();
+    std::cout << "Collisions: " << collisions[i] << std::endl;
+    for (int j = 0; j < num_ratios; ++j) {
+      std::cout << std::setprecision(1) << std::fixed << std::setw(5) << (100.0*test_ratios[j]) << "%  " << std::flush;
+      for (uint32_t capacity = 1<<14; capacity < 1<<25; capacity = capacity << 1) {
+        uint32_t inserts = static_cast<uint32_t>(test_ratios[j]*(capacity));
+        std::cout << capacity << std::flush;
+        UnorderedMapTest<Device, Near> test(capacity, inserts*collisions[i], collisions[i]);
+        Device::fence();
+        test.print(metrics_out, length_out, distance_out, block_distance_out);
+      }
+      std::cout << "\b\b  " <<  std::endl;
+
+    }
+    std::cout << "  " << wall_clock.seconds() << " secs" << std::endl;
+  }
+  metrics_out.close();
+  length_out.close();
+  distance_out.close();
+  block_distance_out.close();
+#else
+  (void)base_file_name;
+  std::cout << "skipping test" << std::endl;
+#endif
+}
+
+
+} // namespace Perf
+
+#endif //KOKKOS_TEST_UNORDERED_MAP_PERFORMANCE_HPP
diff --git a/lib/kokkos/containers/src/CMakeLists.txt b/lib/kokkos/containers/src/CMakeLists.txt
new file mode 100644
index 0000000000..da5a791530
--- /dev/null
+++ b/lib/kokkos/containers/src/CMakeLists.txt
@@ -0,0 +1,31 @@
+
+TRIBITS_CONFIGURE_FILE(${PACKAGE_NAME}_config.h)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+#-----------------------------------------------------------------------------
+
+SET(HEADERS "")
+SET(SOURCES "")
+
+SET(HEADERS_IMPL "")
+
+FILE(GLOB HEADERS *.hpp)
+FILE(GLOB HEADERS_IMPL impl/*.hpp)
+FILE(GLOB SOURCES impl/*.cpp)
+
+SET(TRILINOS_INCDIR ${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR})
+
+INSTALL(FILES ${HEADERS_IMPL} DESTINATION ${TRILINOS_INCDIR}/impl/)
+
+TRIBITS_ADD_LIBRARY(
+    kokkoscontainers
+    HEADERS ${HEADERS}
+    NOINSTALLHEADERS ${HEADERS_IMPL}
+    SOURCES ${SOURCES}
+    DEPLIBS
+    )
+
+#-----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/containers/src/Kokkos_Bitset.hpp b/lib/kokkos/containers/src/Kokkos_Bitset.hpp
new file mode 100644
index 0000000000..74da5f61b5
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_Bitset.hpp
@@ -0,0 +1,437 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_BITSET_HPP
+#define KOKKOS_BITSET_HPP
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Functional.hpp>
+
+#include <impl/Kokkos_Bitset_impl.hpp>
+
+#include <stdexcept>
+
+namespace Kokkos {
+
+template <typename Device = Kokkos::DefaultExecutionSpace >
+class Bitset;
+
+template <typename Device = Kokkos::DefaultExecutionSpace >
+class ConstBitset;
+
+template <typename DstDevice, typename SrcDevice>
+void deep_copy( Bitset<DstDevice> & dst, Bitset<SrcDevice> const& src);
+
+template <typename DstDevice, typename SrcDevice>
+void deep_copy( Bitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src);
+
+template <typename DstDevice, typename SrcDevice>
+void deep_copy( ConstBitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src);
+
+
+/// A thread safe view to a bitset
+template <typename Device>
+class Bitset
+{
+public:
+  typedef Device execution_space;
+  typedef unsigned size_type;
+
+  enum { BIT_SCAN_REVERSE = 1u };
+  enum { MOVE_HINT_BACKWARD = 2u };
+
+  enum {
+      BIT_SCAN_FORWARD_MOVE_HINT_FORWARD = 0u
+    , BIT_SCAN_REVERSE_MOVE_HINT_FORWARD = BIT_SCAN_REVERSE
+    , BIT_SCAN_FORWARD_MOVE_HINT_BACKWARD = MOVE_HINT_BACKWARD
+    , BIT_SCAN_REVERSE_MOVE_HINT_BACKWARD = BIT_SCAN_REVERSE | MOVE_HINT_BACKWARD
+  };
+
+private:
+  enum { block_size = static_cast<unsigned>(sizeof(unsigned)*CHAR_BIT) };
+  enum { block_mask = block_size-1u };
+  enum { block_shift = Kokkos::Impl::integral_power_of_two(block_size) };
+
+public:
+
+
+  /// constructor
+  /// arg_size := number of bit in set
+  Bitset(unsigned arg_size = 0u)
+    : m_size(arg_size)
+    , m_last_block_mask(0u)
+    , m_blocks("Bitset", ((m_size + block_mask) >> block_shift) )
+  {
+    for (int i=0, end = static_cast<int>(m_size & block_mask); i < end; ++i) {
+      m_last_block_mask |= 1u << i;
+    }
+  }
+
+  /// assignment
+  Bitset<Device> & operator = (Bitset<Device> const & rhs)
+  {
+    this->m_size = rhs.m_size;
+    this->m_last_block_mask = rhs.m_last_block_mask;
+    this->m_blocks = rhs.m_blocks;
+
+    return *this;
+  }
+
+  /// copy constructor
+  Bitset( Bitset<Device> const & rhs)
+    : m_size( rhs.m_size )
+    , m_last_block_mask( rhs.m_last_block_mask )
+    , m_blocks( rhs.m_blocks )
+  {}
+
+  /// number of bits in the set
+  /// can be call from the host or the device
+  KOKKOS_FORCEINLINE_FUNCTION
+  unsigned size() const
+  { return m_size; }
+
+  /// number of bits which are set to 1
+  /// can only be called from the host
+  unsigned count() const
+  {
+    Impl::BitsetCount< Bitset<Device> > f(*this);
+    return f.apply();
+  }
+
+  /// set all bits to 1
+  /// can only be called from the host
+  void set()
+  {
+    Kokkos::deep_copy(m_blocks, ~0u );
+
+    if (m_last_block_mask) {
+      //clear the unused bits in the last block
+      typedef Kokkos::Impl::DeepCopy< typename execution_space::memory_space, Kokkos::HostSpace > raw_deep_copy;
+      raw_deep_copy( m_blocks.ptr_on_device() + (m_blocks.dimension_0() -1u), &m_last_block_mask, sizeof(unsigned));
+    }
+  }
+
+  /// set all bits to 0
+  /// can only be called from the host
+  void reset()
+  {
+    Kokkos::deep_copy(m_blocks, 0u );
+  }
+
+  /// set all bits to 0
+  /// can only be called from the host
+  void clear()
+  {
+    Kokkos::deep_copy(m_blocks, 0u );
+  }
+
+  /// set i'th bit to 1
+  /// can only be called from the device
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool set( unsigned i ) const
+  {
+    if ( i < m_size ) {
+      unsigned * block_ptr = &m_blocks[ i >> block_shift ];
+      const unsigned mask = 1u << static_cast<int>( i & block_mask );
+
+      return !( atomic_fetch_or( block_ptr, mask ) & mask );
+    }
+    return false;
+  }
+
+  /// set i'th bit to 0
+  /// can only be called from the device
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool reset( unsigned i ) const
+  {
+    if ( i < m_size ) {
+      unsigned * block_ptr = &m_blocks[ i >> block_shift ];
+      const unsigned mask = 1u << static_cast<int>( i & block_mask );
+
+      return atomic_fetch_and( block_ptr, ~mask ) & mask;
+    }
+    return false;
+  }
+
+  /// return true if the i'th bit set to 1
+  /// can only be called from the device
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool test( unsigned i ) const
+  {
+    if ( i < m_size ) {
+      const unsigned block = volatile_load(&m_blocks[ i >> block_shift ]);
+      const unsigned mask = 1u << static_cast<int>( i & block_mask );
+      return block & mask;
+    }
+    return false;
+  }
+
+  /// used with find_any_set_near or find_any_unset_near functions
+  /// returns the max number of times those functions should be call
+  /// when searching for an available bit
+  KOKKOS_FORCEINLINE_FUNCTION
+  unsigned max_hint() const
+  {
+    return m_blocks.dimension_0();
+  }
+
+  /// find a bit set to 1 near the hint
+  /// returns a pair< bool, unsigned> where if result.first is true then result.second is the bit found
+  /// and if result.first is false the result.second is a new hint
+  KOKKOS_INLINE_FUNCTION
+  Kokkos::pair<bool, unsigned> find_any_set_near( unsigned hint , unsigned scan_direction = BIT_SCAN_FORWARD_MOVE_HINT_FORWARD ) const
+  {
+    const unsigned block_idx = (hint >> block_shift) < m_blocks.dimension_0() ? (hint >> block_shift) : 0;
+    const unsigned offset = hint & block_mask;
+    unsigned block = volatile_load(&m_blocks[ block_idx ]);
+    block = !m_last_block_mask || (block_idx < (m_blocks.dimension_0()-1)) ? block : block & m_last_block_mask ;
+
+    return find_any_helper(block_idx, offset, block, scan_direction);
+  }
+
+  /// find a bit set to 0 near the hint
+  /// returns a pair< bool, unsigned> where if result.first is true then result.second is the bit found
+  /// and if result.first is false the result.second is a new hint
+  KOKKOS_INLINE_FUNCTION
+  Kokkos::pair<bool, unsigned> find_any_unset_near( unsigned hint , unsigned scan_direction = BIT_SCAN_FORWARD_MOVE_HINT_FORWARD ) const
+  {
+    const unsigned block_idx = hint >> block_shift;
+    const unsigned offset = hint & block_mask;
+    unsigned block = volatile_load(&m_blocks[ block_idx ]);
+    block = !m_last_block_mask || (block_idx < (m_blocks.dimension_0()-1) ) ? ~block : ~block & m_last_block_mask ;
+
+    return find_any_helper(block_idx, offset, block, scan_direction);
+  }
+
+private:
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  Kokkos::pair<bool, unsigned> find_any_helper(unsigned block_idx, unsigned offset, unsigned block, unsigned scan_direction) const
+  {
+    Kokkos::pair<bool, unsigned> result( block > 0u, 0);
+
+    if (!result.first) {
+      result.second = update_hint( block_idx, offset, scan_direction );
+    }
+    else {
+      result.second = scan_block(  (block_idx << block_shift)
+                                 , offset
+                                 , block
+                                 , scan_direction
+                                );
+    }
+    return result;
+  }
+
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  unsigned scan_block(unsigned block_start, int offset, unsigned block, unsigned scan_direction ) const
+  {
+    offset = !(scan_direction & BIT_SCAN_REVERSE) ? offset : (offset + block_mask) & block_mask;
+    block = Impl::rotate_right(block, offset);
+    return ((( !(scan_direction & BIT_SCAN_REVERSE) ?
+               Impl::bit_scan_forward(block) :
+               Impl::bit_scan_reverse(block)
+             ) + offset
+            ) & block_mask
+           ) + block_start;
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  unsigned update_hint( long long block_idx, unsigned offset, unsigned scan_direction ) const
+  {
+    block_idx += scan_direction & MOVE_HINT_BACKWARD ? -1 : 1;
+    block_idx = block_idx >= 0 ? block_idx : m_blocks.dimension_0() - 1;
+    block_idx = block_idx < static_cast<long long>(m_blocks.dimension_0()) ? block_idx : 0;
+
+    return static_cast<unsigned>(block_idx)*block_size + offset;
+  }
+
+private:
+
+  unsigned m_size;
+  unsigned m_last_block_mask;
+  View< unsigned *, execution_space, MemoryTraits<RandomAccess> > m_blocks;
+
+private:
+  template <typename DDevice>
+  friend class Bitset;
+
+  template <typename DDevice>
+  friend class ConstBitset;
+
+  template <typename Bitset>
+  friend struct Impl::BitsetCount;
+
+  template <typename DstDevice, typename SrcDevice>
+  friend void deep_copy( Bitset<DstDevice> & dst, Bitset<SrcDevice> const& src);
+
+  template <typename DstDevice, typename SrcDevice>
+  friend void deep_copy( Bitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src);
+};
+
+/// a thread-safe view to a const bitset
+/// i.e. can only test bits
+template <typename Device>
+class ConstBitset
+{
+public:
+  typedef Device execution_space;
+  typedef unsigned size_type;
+
+private:
+  enum { block_size = static_cast<unsigned>(sizeof(unsigned)*CHAR_BIT) };
+  enum { block_mask = block_size -1u };
+  enum { block_shift = Kokkos::Impl::integral_power_of_two(block_size) };
+
+public:
+  ConstBitset()
+    : m_size (0)
+  {}
+
+  ConstBitset(Bitset<Device> const& rhs)
+    : m_size(rhs.m_size)
+    , m_blocks(rhs.m_blocks)
+  {}
+
+  ConstBitset(ConstBitset<Device> const& rhs)
+    : m_size( rhs.m_size )
+    , m_blocks( rhs.m_blocks )
+  {}
+
+  ConstBitset<Device> & operator = (Bitset<Device> const & rhs)
+  {
+    this->m_size = rhs.m_size;
+    this->m_blocks = rhs.m_blocks;
+
+    return *this;
+  }
+
+  ConstBitset<Device> & operator = (ConstBitset<Device> const & rhs)
+  {
+    this->m_size = rhs.m_size;
+    this->m_blocks = rhs.m_blocks;
+
+    return *this;
+  }
+
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  unsigned size() const
+  {
+    return m_size;
+  }
+
+  unsigned count() const
+  {
+    Impl::BitsetCount< ConstBitset<Device> > f(*this);
+    return f.apply();
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool test( unsigned i ) const
+  {
+    if ( i < m_size ) {
+      const unsigned block = m_blocks[ i >> block_shift ];
+      const unsigned mask = 1u << static_cast<int>( i & block_mask );
+      return block & mask;
+    }
+    return false;
+  }
+
+private:
+
+  unsigned m_size;
+  View< const unsigned *, execution_space, MemoryTraits<RandomAccess> > m_blocks;
+
+private:
+  template <typename DDevice>
+  friend class ConstBitset;
+
+  template <typename Bitset>
+  friend struct Impl::BitsetCount;
+
+  template <typename DstDevice, typename SrcDevice>
+  friend void deep_copy( Bitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src);
+
+  template <typename DstDevice, typename SrcDevice>
+  friend void deep_copy( ConstBitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src);
+};
+
+
+template <typename DstDevice, typename SrcDevice>
+void deep_copy( Bitset<DstDevice> & dst, Bitset<SrcDevice> const& src)
+{
+  if (dst.size() != src.size()) {
+    throw std::runtime_error("Error: Cannot deep_copy bitsets of different sizes!");
+  }
+
+  typedef Kokkos::Impl::DeepCopy< typename DstDevice::memory_space, typename SrcDevice::memory_space > raw_deep_copy;
+  raw_deep_copy(dst.m_blocks.ptr_on_device(), src.m_blocks.ptr_on_device(), sizeof(unsigned)*src.m_blocks.dimension_0());
+}
+
+template <typename DstDevice, typename SrcDevice>
+void deep_copy( Bitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src)
+{
+  if (dst.size() != src.size()) {
+    throw std::runtime_error("Error: Cannot deep_copy bitsets of different sizes!");
+  }
+
+  typedef Kokkos::Impl::DeepCopy< typename DstDevice::memory_space, typename SrcDevice::memory_space > raw_deep_copy;
+  raw_deep_copy(dst.m_blocks.ptr_on_device(), src.m_blocks.ptr_on_device(), sizeof(unsigned)*src.m_blocks.dimension_0());
+}
+
+template <typename DstDevice, typename SrcDevice>
+void deep_copy( ConstBitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src)
+{
+  if (dst.size() != src.size()) {
+    throw std::runtime_error("Error: Cannot deep_copy bitsets of different sizes!");
+  }
+
+  typedef Kokkos::Impl::DeepCopy< typename DstDevice::memory_space, typename SrcDevice::memory_space > raw_deep_copy;
+  raw_deep_copy(dst.m_blocks.ptr_on_device(), src.m_blocks.ptr_on_device(), sizeof(unsigned)*src.m_blocks.dimension_0());
+}
+
+} // namespace Kokkos
+
+#endif //KOKKOS_BITSET_HPP
diff --git a/lib/kokkos/containers/src/Kokkos_DualView.hpp b/lib/kokkos/containers/src/Kokkos_DualView.hpp
new file mode 100644
index 0000000000..1230df4d97
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_DualView.hpp
@@ -0,0 +1,982 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+/// \file Kokkos_DualView.hpp
+/// \brief Declaration and definition of Kokkos::DualView.
+///
+/// This header file declares and defines Kokkos::DualView and its
+/// related nonmember functions.
+
+#ifndef KOKKOS_DUALVIEW_HPP
+#define KOKKOS_DUALVIEW_HPP
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Error.hpp>
+
+namespace Kokkos {
+
+/* \class DualView
+ * \brief Container to manage mirroring a Kokkos::View that lives
+ *   in device memory with a Kokkos::View that lives in host memory.
+ *
+ * This class provides capabilities to manage data which exists in two
+ * memory spaces at the same time.  It keeps views of the same layout
+ * on two memory spaces as well as modified flags for both
+ * allocations.  Users are responsible for setting the modified flags
+ * manually if they change the data in either memory space, by calling
+ * the sync() method templated on the device where they modified the
+ * data.  Users may synchronize data by calling the modify() function,
+ * templated on the device towards which they want to synchronize
+ * (i.e., the target of the one-way copy operation).
+ *
+ * The DualView class also provides convenience methods such as
+ * realloc, resize and capacity which call the appropriate methods of
+ * the underlying Kokkos::View objects.
+ *
+ * The four template arguments are the same as those of Kokkos::View.
+ * (Please refer to that class' documentation for a detailed
+ * description.)
+ *
+ *   \tparam DataType The type of the entries stored in the container.
+ *
+ *   \tparam Layout The array's layout in memory.
+ *
+ *   \tparam Device The Kokkos Device type.  If its memory space is
+ *     not the same as the host's memory space, then DualView will
+ *     contain two separate Views: one in device memory, and one in
+ *     host memory.  Otherwise, DualView will only store one View.
+ *
+ *   \tparam MemoryTraits (optional) The user's intended memory access
+ *     behavior.  Please see the documentation of Kokkos::View for
+ *     examples.  The default suffices for most users.
+ */
+template< class DataType ,
+          class Arg1Type = void ,
+          class Arg2Type = void ,
+          class Arg3Type = void>
+class DualView : public ViewTraits< DataType , Arg1Type , Arg2Type, Arg3Type >
+{
+public:
+  //! \name Typedefs for device types and various Kokkos::View specializations.
+  //@{
+  typedef ViewTraits< DataType , Arg1Type , Arg2Type, Arg3Type > traits ;
+
+  //! The Kokkos Host Device type;
+  typedef typename traits::host_mirror_space host_mirror_space ;
+
+  //! The type of a Kokkos::View on the device.
+  typedef View< typename traits::data_type ,
+                Arg1Type ,
+                Arg2Type ,
+                Arg3Type > t_dev ;
+
+  /// \typedef t_host
+  /// \brief The type of a Kokkos::View host mirror of \c t_dev.
+  typedef typename t_dev::HostMirror t_host ;
+
+  //! The type of a const View on the device.
+  //! The type of a Kokkos::View on the device.
+  typedef View< typename traits::const_data_type ,
+                Arg1Type ,
+                Arg2Type ,
+                Arg3Type > t_dev_const ;
+
+  /// \typedef t_host_const
+  /// \brief The type of a const View host mirror of \c t_dev_const.
+  typedef typename t_dev_const::HostMirror t_host_const;
+
+  //! The type of a const, random-access View on the device.
+  typedef View< typename traits::const_data_type ,
+                typename traits::array_layout ,
+                typename traits::device_type ,
+                Kokkos::MemoryTraits<Kokkos::RandomAccess> > t_dev_const_randomread ;
+
+  /// \typedef t_host_const_randomread
+  /// \brief The type of a const, random-access View host mirror of
+  ///   \c t_dev_const_randomread.
+  typedef typename t_dev_const_randomread::HostMirror t_host_const_randomread;
+
+  //! The type of an unmanaged View on the device.
+  typedef View< typename traits::data_type ,
+                typename traits::array_layout ,
+                typename traits::device_type ,
+                MemoryUnmanaged> t_dev_um;
+
+  //! The type of an unmanaged View host mirror of \c t_dev_um.
+  typedef View< typename t_host::data_type ,
+                typename t_host::array_layout ,
+                typename t_host::device_type ,
+                MemoryUnmanaged> t_host_um;
+
+  //! The type of a const unmanaged View on the device.
+  typedef View< typename traits::const_data_type ,
+                typename traits::array_layout ,
+                typename traits::device_type ,
+                MemoryUnmanaged> t_dev_const_um;
+
+  //! The type of a const unmanaged View host mirror of \c t_dev_const_um.
+  typedef View<typename t_host::const_data_type,
+               typename t_host::array_layout,
+               typename t_host::device_type,
+               MemoryUnmanaged> t_host_const_um;
+
+  //! The type of a const, random-access View on the device.
+  typedef View< typename t_host::const_data_type ,
+                typename t_host::array_layout ,
+                typename t_host::device_type ,
+                Kokkos::MemoryTraits<Kokkos::Unmanaged|Kokkos::RandomAccess> > t_dev_const_randomread_um ;
+
+  /// \typedef t_host_const_randomread
+  /// \brief The type of a const, random-access View host mirror of
+  ///   \c t_dev_const_randomread.
+  typedef typename t_dev_const_randomread::HostMirror t_host_const_randomread_um;
+
+  //@}
+  //! \name The two View instances.
+  //@{
+
+  t_dev d_view;
+  t_host h_view;
+
+  //@}
+  //! \name Counters to keep track of changes ("modified" flags)
+  //@{
+
+  View<unsigned int,LayoutLeft,typename t_host::execution_space> modified_device;
+  View<unsigned int,LayoutLeft,typename t_host::execution_space> modified_host;
+
+  //@}
+  //! \name Constructors
+  //@{
+
+  /// \brief Empty constructor.
+  ///
+  /// Both device and host View objects are constructed using their
+  /// default constructors.  The "modified" flags are both initialized
+  /// to "unmodified."
+  DualView () :
+    modified_device (View<unsigned int,LayoutLeft,typename t_host::execution_space> ("DualView::modified_device")),
+    modified_host (View<unsigned int,LayoutLeft,typename t_host::execution_space> ("DualView::modified_host"))
+  {}
+
+  /// \brief Constructor that allocates View objects on both host and device.
+  ///
+  /// This constructor works like the analogous constructor of View.
+  /// The first argument is a string label, which is entirely for your
+  /// benefit.  (Different DualView objects may have the same label if
+  /// you like.)  The arguments that follow are the dimensions of the
+  /// View objects.  For example, if the View has three dimensions,
+  /// the first three integer arguments will be nonzero, and you may
+  /// omit the integer arguments that follow.
+  DualView (const std::string& label,
+            const size_t n0 = 0,
+            const size_t n1 = 0,
+            const size_t n2 = 0,
+            const size_t n3 = 0,
+            const size_t n4 = 0,
+            const size_t n5 = 0,
+            const size_t n6 = 0,
+            const size_t n7 = 0)
+    : d_view (label, n0, n1, n2, n3, n4, n5, n6, n7)
+    , h_view (create_mirror_view (d_view)) // without UVM, host View mirrors
+    , modified_device (View<unsigned int,LayoutLeft,typename t_host::execution_space> ("DualView::modified_device"))
+    , modified_host (View<unsigned int,LayoutLeft,typename t_host::execution_space> ("DualView::modified_host"))
+  {}
+
+  //! Copy constructor (shallow copy)
+  template<class SS, class LS, class DS, class MS>
+  DualView (const DualView<SS,LS,DS,MS>& src) :
+    d_view (src.d_view),
+    h_view (src.h_view),
+    modified_device (src.modified_device),
+    modified_host (src.modified_host)
+  {}
+
+  //! Subview constructor
+  template< class SD, class S1 , class S2 , class S3
+          , class Arg0 , class ... Args >
+  DualView( const DualView<SD,S1,S2,S3> & src
+          , const Arg0 & arg0
+          , Args ... args
+          )
+    : d_view( Kokkos::subview( src.d_view , arg0 , args ... ) )
+    , h_view( Kokkos::subview( src.h_view , arg0 , args ... ) )
+    , modified_device (src.modified_device)
+    , modified_host (src.modified_host)
+    {}
+
+  /// \brief Create DualView from existing device and host View objects.
+  ///
+  /// This constructor assumes that the device and host View objects
+  /// are synchronized.  You, the caller, are responsible for making
+  /// sure this is the case before calling this constructor.  After
+  /// this constructor returns, you may use DualView's sync() and
+  /// modify() methods to ensure synchronization of the View objects.
+  ///
+  /// \param d_view_ Device View
+  /// \param h_view_ Host View (must have type t_host = t_dev::HostMirror)
+  DualView (const t_dev& d_view_, const t_host& h_view_) :
+    d_view (d_view_),
+    h_view (h_view_),
+    modified_device (View<unsigned int,LayoutLeft,typename t_host::execution_space> ("DualView::modified_device")),
+    modified_host (View<unsigned int,LayoutLeft,typename t_host::execution_space> ("DualView::modified_host"))
+  {
+#if ! KOKKOS_USING_EXP_VIEW
+    Impl::assert_shapes_are_equal (d_view.shape (), h_view.shape ());
+#else
+    if ( int(d_view.rank)     != int(h_view.rank) ||
+         d_view.dimension_0() != h_view.dimension_0() ||
+         d_view.dimension_1() != h_view.dimension_1() ||
+         d_view.dimension_2() != h_view.dimension_2() ||
+         d_view.dimension_3() != h_view.dimension_3() ||
+         d_view.dimension_4() != h_view.dimension_4() ||
+         d_view.dimension_5() != h_view.dimension_5() ||
+         d_view.dimension_6() != h_view.dimension_6() ||
+         d_view.dimension_7() != h_view.dimension_7() ||
+         d_view.stride_0()    != h_view.stride_0() ||
+         d_view.stride_1()    != h_view.stride_1() ||
+         d_view.stride_2()    != h_view.stride_2() ||
+         d_view.stride_3()    != h_view.stride_3() ||
+         d_view.stride_4()    != h_view.stride_4() ||
+         d_view.stride_5()    != h_view.stride_5() ||
+         d_view.stride_6()    != h_view.stride_6() ||
+         d_view.stride_7()    != h_view.stride_7() ||
+         d_view.span()        != h_view.span() ) {
+      Kokkos::Impl::throw_runtime_exception("DualView constructed with incompatible views");
+    }
+#endif
+  }
+
+  //@}
+  //! \name Methods for synchronizing, marking as modified, and getting Views.
+  //@{
+
+  /// \brief Return a View on a specific device \c Device.
+  ///
+  /// Please don't be afraid of the if_c expression in the return
+  /// value's type.  That just tells the method what the return type
+  /// should be: t_dev if the \c Device template parameter matches
+  /// this DualView's device type, else t_host.
+  ///
+  /// For example, suppose you create a DualView on Cuda, like this:
+  /// \code
+  /// typedef Kokkos::DualView<float, Kokkos::LayoutRight, Kokkos::Cuda> dual_view_type;
+  /// dual_view_type DV ("my dual view", 100);
+  /// \endcode
+  /// If you want to get the CUDA device View, do this:
+  /// \code
+  /// typename dual_view_type::t_dev cudaView = DV.view<Kokkos::Cuda> ();
+  /// \endcode
+  /// and if you want to get the host mirror of that View, do this:
+  /// \code
+  /// typedef typename Kokkos::HostSpace::execution_space host_device_type;
+  /// typename dual_view_type::t_host hostView = DV.view<host_device_type> ();
+  /// \endcode
+  template< class Device >
+  KOKKOS_INLINE_FUNCTION
+  const typename Impl::if_c<
+    Impl::is_same<typename t_dev::memory_space,
+                          typename Device::memory_space>::value,
+    t_dev,
+    t_host>::type& view () const
+  {
+    return Impl::if_c<
+      Impl::is_same<
+        typename t_dev::memory_space,
+        typename Device::memory_space>::value,
+      t_dev,
+      t_host >::select (d_view , h_view);
+  }
+
+  /// \brief Update data on device or host only if data in the other
+  ///   space has been marked as modified.
+  ///
+  /// If \c Device is the same as this DualView's device type, then
+  /// copy data from host to device.  Otherwise, copy data from device
+  /// to host.  In either case, only copy if the source of the copy
+  /// has been modified.
+  ///
+  /// This is a one-way synchronization only.  If the target of the
+  /// copy has been modified, this operation will discard those
+  /// modifications.  It will also reset both device and host modified
+  /// flags.
+  ///
+  /// \note This method doesn't know on its own whether you modified
+  ///   the data in either View.  You must manually mark modified data
+  ///   as modified, by calling the modify() method with the
+  ///   appropriate template parameter.
+  template<class Device>
+  void sync( const typename Impl::enable_if<
+        ( Impl::is_same< typename traits::data_type , typename traits::non_const_data_type>::value) ||
+        ( Impl::is_same< Device , int>::value)
+        , int >::type& = 0)
+  {
+    const unsigned int dev =
+      Impl::if_c<
+        Impl::is_same<
+          typename t_dev::memory_space,
+          typename Device::memory_space>::value ,
+        unsigned int,
+        unsigned int>::select (1, 0);
+
+    if (dev) { // if Device is the same as DualView's device type
+      if ((modified_host () > 0) && (modified_host () >= modified_device ())) {
+        deep_copy (d_view, h_view);
+        modified_host() = modified_device() = 0;
+      }
+    } else { // hopefully Device is the same as DualView's host type
+      if ((modified_device () > 0) && (modified_device () >= modified_host ())) {
+        deep_copy (h_view, d_view);
+        modified_host() = modified_device() = 0;
+      }
+    }
+    if(Impl::is_same<typename t_host::memory_space,typename t_dev::memory_space>::value) {
+      t_dev::execution_space::fence();
+      t_host::execution_space::fence();
+    }
+  }
+
+  template<class Device>
+  void sync ( const typename Impl::enable_if<
+      ( ! Impl::is_same< typename traits::data_type , typename traits::non_const_data_type>::value ) ||
+      ( Impl::is_same< Device , int>::value)
+      , int >::type& = 0 )
+  {
+    const unsigned int dev =
+      Impl::if_c<
+        Impl::is_same<
+          typename t_dev::memory_space,
+          typename Device::memory_space>::value,
+        unsigned int,
+        unsigned int>::select (1, 0);
+    if (dev) { // if Device is the same as DualView's device type
+      if ((modified_host () > 0) && (modified_host () >= modified_device ())) {
+        Impl::throw_runtime_exception("Calling sync on a DualView with a const datatype.");
+      }
+    } else { // hopefully Device is the same as DualView's host type
+      if ((modified_device () > 0) && (modified_device () >= modified_host ())) {
+        Impl::throw_runtime_exception("Calling sync on a DualView with a const datatype.");
+      }
+    }
+  }
+
+  template<class Device>
+  bool need_sync() const
+  {
+    const unsigned int dev =
+      Impl::if_c<
+        Impl::is_same<
+          typename t_dev::memory_space,
+          typename Device::memory_space>::value ,
+        unsigned int,
+        unsigned int>::select (1, 0);
+
+    if (dev) { // if Device is the same as DualView's device type
+      if ((modified_host () > 0) && (modified_host () >= modified_device ())) {
+        return true;
+      }
+    } else { // hopefully Device is the same as DualView's host type
+      if ((modified_device () > 0) && (modified_device () >= modified_host ())) {
+        return true;
+      }
+    }
+    return false;
+  }
+  /// \brief Mark data as modified on the given device \c Device.
+  ///
+  /// If \c Device is the same as this DualView's device type, then
+  /// mark the device's data as modified.  Otherwise, mark the host's
+  /// data as modified.
+  template<class Device>
+  void modify () {
+    const unsigned int dev =
+      Impl::if_c<
+        Impl::is_same<
+          typename t_dev::memory_space,
+          typename Device::memory_space>::value,
+        unsigned int,
+        unsigned int>::select (1, 0);
+
+    if (dev) { // if Device is the same as DualView's device type
+      // Increment the device's modified count.
+      modified_device () = (modified_device () > modified_host () ?
+                            modified_device () : modified_host ()) + 1;
+    } else { // hopefully Device is the same as DualView's host type
+      // Increment the host's modified count.
+      modified_host () = (modified_device () > modified_host () ?
+                          modified_device () : modified_host ())  + 1;
+    }
+  }
+
+  //@}
+  //! \name Methods for reallocating or resizing the View objects.
+  //@{
+
+  /// \brief Reallocate both View objects.
+  ///
+  /// This discards any existing contents of the objects, and resets
+  /// their modified flags.  It does <i>not</i> copy the old contents
+  /// of either View into the new View objects.
+  void realloc( const size_t n0 = 0 ,
+           const size_t n1 = 0 ,
+           const size_t n2 = 0 ,
+           const size_t n3 = 0 ,
+           const size_t n4 = 0 ,
+           const size_t n5 = 0 ,
+           const size_t n6 = 0 ,
+           const size_t n7 = 0 ) {
+    ::Kokkos::realloc(d_view,n0,n1,n2,n3,n4,n5,n6,n7);
+     h_view = create_mirror_view( d_view );
+
+     /* Reset dirty flags */
+     modified_device() = modified_host() = 0;
+  }
+
+  /// \brief Resize both views, copying old contents into new if necessary.
+  ///
+  /// This method only copies the old contents into the new View
+  /// objects for the device which was last marked as modified.
+  void resize( const size_t n0 = 0 ,
+           const size_t n1 = 0 ,
+           const size_t n2 = 0 ,
+           const size_t n3 = 0 ,
+           const size_t n4 = 0 ,
+           const size_t n5 = 0 ,
+           const size_t n6 = 0 ,
+           const size_t n7 = 0 ) {
+   if(modified_device() >= modified_host()) {
+     /* Resize on Device */
+     ::Kokkos::resize(d_view,n0,n1,n2,n3,n4,n5,n6,n7);
+     h_view = create_mirror_view( d_view );
+
+     /* Mark Device copy as modified */
+     modified_device() = modified_device()+1;
+
+   } else {
+     /* Realloc on Device */
+
+     ::Kokkos::realloc(d_view,n0,n1,n2,n3,n4,n5,n6,n7);
+     t_host temp_view = create_mirror_view( d_view );
+
+     /* Remap on Host */
+     Kokkos::deep_copy( temp_view , h_view );
+
+     h_view = temp_view;
+
+     /* Mark Host copy as modified */
+     modified_host() = modified_host()+1;
+   }
+  }
+
+  //@}
+  //! \name Methods for getting capacity, stride, or dimension(s).
+  //@{
+
+  //! The allocation size (same as Kokkos::View::capacity).
+  size_t capacity() const {
+#if KOKKOS_USING_EXP_VIEW
+    return d_view.span();
+#else
+    return d_view.capacity();
+#endif
+  }
+
+  //! Get stride(s) for each dimension.
+  template< typename iType>
+  void stride(iType* stride_) const {
+    d_view.stride(stride_);
+  }
+
+  /* \brief return size of dimension 0 */
+  size_t dimension_0() const {return d_view.dimension_0();}
+  /* \brief return size of dimension 1 */
+  size_t dimension_1() const {return d_view.dimension_1();}
+  /* \brief return size of dimension 2 */
+  size_t dimension_2() const {return d_view.dimension_2();}
+  /* \brief return size of dimension 3 */
+  size_t dimension_3() const {return d_view.dimension_3();}
+  /* \brief return size of dimension 4 */
+  size_t dimension_4() const {return d_view.dimension_4();}
+  /* \brief return size of dimension 5 */
+  size_t dimension_5() const {return d_view.dimension_5();}
+  /* \brief return size of dimension 6 */
+  size_t dimension_6() const {return d_view.dimension_6();}
+  /* \brief return size of dimension 7 */
+  size_t dimension_7() const {return d_view.dimension_7();}
+
+  //@}
+};
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+//
+// Partial specializations of Kokkos::subview() for DualView objects.
+//
+
+#if KOKKOS_USING_EXP_VIEW
+
+namespace Kokkos {
+namespace Impl {
+
+template< class D, class A1, class A2, class A3, class ... Args >
+struct DualViewSubview {
+
+  typedef typename Kokkos::Experimental::Impl::ViewMapping
+    < void
+    , Kokkos::ViewTraits< D, A1, A2, A3 >
+    , Args ...
+    >::traits_type dst_traits ;
+
+  typedef Kokkos::DualView
+    < typename dst_traits::data_type
+    , typename dst_traits::array_layout
+    , typename dst_traits::device_type
+    , typename dst_traits::memory_traits
+    > type ;
+};
+
+} /* namespace Impl */
+
+
+template< class D , class A1 , class A2 , class A3 , class ... Args >
+typename Impl::DualViewSubview<D,A1,A2,A3,Args...>::type
+subview( const DualView<D,A1,A2,A3> & src , Args ... args )
+{
+  return typename
+    Impl::DualViewSubview<D,A1,A2,A3,Args...>::type( src , args ... );
+}
+
+} /* namespace Kokkos */
+
+#else
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+//
+// Partial specializations of Kokkos::subview() for DualView objects.
+//
+
+namespace Kokkos {
+namespace Impl {
+
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type , class SubArg2_type , class SubArg3_type
+        , class SubArg4_type , class SubArg5_type , class SubArg6_type , class SubArg7_type
+        >
+struct ViewSubview< DualView< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type  >
+                  , SubArg0_type , SubArg1_type , SubArg2_type , SubArg3_type
+                  , SubArg4_type , SubArg5_type , SubArg6_type , SubArg7_type >
+{
+private:
+
+  typedef DualView< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type >  SrcViewType ;
+
+  enum { V0 = Impl::is_same< SubArg0_type , void >::value ? 1 : 0 };
+  enum { V1 = Impl::is_same< SubArg1_type , void >::value ? 1 : 0 };
+  enum { V2 = Impl::is_same< SubArg2_type , void >::value ? 1 : 0 };
+  enum { V3 = Impl::is_same< SubArg3_type , void >::value ? 1 : 0 };
+  enum { V4 = Impl::is_same< SubArg4_type , void >::value ? 1 : 0 };
+  enum { V5 = Impl::is_same< SubArg5_type , void >::value ? 1 : 0 };
+  enum { V6 = Impl::is_same< SubArg6_type , void >::value ? 1 : 0 };
+  enum { V7 = Impl::is_same< SubArg7_type , void >::value ? 1 : 0 };
+
+  // The source view rank must be equal to the input argument rank
+  // Once a void argument is encountered all subsequent arguments must be void.
+  enum { InputRank =
+    Impl::StaticAssert<( SrcViewType::rank ==
+                         ( V0 ? 0 : (
+                           V1 ? 1 : (
+                           V2 ? 2 : (
+                           V3 ? 3 : (
+                           V4 ? 4 : (
+                           V5 ? 5 : (
+                           V6 ? 6 : (
+                           V7 ? 7 : 8 ))))))) ))
+                       &&
+                       ( SrcViewType::rank ==
+                         ( 8 - ( V0 + V1 + V2 + V3 + V4 + V5 + V6 + V7 ) ) )
+    >::value ? SrcViewType::rank : 0 };
+
+  enum { R0 = Impl::ViewOffsetRange< SubArg0_type >::is_range ? 1 : 0 };
+  enum { R1 = Impl::ViewOffsetRange< SubArg1_type >::is_range ? 1 : 0 };
+  enum { R2 = Impl::ViewOffsetRange< SubArg2_type >::is_range ? 1 : 0 };
+  enum { R3 = Impl::ViewOffsetRange< SubArg3_type >::is_range ? 1 : 0 };
+  enum { R4 = Impl::ViewOffsetRange< SubArg4_type >::is_range ? 1 : 0 };
+  enum { R5 = Impl::ViewOffsetRange< SubArg5_type >::is_range ? 1 : 0 };
+  enum { R6 = Impl::ViewOffsetRange< SubArg6_type >::is_range ? 1 : 0 };
+  enum { R7 = Impl::ViewOffsetRange< SubArg7_type >::is_range ? 1 : 0 };
+
+  enum { OutputRank = unsigned(R0) + unsigned(R1) + unsigned(R2) + unsigned(R3)
+                    + unsigned(R4) + unsigned(R5) + unsigned(R6) + unsigned(R7) };
+
+  // Reverse
+  enum { R0_rev = 0 == InputRank ? 0u : (
+                  1 == InputRank ? unsigned(R0) : (
+                  2 == InputRank ? unsigned(R1) : (
+                  3 == InputRank ? unsigned(R2) : (
+                  4 == InputRank ? unsigned(R3) : (
+                  5 == InputRank ? unsigned(R4) : (
+                  6 == InputRank ? unsigned(R5) : (
+                  7 == InputRank ? unsigned(R6) : unsigned(R7) ))))))) };
+
+  typedef typename SrcViewType::array_layout  SrcViewLayout ;
+
+  // Choose array layout, attempting to preserve original layout if at all possible.
+  typedef typename Impl::if_c<
+     ( // Same Layout IF
+       // OutputRank 0
+       ( OutputRank == 0 )
+       ||
+       // OutputRank 1 or 2, InputLayout Left, Interval 0
+       // because single stride one or second index has a stride.
+       ( OutputRank <= 2 && R0 && Impl::is_same<SrcViewLayout,LayoutLeft>::value )
+       ||
+       // OutputRank 1 or 2, InputLayout Right, Interval [InputRank-1]
+       // because single stride one or second index has a stride.
+       ( OutputRank <= 2 && R0_rev && Impl::is_same<SrcViewLayout,LayoutRight>::value )
+     ), SrcViewLayout , Kokkos::LayoutStride >::type OutputViewLayout ;
+
+  // Choose data type as a purely dynamic rank array to accomodate a runtime range.
+  typedef typename Impl::if_c< OutputRank == 0 , typename SrcViewType::value_type ,
+          typename Impl::if_c< OutputRank == 1 , typename SrcViewType::value_type *,
+          typename Impl::if_c< OutputRank == 2 , typename SrcViewType::value_type **,
+          typename Impl::if_c< OutputRank == 3 , typename SrcViewType::value_type ***,
+          typename Impl::if_c< OutputRank == 4 , typename SrcViewType::value_type ****,
+          typename Impl::if_c< OutputRank == 5 , typename SrcViewType::value_type *****,
+          typename Impl::if_c< OutputRank == 6 , typename SrcViewType::value_type ******,
+          typename Impl::if_c< OutputRank == 7 , typename SrcViewType::value_type *******,
+                                                 typename SrcViewType::value_type ********
+  >::type >::type >::type >::type >::type >::type >::type >::type  OutputData ;
+
+  // Choose space.
+  // If the source view's template arg1 or arg2 is a space then use it,
+  // otherwise use the source view's execution space.
+
+  typedef typename Impl::if_c< Impl::is_space< SrcArg1Type >::value , SrcArg1Type ,
+          typename Impl::if_c< Impl::is_space< SrcArg2Type >::value , SrcArg2Type , typename SrcViewType::execution_space
+  >::type >::type OutputSpace ;
+
+public:
+
+  // If keeping the layout then match non-data type arguments
+  // else keep execution space and memory traits.
+  typedef typename
+    Impl::if_c< Impl::is_same< SrcViewLayout , OutputViewLayout >::value
+              , Kokkos::DualView< OutputData , SrcArg1Type , SrcArg2Type , SrcArg3Type >
+              , Kokkos::DualView< OutputData , OutputViewLayout , OutputSpace
+                            , typename SrcViewType::memory_traits >
+              >::type  type ;
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+namespace Kokkos {
+
+template< class D , class A1 , class A2 , class A3 ,
+          class ArgType0 >
+typename Impl::ViewSubview< DualView<D,A1,A2,A3>
+                          , ArgType0 , void , void , void
+                          , void , void , void , void
+                          >::type
+subview( const DualView<D,A1,A2,A3> & src ,
+         const ArgType0 & arg0 )
+{
+  typedef typename
+    Impl::ViewSubview< DualView<D,A1,A2,A3>
+                 , ArgType0 , void , void , void
+                 , void , void , void , void
+                 >::type
+      DstViewType ;
+  DstViewType sub_view;
+  sub_view.d_view = subview(src.d_view,arg0);
+  sub_view.h_view = subview(src.h_view,arg0);
+  sub_view.modified_device = src.modified_device;
+  sub_view.modified_host = src.modified_host;
+  return sub_view;
+}
+
+
+template< class D , class A1 , class A2 , class A3 ,
+          class ArgType0 , class ArgType1 >
+typename Impl::ViewSubview< DualView<D,A1,A2,A3>
+                          , ArgType0 , ArgType1 , void , void
+                          , void , void , void , void
+                          >::type
+subview( const DualView<D,A1,A2,A3> & src ,
+         const ArgType0 & arg0 ,
+         const ArgType1 & arg1 )
+{
+  typedef typename
+    Impl::ViewSubview< DualView<D,A1,A2,A3>
+                 , ArgType0 , ArgType1 , void , void
+                 , void , void , void , void
+                 >::type
+      DstViewType ;
+  DstViewType sub_view;
+  sub_view.d_view = subview(src.d_view,arg0,arg1);
+  sub_view.h_view = subview(src.h_view,arg0,arg1);
+  sub_view.modified_device = src.modified_device;
+  sub_view.modified_host = src.modified_host;
+  return sub_view;
+}
+
+template< class D , class A1 , class A2 , class A3 ,
+          class ArgType0 , class ArgType1 , class ArgType2 >
+typename Impl::ViewSubview< DualView<D,A1,A2,A3>
+                          , ArgType0 , ArgType1 , ArgType2 , void
+                          , void , void , void , void
+                          >::type
+subview( const DualView<D,A1,A2,A3> & src ,
+         const ArgType0 & arg0 ,
+         const ArgType1 & arg1 ,
+         const ArgType2 & arg2 )
+{
+  typedef typename
+    Impl::ViewSubview< DualView<D,A1,A2,A3>
+                 , ArgType0 , ArgType1 , ArgType2 , void
+                 , void , void , void , void
+                 >::type
+      DstViewType ;
+  DstViewType sub_view;
+  sub_view.d_view = subview(src.d_view,arg0,arg1,arg2);
+  sub_view.h_view = subview(src.h_view,arg0,arg1,arg2);
+  sub_view.modified_device = src.modified_device;
+  sub_view.modified_host = src.modified_host;
+  return sub_view;
+}
+
+template< class D , class A1 , class A2 , class A3 ,
+          class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 >
+typename Impl::ViewSubview< DualView<D,A1,A2,A3>
+                          , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                          , void , void , void , void
+                          >::type
+subview( const DualView<D,A1,A2,A3> & src ,
+         const ArgType0 & arg0 ,
+         const ArgType1 & arg1 ,
+         const ArgType2 & arg2 ,
+         const ArgType3 & arg3 )
+{
+  typedef typename
+    Impl::ViewSubview< DualView<D,A1,A2,A3>
+                 , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                 , void , void , void , void
+                 >::type
+      DstViewType ;
+  DstViewType sub_view;
+  sub_view.d_view = subview(src.d_view,arg0,arg1,arg2,arg3);
+  sub_view.h_view = subview(src.h_view,arg0,arg1,arg2,arg3);
+  sub_view.modified_device = src.modified_device;
+  sub_view.modified_host = src.modified_host;
+  return sub_view;
+}
+
+template< class D , class A1 , class A2 , class A3 ,
+          class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 ,
+          class ArgType4 >
+typename Impl::ViewSubview< DualView<D,A1,A2,A3>
+                          , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                          , ArgType4 , void , void , void
+                          >::type
+subview( const DualView<D,A1,A2,A3> & src ,
+         const ArgType0 & arg0 ,
+         const ArgType1 & arg1 ,
+         const ArgType2 & arg2 ,
+         const ArgType3 & arg3 ,
+         const ArgType4 & arg4 )
+{
+  typedef typename
+    Impl::ViewSubview< DualView<D,A1,A2,A3>
+                 , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                 , ArgType4 , void , void ,void
+                 >::type
+      DstViewType ;
+  DstViewType sub_view;
+  sub_view.d_view = subview(src.d_view,arg0,arg1,arg2,arg3,arg4);
+  sub_view.h_view = subview(src.h_view,arg0,arg1,arg2,arg3,arg4);
+  sub_view.modified_device = src.modified_device;
+  sub_view.modified_host = src.modified_host;
+  return sub_view;
+}
+
+template< class D , class A1 , class A2 , class A3 ,
+          class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 ,
+          class ArgType4 , class ArgType5 >
+typename Impl::ViewSubview< DualView<D,A1,A2,A3>
+                          , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                          , ArgType4 , ArgType5 , void , void
+                          >::type
+subview( const DualView<D,A1,A2,A3> & src ,
+         const ArgType0 & arg0 ,
+         const ArgType1 & arg1 ,
+         const ArgType2 & arg2 ,
+         const ArgType3 & arg3 ,
+         const ArgType4 & arg4 ,
+         const ArgType5 & arg5 )
+{
+  typedef typename
+    Impl::ViewSubview< DualView<D,A1,A2,A3>
+                 , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                 , ArgType4 , ArgType5 , void , void
+                 >::type
+      DstViewType ;
+  DstViewType sub_view;
+  sub_view.d_view = subview(src.d_view,arg0,arg1,arg2,arg3,arg4,arg5);
+  sub_view.h_view = subview(src.h_view,arg0,arg1,arg2,arg3,arg4,arg5);
+  sub_view.modified_device = src.modified_device;
+  sub_view.modified_host = src.modified_host;
+  return sub_view;
+}
+
+template< class D , class A1 , class A2 , class A3 ,
+          class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 ,
+          class ArgType4 , class ArgType5 , class ArgType6 >
+typename Impl::ViewSubview< DualView<D,A1,A2,A3>
+                          , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                          , ArgType4 , ArgType5 , ArgType6 , void
+                          >::type
+subview( const DualView<D,A1,A2,A3> & src ,
+         const ArgType0 & arg0 ,
+         const ArgType1 & arg1 ,
+         const ArgType2 & arg2 ,
+         const ArgType3 & arg3 ,
+         const ArgType4 & arg4 ,
+         const ArgType5 & arg5 ,
+         const ArgType6 & arg6 )
+{
+  typedef typename
+    Impl::ViewSubview< DualView<D,A1,A2,A3>
+                 , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                 , ArgType4 , ArgType5 , ArgType6 , void
+                 >::type
+      DstViewType ;
+  DstViewType sub_view;
+  sub_view.d_view = subview(src.d_view,arg0,arg1,arg2,arg3,arg4,arg5,arg6);
+  sub_view.h_view = subview(src.h_view,arg0,arg1,arg2,arg3,arg4,arg5,arg6);
+  sub_view.modified_device = src.modified_device;
+  sub_view.modified_host = src.modified_host;
+  return sub_view;
+}
+
+template< class D , class A1 , class A2 , class A3 ,
+          class ArgType0 , class ArgType1 , class ArgType2 , class ArgType3 ,
+          class ArgType4 , class ArgType5 , class ArgType6 , class ArgType7 >
+typename Impl::ViewSubview< DualView<D,A1,A2,A3>
+                          , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                          , ArgType4 , ArgType5 , ArgType6 , ArgType7
+                          >::type
+subview( const DualView<D,A1,A2,A3> & src ,
+         const ArgType0 & arg0 ,
+         const ArgType1 & arg1 ,
+         const ArgType2 & arg2 ,
+         const ArgType3 & arg3 ,
+         const ArgType4 & arg4 ,
+         const ArgType5 & arg5 ,
+         const ArgType6 & arg6 ,
+         const ArgType7 & arg7 )
+{
+  typedef typename
+    Impl::ViewSubview< DualView<D,A1,A2,A3>
+                 , ArgType0 , ArgType1 , ArgType2 , ArgType3
+                 , ArgType4 , ArgType5 , ArgType6 , ArgType7
+                 >::type
+      DstViewType ;
+  DstViewType sub_view;
+  sub_view.d_view = subview(src.d_view,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+  sub_view.h_view = subview(src.h_view,arg0,arg1,arg2,arg3,arg4,arg5,arg6,arg7);
+  sub_view.modified_device = src.modified_device;
+  sub_view.modified_host = src.modified_host;
+  return sub_view;
+}
+
+} // namespace Kokkos
+
+#endif /* KOKKOS_USING_EXP_VIEW */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+//
+// Partial specialization of Kokkos::deep_copy() for DualView objects.
+//
+
+template< class DT , class DL , class DD , class DM ,
+          class ST , class SL , class SD , class SM >
+void
+deep_copy (DualView<DT,DL,DD,DM> dst, // trust me, this must not be a reference
+           const DualView<ST,SL,SD,SM>& src )
+{
+  if (src.modified_device () >= src.modified_host ()) {
+    deep_copy (dst.d_view, src.d_view);
+    dst.template modify<typename DualView<DT,DL,DD,DM>::device_type> ();
+  } else {
+    deep_copy (dst.h_view, src.h_view);
+    dst.template modify<typename DualView<DT,DL,DD,DM>::host_mirror_space> ();
+  }
+}
+
+template< class ExecutionSpace ,
+          class DT , class DL , class DD , class DM ,
+          class ST , class SL , class SD , class SM >
+void
+deep_copy (const ExecutionSpace& exec ,
+           DualView<DT,DL,DD,DM> dst, // trust me, this must not be a reference
+           const DualView<ST,SL,SD,SM>& src )
+{
+  if (src.modified_device () >= src.modified_host ()) {
+    deep_copy (exec, dst.d_view, src.d_view);
+    dst.template modify<typename DualView<DT,DL,DD,DM>::device_type> ();
+  } else {
+    deep_copy (exec, dst.h_view, src.h_view);
+    dst.template modify<typename DualView<DT,DL,DD,DM>::host_mirror_space> ();
+  }
+}
+
+} // namespace Kokkos
+
+#endif
diff --git a/lib/kokkos/containers/src/Kokkos_DynRankView.hpp b/lib/kokkos/containers/src/Kokkos_DynRankView.hpp
new file mode 100644
index 0000000000..f72277700a
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_DynRankView.hpp
@@ -0,0 +1,1834 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/// \file Kokkos_DynRankView.hpp
+/// \brief Declaration and definition of Kokkos::Experimental::DynRankView.
+///
+/// This header file declares and defines Kokkos::Experimental::DynRankView and its
+/// related nonmember functions.
+/*
+ *   Changes from View
+ *   1. The rank of the DynRankView is returned by the method rank()
+ *   2. Max rank of a DynRankView is 7
+ *   3. subview name is subdynrankview
+ *   4. Every subdynrankview is returned with LayoutStride
+ *
+ *   NEW: Redesigned DynRankView
+ *   5. subview function name now available
+ *   6. Copy and Copy-Assign View to DynRankView
+ *   7. deep_copy between Views and DynRankViews
+ *   8. rank( view ); returns the rank of View or DynRankView
+ */
+
+#ifndef KOKKOS_DYNRANKVIEW_HPP
+#define KOKKOS_DYNRANKVIEW_HPP
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <type_traits>
+
+namespace Kokkos {
+namespace Experimental {
+
+template< typename DataType , class ... Properties >
+class DynRankView;  //forward declare
+
+namespace Impl {
+
+template <typename Specialize>
+struct DynRankDimTraits {
+
+  enum : size_t{unspecified = ~size_t(0)};
+
+  // Compute the rank of the view from the nonzero dimension arguments.
+  KOKKOS_INLINE_FUNCTION
+  static size_t computeRank( const size_t N0
+                           , const size_t N1
+                           , const size_t N2
+                           , const size_t N3
+                           , const size_t N4
+                           , const size_t N5
+                           , const size_t N6
+                           , const size_t N7 )
+  {
+    return
+      (   (N6 == unspecified && N5 == unspecified && N4 == unspecified && N3 == unspecified && N2 == unspecified && N1 == unspecified && N0 == unspecified) ? 0
+      : ( (N6 == unspecified && N5 == unspecified && N4 == unspecified && N3 == unspecified && N2 == unspecified && N1 == unspecified) ? 1
+      : ( (N6 == unspecified && N5 == unspecified && N4 == unspecified && N3 == unspecified && N2 == unspecified) ? 2
+      : ( (N6 == unspecified && N5 == unspecified && N4 == unspecified && N3 == unspecified) ? 3
+      : ( (N6 == unspecified && N5 == unspecified && N4 == unspecified) ? 4
+      : ( (N6 == unspecified && N5 == unspecified) ? 5
+      : ( (N6 == unspecified) ? 6
+      : 7 ) ) ) ) ) ) );
+  }
+
+  // Compute the rank of the view from the nonzero layout arguments.
+  template <typename Layout>
+  KOKKOS_INLINE_FUNCTION
+  static size_t computeRank( const Layout& layout )
+  {
+    return computeRank( layout.dimension[0]
+                      , layout.dimension[1]
+                      , layout.dimension[2]
+                      , layout.dimension[3]
+                      , layout.dimension[4]
+                      , layout.dimension[5]
+                      , layout.dimension[6]
+                      , layout.dimension[7] );
+  }
+
+  // Create the layout for the rank-7 view.
+  // Non-strided Layout
+  template <typename Layout>
+  KOKKOS_INLINE_FUNCTION
+  static typename std::enable_if< (std::is_same<Layout , Kokkos::LayoutRight>::value || std::is_same<Layout , Kokkos::LayoutLeft>::value) , Layout >::type createLayout( const Layout& layout )
+  {
+    return Layout( layout.dimension[0] != unspecified ? layout.dimension[0] : 1
+                 , layout.dimension[1] != unspecified ? layout.dimension[1] : 1
+                 , layout.dimension[2] != unspecified ? layout.dimension[2] : 1
+                 , layout.dimension[3] != unspecified ? layout.dimension[3] : 1
+                 , layout.dimension[4] != unspecified ? layout.dimension[4] : 1
+                 , layout.dimension[5] != unspecified ? layout.dimension[5] : 1
+                 , layout.dimension[6] != unspecified ? layout.dimension[6] : 1
+                 , layout.dimension[7] != unspecified ? layout.dimension[7] : 1
+                 );
+  }
+
+  // LayoutStride
+  template <typename Layout>
+  KOKKOS_INLINE_FUNCTION
+  static typename std::enable_if< (std::is_same<Layout , Kokkos::LayoutStride>::value) , Layout>::type createLayout( const Layout& layout )
+  {
+    return Layout( layout.dimension[0] != unspecified ? layout.dimension[0] : 1
+                 , layout.stride[0] 
+                 , layout.dimension[1] != unspecified ? layout.dimension[1] : 1
+                 , layout.stride[1] 
+                 , layout.dimension[2] != unspecified ? layout.dimension[2] : 1
+                 , layout.stride[2] 
+                 , layout.dimension[3] != unspecified ? layout.dimension[3] : 1
+                 , layout.stride[3] 
+                 , layout.dimension[4] != unspecified ? layout.dimension[4] : 1
+                 , layout.stride[4] 
+                 , layout.dimension[5] != unspecified ? layout.dimension[5] : 1
+                 , layout.stride[5] 
+                 , layout.dimension[6] != unspecified ? layout.dimension[6] : 1
+                 , layout.stride[6] 
+                 , layout.dimension[7] != unspecified ? layout.dimension[7] : 1
+                 , layout.stride[7] 
+                 );
+  }
+
+  // Create a view from the given dimension arguments.
+  // This is only necessary because the shmem constructor doesn't take a layout.
+  template <typename ViewType, typename ViewArg>
+  static ViewType createView( const ViewArg& arg
+                            , const size_t N0
+                            , const size_t N1
+                            , const size_t N2
+                            , const size_t N3
+                            , const size_t N4
+                            , const size_t N5
+                            , const size_t N6
+                            , const size_t N7 )
+  {
+    return ViewType( arg
+                   , N0 != unspecified ? N0 : 1
+                   , N1 != unspecified ? N1 : 1
+                   , N2 != unspecified ? N2 : 1
+                   , N3 != unspecified ? N3 : 1
+                   , N4 != unspecified ? N4 : 1
+                   , N5 != unspecified ? N5 : 1
+                   , N6 != unspecified ? N6 : 1
+                   , N7 != unspecified ? N7 : 1 );
+  }
+};
+
+  // Non-strided Layout
+  template <typename Layout , typename iType>
+  KOKKOS_INLINE_FUNCTION
+  static typename std::enable_if< (std::is_same<Layout , Kokkos::LayoutRight>::value || std::is_same<Layout , Kokkos::LayoutLeft>::value) && std::is_integral<iType>::value , Layout >::type reconstructLayout( const Layout& layout , iType dynrank )
+  {
+    return Layout( dynrank > 0 ? layout.dimension[0] : ~size_t(0) 
+                 , dynrank > 1 ? layout.dimension[1] : ~size_t(0)
+                 , dynrank > 2 ? layout.dimension[2] : ~size_t(0)
+                 , dynrank > 3 ? layout.dimension[3] : ~size_t(0)
+                 , dynrank > 4 ? layout.dimension[4] : ~size_t(0)
+                 , dynrank > 5 ? layout.dimension[5] : ~size_t(0)
+                 , dynrank > 6 ? layout.dimension[6] : ~size_t(0)
+                 , dynrank > 7 ? layout.dimension[7] : ~size_t(0)
+                 );
+  }
+
+  // LayoutStride
+  template <typename Layout , typename iType>
+  KOKKOS_INLINE_FUNCTION
+  static typename std::enable_if< (std::is_same<Layout , Kokkos::LayoutStride>::value) && std::is_integral<iType>::value , Layout >::type reconstructLayout( const Layout& layout , iType dynrank )
+  {
+    return Layout( dynrank > 0 ? layout.dimension[0] : ~size_t(0)
+                 , dynrank > 0 ? layout.stride[0] : (0) 
+                 , dynrank > 1 ? layout.dimension[1] : ~size_t(0)
+                 , dynrank > 1 ? layout.stride[1] : (0) 
+                 , dynrank > 2 ? layout.dimension[2] : ~size_t(0)
+                 , dynrank > 2 ? layout.stride[2] : (0) 
+                 , dynrank > 3 ? layout.dimension[3] : ~size_t(0)
+                 , dynrank > 3 ? layout.stride[3] : (0) 
+                 , dynrank > 4 ? layout.dimension[4] : ~size_t(0)
+                 , dynrank > 4 ? layout.stride[4] : (0) 
+                 , dynrank > 5 ? layout.dimension[5] : ~size_t(0)
+                 , dynrank > 5 ? layout.stride[5] : (0) 
+                 , dynrank > 6 ? layout.dimension[6] : ~size_t(0)
+                 , dynrank > 6 ? layout.stride[6] : (0) 
+                 , dynrank > 7 ? layout.dimension[7] : ~size_t(0)
+                 , dynrank > 7 ? layout.stride[7] : (0) 
+                 );
+  }
+
+  template < typename DynRankViewType , typename iType >
+  void verify_dynrankview_rank ( iType N , const DynRankViewType &drv )
+  {
+    if ( static_cast<iType>(drv.rank()) > N )
+       {
+         Kokkos::abort( "Need at least rank arguments to the operator()" ); 
+       }
+  }
+
+
+/** \brief  Assign compatible default mappings */
+struct ViewToDynRankViewTag {};
+
+template< class DstTraits , class SrcTraits >
+class ViewMapping< DstTraits , SrcTraits ,
+  typename std::enable_if<(
+    std::is_same< typename DstTraits::memory_space , typename SrcTraits::memory_space >::value
+    &&
+    std::is_same< typename DstTraits::specialize , void >::value
+    &&
+    std::is_same< typename SrcTraits::specialize , void >::value
+    &&
+    (
+      std::is_same< typename DstTraits::array_layout , typename SrcTraits::array_layout >::value
+      ||
+      (
+        (
+          std::is_same< typename DstTraits::array_layout , Kokkos::LayoutLeft >::value ||
+          std::is_same< typename DstTraits::array_layout , Kokkos::LayoutRight >::value ||
+          std::is_same< typename DstTraits::array_layout , Kokkos::LayoutStride >::value
+        )
+        &&
+        (
+          std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value ||
+          std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value ||
+          std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutStride >::value
+        )
+      )
+    )
+  ) , ViewToDynRankViewTag >::type >
+{
+private:
+
+  enum { is_assignable_value_type =
+    std::is_same< typename DstTraits::value_type
+                , typename SrcTraits::value_type >::value ||
+    std::is_same< typename DstTraits::value_type
+                , typename SrcTraits::const_value_type >::value };
+
+  enum { is_assignable_layout =
+    std::is_same< typename DstTraits::array_layout
+                , typename SrcTraits::array_layout >::value ||
+    std::is_same< typename DstTraits::array_layout
+                , Kokkos::LayoutStride >::value 
+    };
+
+public:
+
+  enum { is_assignable = is_assignable_value_type &&
+                         is_assignable_layout };
+
+  typedef ViewMapping< DstTraits , void >  DstType ;
+  typedef ViewMapping< SrcTraits , void >  SrcType ;
+
+  template < typename DT , typename ... DP , typename ST , typename ... SP >
+  KOKKOS_INLINE_FUNCTION
+  static void assign( Kokkos::Experimental::DynRankView< DT , DP...> & dst ,  const Kokkos::View< ST , SP... > & src )
+    {
+      static_assert( is_assignable_value_type
+                   , "View assignment must have same value type or const = non-const" );
+
+      static_assert( is_assignable_layout
+                   , "View assignment must have compatible layout or have rank <= 1" );
+
+    // Removed dimension checks...
+
+      typedef typename DstType::offset_type  dst_offset_type ;
+      dst.m_map.m_offset = dst_offset_type(std::integral_constant<unsigned,0>() , src.layout() ); //Check this for integer input1 for padding, etc
+      dst.m_map.m_handle = Kokkos::Experimental::Impl::ViewDataHandle< DstTraits >::assign( src.m_map.m_handle , src.m_track );
+      dst.m_track.assign( src.m_track , DstTraits::is_managed );
+      dst.m_rank = src.Rank ;
+    }
+};
+
+} //end Impl
+
+/* \class DynRankView
+ * \brief Container that creates a Kokkos view with rank determined at runtime. 
+ *   Essentially this is a rank 7 view that wraps the access operators
+ *   to yield the functionality of a view 
+ *
+ *   Changes from View
+ *   1. The rank of the DynRankView is returned by the method rank()
+ *   2. Max rank of a DynRankView is 7
+ *   3. subview name is subdynrankview
+ *   4. Every subdynrankview is returned with LayoutStride
+ *
+ *   NEW: Redesigned DynRankView
+ *   5. subview function name now available
+ *   6. Copy and Copy-Assign View to DynRankView
+ *   7. deep_copy between Views and DynRankViews
+ *   8. rank( view ); returns the rank of View or DynRankView
+ *
+ */
+
+template< class > struct is_dyn_rank_view : public std::false_type {};
+
+template< class D, class ... P >
+struct is_dyn_rank_view< Kokkos::Experimental::DynRankView<D,P...> > : public std::true_type {};
+
+
+template< typename DataType , class ... Properties >
+class DynRankView : public ViewTraits< DataType , Properties ... >
+{
+  static_assert( !std::is_array<DataType>::value && !std::is_pointer<DataType>::value , "Cannot template DynRankView with array or pointer datatype - must be pod" );
+
+private: 
+  template < class , class ... > friend class DynRankView ;
+//  template < class , class ... > friend class Kokkos::Experimental::View ; //unnecessary now...
+  template < class , class ... > friend class Impl::ViewMapping ;
+
+public: 
+  typedef ViewTraits< DataType , Properties ... > drvtraits ;
+
+  typedef View< DataType******* , Properties...> view_type ; 
+
+  typedef ViewTraits< DataType******* , Properties ... > traits ;
+
+
+private:
+  typedef Kokkos::Experimental::Impl::ViewMapping< traits , void > map_type ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker      track_type ;
+
+  track_type  m_track ;
+  map_type    m_map ;
+  unsigned m_rank;
+
+public: 
+  KOKKOS_INLINE_FUNCTION
+  view_type & DownCast() const { return ( view_type & ) (*this); }
+  KOKKOS_INLINE_FUNCTION
+  const view_type & ConstDownCast() const { return (const view_type & ) (*this); }
+
+  //Types below - at least the HostMirror requires the value_type, NOT the rank 7 data_type of the traits
+
+  /** \brief  Compatible view of array of scalar types */
+  typedef DynRankView< typename drvtraits::scalar_array_type ,
+                typename drvtraits::array_layout ,
+                typename drvtraits::device_type ,
+                typename drvtraits::memory_traits >
+    array_type ;
+
+  /** \brief  Compatible view of const data type */
+  typedef DynRankView< typename drvtraits::const_data_type ,
+                typename drvtraits::array_layout ,
+                typename drvtraits::device_type ,
+                typename drvtraits::memory_traits >
+    const_type ;
+
+  /** \brief  Compatible view of non-const data type */
+  typedef DynRankView< typename drvtraits::non_const_data_type ,
+                typename drvtraits::array_layout ,
+                typename drvtraits::device_type ,
+                typename drvtraits::memory_traits >
+    non_const_type ;
+
+  /** \brief  Compatible HostMirror view */
+  typedef DynRankView< typename drvtraits::non_const_data_type ,
+                typename drvtraits::array_layout ,
+                typename drvtraits::host_mirror_space >
+    HostMirror ;
+
+
+  //----------------------------------------
+  // Domain rank and extents
+
+//  enum { Rank = map_type::Rank }; //Will be dyn rank of 7 always, keep the enum?
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename std::enable_if< std::is_integral<iType>::value , size_t >::type
+  extent( const iType & r ) const
+    { return m_map.extent(r); }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename std::enable_if< std::is_integral<iType>::value , int >::type
+  extent_int( const iType & r ) const
+    { return static_cast<int>(m_map.extent(r)); }
+
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename traits::array_layout layout() const
+    { return m_map.layout(); }
+
+  //----------------------------------------
+  /*  Deprecate all 'dimension' functions in favor of
+   *  ISO/C++ vocabulary 'extent'.
+   */
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename std::enable_if< std::is_integral<iType>::value , size_t >::type
+  dimension( const iType & r ) const { return extent( r ); }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_0() const { return m_map.dimension_0(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return m_map.dimension_1(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return m_map.dimension_2(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return m_map.dimension_3(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return m_map.dimension_4(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return m_map.dimension_5(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return m_map.dimension_6(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return m_map.dimension_7(); }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t size() const { return m_map.dimension_0() *
+                                                                m_map.dimension_1() *
+                                                                m_map.dimension_2() *
+                                                                m_map.dimension_3() *
+                                                                m_map.dimension_4() *
+                                                                m_map.dimension_5() *
+                                                                m_map.dimension_6() *
+                                                                m_map.dimension_7(); }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return m_map.stride_0(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return m_map.stride_1(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return m_map.stride_2(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return m_map.stride_3(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return m_map.stride_4(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return m_map.stride_5(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return m_map.stride_6(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return m_map.stride_7(); }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION void stride( iType * const s ) const { m_map.stride(s); }
+
+  //----------------------------------------
+  // Range span is the span which contains all members.
+
+  typedef typename map_type::reference_type  reference_type ;
+  typedef typename map_type::pointer_type    pointer_type ;
+
+  enum { reference_type_is_lvalue_reference = std::is_lvalue_reference< reference_type >::value };
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return m_map.span(); }
+  // Deprecated, use 'span()' instead
+  KOKKOS_INLINE_FUNCTION constexpr size_t capacity() const { return m_map.span(); }
+  KOKKOS_INLINE_FUNCTION constexpr bool   span_is_contiguous() const { return m_map.span_is_contiguous(); }
+  KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const { return m_map.data(); }
+
+  // Deprecated, use 'span_is_contigous()' instead
+  KOKKOS_INLINE_FUNCTION constexpr bool   is_contiguous() const { return m_map.span_is_contiguous(); }
+  // Deprecated, use 'data()' instead
+  KOKKOS_INLINE_FUNCTION constexpr pointer_type ptr_on_device() const { return m_map.data(); }
+
+  //----------------------------------------
+  // Allow specializations to query their specialized map
+
+  KOKKOS_INLINE_FUNCTION
+  const Kokkos::Experimental::Impl::ViewMapping< traits , void > &
+  implementation_map() const { return m_map ; }
+
+  //----------------------------------------
+
+private:
+
+  enum {
+    is_layout_left = std::is_same< typename traits::array_layout
+                                  , Kokkos::LayoutLeft >::value ,
+
+    is_layout_right = std::is_same< typename traits::array_layout
+                                  , Kokkos::LayoutRight >::value ,
+
+    is_layout_stride = std::is_same< typename traits::array_layout
+                                   , Kokkos::LayoutStride >::value ,
+
+    is_default_map =
+      std::is_same< typename traits::specialize , void >::value &&
+      ( is_layout_left || is_layout_right || is_layout_stride )
+  };
+
+// Bounds checking macros
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+
+#define KOKKOS_VIEW_OPERATOR_VERIFY( N , ARG ) \
+  Kokkos::Impl::VerifyExecutionCanAccessMemorySpace \
+    < Kokkos::Impl::ActiveExecutionMemorySpace , typename traits::memory_space >::verify(); \
+  Kokkos::Experimental::Impl::verify_dynrankview_rank ( N , *this ) ; \
+  Kokkos::Experimental::Impl::view_verify_operator_bounds ARG ; 
+
+#else
+
+#define KOKKOS_VIEW_OPERATOR_VERIFY( N , ARG ) \
+  Kokkos::Impl::VerifyExecutionCanAccessMemorySpace \
+    < Kokkos::Impl::ActiveExecutionMemorySpace , typename traits::memory_space >::verify();
+
+#endif
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr unsigned rank() const { return m_rank; }
+
+
+  //operators ()
+  // Rank 0
+  KOKKOS_INLINE_FUNCTION
+  reference_type operator()() const
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 0 , ( implementation_map() ) )
+      return implementation_map().reference();
+      //return m_map.reference(0,0,0,0,0,0,0); 
+    }
+
+  // Rank 1
+  // This assumes a contiguous underlying memory (i.e. no padding, no striding...)
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< std::is_same<typename drvtraits::value_type, typename drvtraits::scalar_array_type>::value && std::is_integral<iType>::value, reference_type>::type
+  operator[](const iType & i0) const
+    {
+      return data()[i0];
+    }
+
+  // This assumes a contiguous underlying memory (i.e. no padding, no striding...
+  // AND a Trilinos/Sacado scalar type )
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< !std::is_same<typename drvtraits::value_type, typename drvtraits::scalar_array_type>::value && std::is_integral<iType>::value, reference_type>::type
+  operator[](const iType & i0) const
+    {
+//      auto map = implementation_map();
+      const size_t dim_scalar = m_map.dimension_scalar();
+      const size_t bytes = this->span() / dim_scalar;
+
+      typedef Kokkos::View<DataType*, typename traits::array_layout, typename traits::device_type, Kokkos::MemoryTraits<Kokkos::Unmanaged | traits::memory_traits::RandomAccess | traits::memory_traits::Atomic> > tmp_view_type;
+      tmp_view_type rankone_view(this->data(), bytes, dim_scalar);
+      return rankone_view(i0);
+    }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< (std::is_same<typename traits::specialize , void>::value && std::is_integral<iType>::value), reference_type>::type
+  operator()(const iType & i0 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 1 , ( m_map , i0 ) )
+      return m_map.reference(i0); 
+    }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< !(std::is_same<typename traits::specialize , void>::value && std::is_integral<iType>::value), reference_type>::type
+  operator()(const iType & i0 ) const
+    {
+      return m_map.reference(i0,0,0,0,0,0,0);
+    }
+
+  // Rank 2
+  template< typename iType0 , typename iType1 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< (std::is_same<typename traits::specialize , void>::value && std::is_integral<iType0>::value  && std::is_integral<iType1>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 2 , ( m_map , i0 , i1 ) )
+      return m_map.reference(i0,i1); 
+    }
+
+  template< typename iType0 , typename iType1 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< !(std::is_same<typename drvtraits::specialize , void>::value && std::is_integral<iType0>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 2 , ( m_map , i0 , i1 ) )
+      return m_map.reference(i0,i1,0,0,0,0,0); 
+    }
+
+  // Rank 3
+  template< typename iType0 , typename iType1 , typename iType2 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< (std::is_same<typename traits::specialize , void>::value && std::is_integral<iType0>::value  && std::is_integral<iType1>::value && std::is_integral<iType2>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 3 , ( m_map , i0 , i1 , i2 ) )
+      return m_map.reference(i0,i1,i2); 
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< !(std::is_same<typename drvtraits::specialize , void>::value && std::is_integral<iType0>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 3 , ( m_map , i0 , i1 , i2 ) )
+      return m_map.reference(i0,i1,i2,0,0,0,0); 
+    }
+
+  // Rank 4
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< (std::is_same<typename traits::specialize , void>::value && std::is_integral<iType0>::value  && std::is_integral<iType1>::value && std::is_integral<iType2>::value && std::is_integral<iType3>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 4 , ( m_map , i0 , i1 , i2 , i3 ) )
+      return m_map.reference(i0,i1,i2,i3); 
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< !(std::is_same<typename drvtraits::specialize , void>::value && std::is_integral<iType0>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 4 , ( m_map , i0 , i1 , i2 , i3 ) )
+      return m_map.reference(i0,i1,i2,i3,0,0,0); 
+    }
+
+  // Rank 5
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3, typename iType4 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< (std::is_same<typename traits::specialize , void>::value && std::is_integral<iType0>::value  && std::is_integral<iType1>::value && std::is_integral<iType2>::value && std::is_integral<iType3>::value && std::is_integral<iType4>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 , const iType4 & i4 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 5 , ( m_map , i0 , i1 , i2 , i3 , i4 ) )
+      return m_map.reference(i0,i1,i2,i3,i4); 
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3, typename iType4 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< !(std::is_same<typename drvtraits::specialize , void>::value && std::is_integral<iType0>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 , const iType4 & i4 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 5 , ( m_map , i0 , i1 , i2 , i3 , i4 ) )
+      return m_map.reference(i0,i1,i2,i3,i4,0,0); 
+    }
+
+  // Rank 6
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3, typename iType4 , typename iType5 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< (std::is_same<typename traits::specialize , void>::value && std::is_integral<iType0>::value  && std::is_integral<iType1>::value && std::is_integral<iType2>::value && std::is_integral<iType3>::value && std::is_integral<iType4>::value && std::is_integral<iType5>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 , const iType4 & i4 , const iType5 & i5 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 6 , ( m_map , i0 , i1 , i2 , i3 , i4 , i5 ) )
+      return m_map.reference(i0,i1,i2,i3,i4,i5); 
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3, typename iType4 , typename iType5 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< !(std::is_same<typename drvtraits::specialize , void>::value && std::is_integral<iType0>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 , const iType4 & i4 , const iType5 & i5 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 6 , ( m_map , i0 , i1 , i2 , i3 , i4 , i5 ) )
+      return m_map.reference(i0,i1,i2,i3,i4,i5,0); 
+    }
+
+  // Rank 7
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3, typename iType4 , typename iType5 , typename iType6 >
+  KOKKOS_INLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<iType0>::value  && std::is_integral<iType1>::value && std::is_integral<iType2>::value && std::is_integral<iType3>::value && std::is_integral<iType4>::value && std::is_integral<iType5>::value && std::is_integral<iType6>::value), reference_type>::type
+  operator()(const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 , const iType4 & i4 , const iType5 & i5 , const iType6 & i6 ) const 
+    { 
+      KOKKOS_VIEW_OPERATOR_VERIFY( 7 , ( m_map , i0 , i1 , i2 , i3 , i4 , i5 , i6 ) )
+      return m_map.reference(i0,i1,i2,i3,i4,i5,i6); 
+    }
+
+#undef KOKKOS_VIEW_OPERATOR_VERIFY
+
+  //----------------------------------------
+  // Standard constructor, destructor, and assignment operators... 
+
+  KOKKOS_INLINE_FUNCTION
+  ~DynRankView() {}
+
+  KOKKOS_INLINE_FUNCTION
+  DynRankView() : m_track(), m_map(), m_rank() {} //Default ctor
+
+  KOKKOS_INLINE_FUNCTION
+  DynRankView( const DynRankView & rhs ) : m_track( rhs.m_track ), m_map( rhs.m_map ), m_rank(rhs.m_rank) {}
+
+  KOKKOS_INLINE_FUNCTION
+  DynRankView( DynRankView && rhs ) : m_track( rhs.m_track ), m_map( rhs.m_map ), m_rank(rhs.m_rank) {}
+
+  KOKKOS_INLINE_FUNCTION
+  DynRankView & operator = ( const DynRankView & rhs ) { m_track = rhs.m_track; m_map = rhs.m_map; m_rank = rhs.m_rank; return *this; }
+
+  KOKKOS_INLINE_FUNCTION
+  DynRankView & operator = ( DynRankView && rhs ) { m_track = rhs.m_track; m_map = rhs.m_map; m_rank = rhs.m_rank; return *this; } 
+
+  //----------------------------------------
+  // Compatible view copy constructor and assignment
+  // may assign unmanaged from managed.
+  template< class RT , class ... RP >
+  KOKKOS_INLINE_FUNCTION
+  DynRankView( const DynRankView<RT,RP...> & rhs )
+    : m_track( rhs.m_track , traits::is_managed )
+    , m_map()
+    , m_rank(rhs.m_rank)
+    {
+      typedef typename DynRankView<RT,RP...> ::traits SrcTraits ;
+      typedef Kokkos::Experimental::Impl::ViewMapping< traits , SrcTraits , void > Mapping ;
+      static_assert( Mapping::is_assignable , "Incompatible DynRankView copy construction" );
+      Mapping::assign( m_map , rhs.m_map , rhs.m_track );
+    }
+
+  template< class RT , class ... RP >
+  KOKKOS_INLINE_FUNCTION
+  DynRankView & operator = (const DynRankView<RT,RP...> & rhs )
+    {
+      typedef typename DynRankView<RT,RP...> ::traits SrcTraits ;
+      typedef Kokkos::Experimental::Impl::ViewMapping< traits , SrcTraits , void > Mapping ;
+      static_assert( Mapping::is_assignable , "Incompatible DynRankView copy construction" );
+      Mapping::assign( m_map , rhs.m_map , rhs.m_track );
+      m_track.assign( rhs.m_track , traits::is_managed );
+      m_rank = rhs.rank();
+      return *this;
+    }
+
+// Experimental
+// Copy/Assign View to DynRankView
+  template< class RT , class ... RP >
+  KOKKOS_INLINE_FUNCTION
+  DynRankView( const View<RT,RP...> & rhs )
+    : m_track()
+    , m_map()
+    , m_rank( rhs.Rank )
+    {
+      typedef typename View<RT,RP...>::traits  SrcTraits ;
+      typedef Kokkos::Experimental::Impl::ViewMapping< traits , SrcTraits , Kokkos::Experimental::Impl::ViewToDynRankViewTag >  Mapping ;
+      static_assert( Mapping::is_assignable , "Incompatible DynRankView copy construction" );
+      Mapping::assign( *this , rhs );
+    }
+
+  template< class RT , class ... RP >
+  KOKKOS_INLINE_FUNCTION
+  DynRankView & operator = ( const View<RT,RP...> & rhs )
+    {
+      typedef typename View<RT,RP...>::traits  SrcTraits ;
+      typedef Kokkos::Experimental::Impl::ViewMapping< traits , SrcTraits , Kokkos::Experimental::Impl::ViewToDynRankViewTag >  Mapping ;
+      static_assert( Mapping::is_assignable , "Incompatible View to DynRankView copy assignment" );
+      Mapping::assign( *this , rhs );
+      return *this ;
+    }
+
+  //----------------------------------------
+  // Allocation tracking properties
+
+  KOKKOS_INLINE_FUNCTION
+  int use_count() const
+    { return m_track.use_count(); }
+
+  inline
+  const std::string label() const
+    { return m_track.template get_label< typename traits::memory_space >(); }
+
+  //----------------------------------------
+  // Allocation according to allocation properties and array layout
+  // unused arg_layout dimensions must be set to ~size_t(0) so that rank deduction can properly take place
+  template< class ... P >
+  explicit inline
+  DynRankView( const Impl::ViewCtorProp< P ... > & arg_prop
+      , typename std::enable_if< ! Impl::ViewCtorProp< P... >::has_pointer
+                               , typename traits::array_layout
+                               >::type const & arg_layout
+      )
+      : m_track()
+      , m_map()
+      , m_rank( Impl::DynRankDimTraits<typename traits::specialize>::computeRank(arg_layout) )
+    {
+      // Append layout and spaces if not input
+      typedef Impl::ViewCtorProp< P ... > alloc_prop_input ;
+
+      // use 'std::integral_constant<unsigned,I>' for non-types
+      // to avoid duplicate class error.
+      typedef Impl::ViewCtorProp
+        < P ...
+        , typename std::conditional
+            < alloc_prop_input::has_label
+            , std::integral_constant<unsigned,0>
+            , typename std::string
+            >::type
+        , typename std::conditional
+            < alloc_prop_input::has_memory_space
+            , std::integral_constant<unsigned,1>
+            , typename traits::device_type::memory_space
+            >::type
+        , typename std::conditional
+            < alloc_prop_input::has_execution_space
+            , std::integral_constant<unsigned,2>
+            , typename traits::device_type::execution_space
+            >::type
+        > alloc_prop ;
+
+      static_assert( traits::is_managed
+                   , "View allocation constructor requires managed memory" );
+
+      if ( alloc_prop::initialize &&
+           ! alloc_prop::execution_space::is_initialized() ) {
+        // If initializing view data then
+        // the execution space must be initialized.
+        Kokkos::Impl::throw_runtime_exception("Constructing DynRankView and initializing data with uninitialized execution space");
+      }
+
+      // Copy the input allocation properties with possibly defaulted properties
+      alloc_prop prop( arg_prop );
+
+//------------------------------------------------------------
+#if defined( KOKKOS_HAVE_CUDA )
+      // If allocating in CudaUVMSpace must fence before and after
+      // the allocation to protect against possible concurrent access
+      // on the CPU and the GPU.
+      // Fence using the trait's executon space (which will be Kokkos::Cuda)
+      // to avoid incomplete type errors from usng Kokkos::Cuda directly.
+      if ( std::is_same< Kokkos::CudaUVMSpace , typename traits::device_type::memory_space >::value ) {
+        traits::device_type::memory_space::execution_space::fence();
+      }
+#endif
+//------------------------------------------------------------
+
+      Kokkos::Experimental::Impl::SharedAllocationRecord<> *
+        record = m_map.allocate_shared( prop , Impl::DynRankDimTraits<typename traits::specialize>::createLayout(arg_layout) );
+
+//------------------------------------------------------------
+#if defined( KOKKOS_HAVE_CUDA )
+      if ( std::is_same< Kokkos::CudaUVMSpace , typename traits::device_type::memory_space >::value ) {
+        traits::device_type::memory_space::execution_space::fence();
+      }
+#endif
+//------------------------------------------------------------
+
+      // Setup and initialization complete, start tracking
+      m_track.assign_allocated_record_to_uninitialized( record );
+    }
+
+
+  // Wrappers
+  template< class ... P >
+  explicit KOKKOS_INLINE_FUNCTION
+  DynRankView( const Impl::ViewCtorProp< P ... > & arg_prop
+      , typename std::enable_if< Impl::ViewCtorProp< P... >::has_pointer
+                               , typename traits::array_layout
+                               >::type const & arg_layout
+      )
+      : m_track() // No memory tracking
+      , m_map( arg_prop , Impl::DynRankDimTraits<typename traits::specialize>::createLayout(arg_layout) )
+      , m_rank( Impl::DynRankDimTraits<typename traits::specialize>::computeRank(arg_layout) )
+    {
+      static_assert(
+        std::is_same< pointer_type
+                    , typename Impl::ViewCtorProp< P... >::pointer_type
+                    >::value ,
+        "Constructing DynRankView to wrap user memory must supply matching pointer type" );
+    }
+
+  //----------------------------------------
+  //Constructor(s)
+
+  // Simple dimension-only layout
+  template< class ... P >
+  explicit inline
+  DynRankView( const Impl::ViewCtorProp< P ... > & arg_prop
+      , typename std::enable_if< ! Impl::ViewCtorProp< P... >::has_pointer
+                               , size_t
+                               >::type const arg_N0 = ~size_t(0)
+      , const size_t arg_N1 = ~size_t(0)
+      , const size_t arg_N2 = ~size_t(0)
+      , const size_t arg_N3 = ~size_t(0)
+      , const size_t arg_N4 = ~size_t(0)
+      , const size_t arg_N5 = ~size_t(0)
+      , const size_t arg_N6 = ~size_t(0)
+      , const size_t arg_N7 = ~size_t(0)
+      )
+    : DynRankView( arg_prop
+    , typename traits::array_layout
+          ( arg_N0 , arg_N1 , arg_N2 , arg_N3 , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+      )
+    {}
+
+  template< class ... P >
+  explicit KOKKOS_INLINE_FUNCTION
+  DynRankView( const Impl::ViewCtorProp< P ... > & arg_prop
+      , typename std::enable_if< Impl::ViewCtorProp< P... >::has_pointer
+                               , size_t
+                               >::type const arg_N0 = ~size_t(0)
+      , const size_t arg_N1 = ~size_t(0)
+      , const size_t arg_N2 = ~size_t(0)
+      , const size_t arg_N3 = ~size_t(0)
+      , const size_t arg_N4 = ~size_t(0)
+      , const size_t arg_N5 = ~size_t(0)
+      , const size_t arg_N6 = ~size_t(0)
+      , const size_t arg_N7 = ~size_t(0)
+      )
+    : DynRankView( arg_prop
+    , typename traits::array_layout
+          ( arg_N0 , arg_N1 , arg_N2 , arg_N3 , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+      )
+    {}
+
+  // Allocate with label and layout
+  template< typename Label >
+  explicit inline
+  DynRankView( const Label & arg_label
+      , typename std::enable_if<
+          Kokkos::Experimental::Impl::is_view_label<Label>::value ,
+          typename traits::array_layout >::type const & arg_layout
+      )
+    : DynRankView( Impl::ViewCtorProp< std::string >( arg_label ) , arg_layout )
+    {}
+
+  // Allocate label and layout, must disambiguate from subview constructor
+  template< typename Label >
+  explicit inline
+  DynRankView( const Label & arg_label
+      , typename std::enable_if<
+          Kokkos::Experimental::Impl::is_view_label<Label>::value ,
+        const size_t >::type arg_N0 = ~size_t(0) 
+      , const size_t arg_N1 = ~size_t(0)
+      , const size_t arg_N2 = ~size_t(0)
+      , const size_t arg_N3 = ~size_t(0)
+      , const size_t arg_N4 = ~size_t(0)
+      , const size_t arg_N5 = ~size_t(0)
+      , const size_t arg_N6 = ~size_t(0)
+      , const size_t arg_N7 = ~size_t(0)
+      )
+    : DynRankView( Impl::ViewCtorProp< std::string >( arg_label )
+    , typename traits::array_layout
+          ( arg_N0 , arg_N1 , arg_N2 , arg_N3 , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+          )
+    {}
+
+  // For backward compatibility
+  explicit inline
+  DynRankView( const ViewAllocateWithoutInitializing & arg_prop
+      , const typename traits::array_layout & arg_layout
+      )
+    : DynRankView( Impl::ViewCtorProp< std::string , Kokkos::Experimental::Impl::WithoutInitializing_t >( arg_prop.label , Kokkos::Experimental::WithoutInitializing )
+          , Impl::DynRankDimTraits<typename traits::specialize>::createLayout(arg_layout)
+      )
+    {}
+
+  explicit inline
+  DynRankView( const ViewAllocateWithoutInitializing & arg_prop
+      , const size_t arg_N0 = ~size_t(0)
+      , const size_t arg_N1 = ~size_t(0)
+      , const size_t arg_N2 = ~size_t(0)
+      , const size_t arg_N3 = ~size_t(0)
+      , const size_t arg_N4 = ~size_t(0)
+      , const size_t arg_N5 = ~size_t(0)
+      , const size_t arg_N6 = ~size_t(0)
+      , const size_t arg_N7 = ~size_t(0)
+      )
+    : DynRankView(Impl::ViewCtorProp< std::string , Kokkos::Experimental::Impl::WithoutInitializing_t >( arg_prop.label , Kokkos::Experimental::WithoutInitializing ), arg_N0, arg_N1, arg_N2, arg_N3, arg_N4, arg_N5, arg_N6, arg_N7 ) 
+    {}
+
+  //----------------------------------------
+  // Memory span required to wrap these dimensions.
+  static constexpr size_t required_allocation_size(
+                                       const size_t arg_N0 = 0
+                                     , const size_t arg_N1 = 0
+                                     , const size_t arg_N2 = 0
+                                     , const size_t arg_N3 = 0
+                                     , const size_t arg_N4 = 0
+                                     , const size_t arg_N5 = 0
+                                     , const size_t arg_N6 = 0
+                                     , const size_t arg_N7 = 0
+                                     )
+    {
+      return map_type::memory_span(
+        typename traits::array_layout
+          ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+          , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) );
+    }
+
+  explicit KOKKOS_INLINE_FUNCTION
+  DynRankView( pointer_type arg_ptr
+      , const size_t arg_N0 = ~size_t(0)
+      , const size_t arg_N1 = ~size_t(0)
+      , const size_t arg_N2 = ~size_t(0)
+      , const size_t arg_N3 = ~size_t(0)
+      , const size_t arg_N4 = ~size_t(0)
+      , const size_t arg_N5 = ~size_t(0)
+      , const size_t arg_N6 = ~size_t(0)
+      , const size_t arg_N7 = ~size_t(0)
+      )
+    : DynRankView( Impl::ViewCtorProp<pointer_type>(arg_ptr) , arg_N0, arg_N1, arg_N2, arg_N3, arg_N4, arg_N5, arg_N6, arg_N7 )
+    {}
+
+  explicit KOKKOS_INLINE_FUNCTION
+  DynRankView( pointer_type arg_ptr
+      , typename traits::array_layout & arg_layout
+      )
+    : DynRankView( Impl::ViewCtorProp<pointer_type>(arg_ptr) , arg_layout )
+    {}
+
+
+  //----------------------------------------
+  // Shared scratch memory constructor
+
+  static inline
+  size_t shmem_size( const size_t arg_N0 = ~size_t(0) ,
+                     const size_t arg_N1 = ~size_t(0) ,
+                     const size_t arg_N2 = ~size_t(0) ,
+                     const size_t arg_N3 = ~size_t(0) ,
+                     const size_t arg_N4 = ~size_t(0) ,
+                     const size_t arg_N5 = ~size_t(0) ,
+                     const size_t arg_N6 = ~size_t(0) ,
+                     const size_t arg_N7 = ~size_t(0) )
+  {
+    const size_t num_passed_args =
+      ( arg_N0 != ~size_t(0) ) + ( arg_N1 != ~size_t(0) ) + ( arg_N2 != ~size_t(0) ) +
+      ( arg_N3 != ~size_t(0) ) + ( arg_N4 != ~size_t(0) ) + ( arg_N5 != ~size_t(0) ) +
+      ( arg_N6 != ~size_t(0) ) + ( arg_N7 != ~size_t(0) );
+
+    if ( std::is_same<typename traits::specialize , void>::value && num_passed_args != traits::rank_dynamic ) {
+      Kokkos::abort( "Kokkos::View::shmem_size() rank_dynamic != number of arguments.\n" );
+    }
+    {}
+
+    return map_type::memory_span(
+           typename traits::array_layout
+            ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+            , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) );
+  }
+
+  explicit KOKKOS_INLINE_FUNCTION
+  DynRankView( const typename traits::execution_space::scratch_memory_space & arg_space
+      , const typename traits::array_layout & arg_layout )
+    : DynRankView( Impl::ViewCtorProp<pointer_type>(
+              reinterpret_cast<pointer_type>(
+                arg_space.get_shmem( map_type::memory_span( 
+                  Impl::DynRankDimTraits<typename traits::specialize>::createLayout( arg_layout ) //is this correct?
+                ) ) ) )
+         , arg_layout )
+     {}
+
+  explicit KOKKOS_INLINE_FUNCTION
+  DynRankView( const typename traits::execution_space::scratch_memory_space & arg_space
+      , const size_t arg_N0 = ~size_t(0)
+      , const size_t arg_N1 = ~size_t(0)
+      , const size_t arg_N2 = ~size_t(0)
+      , const size_t arg_N3 = ~size_t(0)
+      , const size_t arg_N4 = ~size_t(0)
+      , const size_t arg_N5 = ~size_t(0)
+      , const size_t arg_N6 = ~size_t(0)
+      , const size_t arg_N7 = ~size_t(0) )
+
+    : DynRankView( Impl::ViewCtorProp<pointer_type>(
+                   reinterpret_cast<pointer_type>(
+                     arg_space.get_shmem(
+                       map_type::memory_span(
+                       Impl::DynRankDimTraits<typename traits::specialize>::createLayout(
+                       typename traits::array_layout
+                       ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+                       , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) ) ) ) ) 
+                    )
+                  , typename traits::array_layout
+                    ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+                    , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+        )
+    {}
+
+};
+
+
+  template < typename D , class ... P >
+  KOKKOS_INLINE_FUNCTION
+  constexpr unsigned rank( const DynRankView<D , P...> & DRV ) { return DRV.rank(); } //needed for transition to common constexpr method in view and dynrankview to return rank
+
+//----------------------------------------------------------------------------
+// Subview mapping.
+// Deduce destination view type from source view traits and subview arguments
+
+namespace Impl {
+
+struct DynRankSubviewTag {};
+
+template< class SrcTraits , class ... Args >
+struct ViewMapping
+  < typename std::enable_if<(
+      std::is_same< typename SrcTraits::specialize , void >::value
+      &&
+      (
+        std::is_same< typename SrcTraits::array_layout
+                    , Kokkos::LayoutLeft >::value ||
+        std::is_same< typename SrcTraits::array_layout
+                    , Kokkos::LayoutRight >::value ||
+        std::is_same< typename SrcTraits::array_layout
+                    , Kokkos::LayoutStride >::value
+      ) 
+    ), DynRankSubviewTag >::type
+  , SrcTraits
+  , Args ... >
+{
+private:
+
+  enum
+    { RZ = false
+    , R0 = bool(is_integral_extent<0,Args...>::value)
+    , R1 = bool(is_integral_extent<1,Args...>::value)
+    , R2 = bool(is_integral_extent<2,Args...>::value)
+    , R3 = bool(is_integral_extent<3,Args...>::value)
+    , R4 = bool(is_integral_extent<4,Args...>::value)
+    , R5 = bool(is_integral_extent<5,Args...>::value)
+    , R6 = bool(is_integral_extent<6,Args...>::value)
+    };
+
+  enum { rank = unsigned(R0) + unsigned(R1) + unsigned(R2) + unsigned(R3)
+              + unsigned(R4) + unsigned(R5) + unsigned(R6) };
+
+  typedef Kokkos::LayoutStride array_layout ;
+
+  typedef typename SrcTraits::value_type  value_type ;
+
+  typedef value_type******* data_type ; 
+
+public:
+
+  typedef Kokkos::Experimental::ViewTraits
+    < data_type
+    , array_layout 
+    , typename SrcTraits::device_type
+    , typename SrcTraits::memory_traits > traits_type ;
+
+  typedef Kokkos::Experimental::View
+    < data_type
+    , array_layout 
+    , typename SrcTraits::device_type
+    , typename SrcTraits::memory_traits > type ;
+
+
+  template< class MemoryTraits >
+  struct apply {
+
+    static_assert( Kokkos::Impl::is_memory_traits< MemoryTraits >::value , "" );
+
+    typedef Kokkos::Experimental::ViewTraits
+      < data_type 
+      , array_layout
+      , typename SrcTraits::device_type
+      , MemoryTraits > traits_type ;
+
+    typedef Kokkos::Experimental::View
+      < data_type 
+      , array_layout
+      , typename SrcTraits::device_type
+      , MemoryTraits > type ;
+  }; 
+
+
+  typedef typename SrcTraits::dimension dimension ;
+
+  template < class Arg0 = int, class Arg1 = int, class Arg2 = int, class Arg3 = int, class Arg4 = int, class Arg5 = int, class Arg6 = int >
+  struct ExtentGenerator {
+    KOKKOS_INLINE_FUNCTION
+    static SubviewExtents< 7 , rank > generator ( const dimension & dim , Arg0 arg0 = Arg0(), Arg1 arg1 = Arg1(), Arg2 arg2 = Arg2(), Arg3 arg3 = Arg3(), Arg4 arg4 = Arg4(), Arg5 arg5 = Arg5(), Arg6 arg6 = Arg6() )
+    {
+       return SubviewExtents< 7 , rank>( dim , arg0 , arg1 , arg2 , arg3 , arg4 , arg5 , arg6 );
+    }
+  };
+
+
+  typedef DynRankView< value_type , array_layout , typename SrcTraits::device_type , typename SrcTraits::memory_traits >  ret_type;
+
+  template < typename T , class ... P >
+  KOKKOS_INLINE_FUNCTION
+  static ret_type subview( const unsigned src_rank , Kokkos::Experimental::DynRankView< T , P...> const & src 
+                    , Args ... args )
+    {
+
+       typedef ViewMapping< traits_type, void >  DstType ;
+
+       typedef typename std::conditional< (rank==0) , ViewDimension<>
+                                                    , typename std::conditional< (rank==1) , ViewDimension<0>
+                                                    , typename std::conditional< (rank==2) , ViewDimension<0,0>
+                                                    , typename std::conditional< (rank==3) , ViewDimension<0,0,0>
+                                                    , typename std::conditional< (rank==4) , ViewDimension<0,0,0,0>
+                                                    , typename std::conditional< (rank==5) , ViewDimension<0,0,0,0,0>
+                                                    , typename std::conditional< (rank==6) , ViewDimension<0,0,0,0,0,0>
+                                                                                           , ViewDimension<0,0,0,0,0,0,0>
+                                                    >::type >::type >::type >::type >::type >::type >::type  DstDimType ;
+
+      typedef ViewOffset< DstDimType , Kokkos::LayoutStride > dst_offset_type ;
+      typedef typename DstType::handle_type  dst_handle_type ;
+
+      ret_type dst ;
+
+      const SubviewExtents< 7 , rank > extents = 
+        ExtentGenerator< Args ... >::generator( src.m_map.m_offset.m_dim , args... ) ; 
+
+      dst_offset_type tempdst( src.m_map.m_offset , extents ) ;
+
+      dst.m_track = src.m_track ;
+
+      dst.m_map.m_offset.m_dim.N0 = tempdst.m_dim.N0 ;
+      dst.m_map.m_offset.m_dim.N1 = tempdst.m_dim.N1 ;
+      dst.m_map.m_offset.m_dim.N2 = tempdst.m_dim.N2 ;
+      dst.m_map.m_offset.m_dim.N3 = tempdst.m_dim.N3 ;
+      dst.m_map.m_offset.m_dim.N4 = tempdst.m_dim.N4 ;
+      dst.m_map.m_offset.m_dim.N5 = tempdst.m_dim.N5 ;
+      dst.m_map.m_offset.m_dim.N6 = tempdst.m_dim.N6 ;
+
+      dst.m_map.m_offset.m_stride.S0 = tempdst.m_stride.S0 ;
+      dst.m_map.m_offset.m_stride.S1 = tempdst.m_stride.S1 ;
+      dst.m_map.m_offset.m_stride.S2 = tempdst.m_stride.S2 ;
+      dst.m_map.m_offset.m_stride.S3 = tempdst.m_stride.S3 ;
+      dst.m_map.m_offset.m_stride.S4 = tempdst.m_stride.S4 ;
+      dst.m_map.m_offset.m_stride.S5 = tempdst.m_stride.S5 ;
+      dst.m_map.m_offset.m_stride.S6 = tempdst.m_stride.S6 ;
+
+      dst.m_map.m_handle = dst_handle_type( src.m_map.m_handle +
+                                      src.m_map.m_offset( extents.domain_offset(0)
+                                                  , extents.domain_offset(1)
+                                                  , extents.domain_offset(2)
+                                                  , extents.domain_offset(3)
+                                                  , extents.domain_offset(4)
+                                                  , extents.domain_offset(5)
+                                                  , extents.domain_offset(6)
+                                                  ) );
+
+      dst.m_rank = ( src_rank > 0 ? unsigned(R0) : 0 )
+                 + ( src_rank > 1 ? unsigned(R1) : 0 )
+                 + ( src_rank > 2 ? unsigned(R2) : 0 )
+                 + ( src_rank > 3 ? unsigned(R3) : 0 )
+                 + ( src_rank > 4 ? unsigned(R4) : 0 )
+                 + ( src_rank > 5 ? unsigned(R5) : 0 )
+                 + ( src_rank > 6 ? unsigned(R6) : 0 ) ;
+
+      return dst ;
+    }
+};
+
+} // end Impl
+
+
+template< class V , class ... Args >
+using Subdynrankview = typename Kokkos::Experimental::Impl::ViewMapping< Kokkos::Experimental::Impl::DynRankSubviewTag , V , Args... >::ret_type ;
+
+template< class D , class ... P , class ...Args >
+KOKKOS_INLINE_FUNCTION
+Subdynrankview< ViewTraits<D******* , P...> , Args... > 
+subdynrankview( const Kokkos::Experimental::DynRankView< D , P... > &src , Args...args)
+  {
+    if ( src.rank() > sizeof...(Args) ) //allow sizeof...(Args) >= src.rank(), ignore the remaining args
+      { Kokkos::abort("subdynrankview: num of args must be >= rank of the source DynRankView"); }
+  
+    typedef Kokkos::Experimental::Impl::ViewMapping< Kokkos::Experimental::Impl::DynRankSubviewTag , Kokkos::Experimental::ViewTraits< D*******, P... > , Args... > metafcn ;
+
+    return metafcn::subview( src.rank() , src , args... );
+  }
+
+//Wrapper to allow subview function name
+template< class D , class ... P , class ...Args >
+KOKKOS_INLINE_FUNCTION
+Subdynrankview< ViewTraits<D******* , P...> , Args... > 
+subview( const Kokkos::Experimental::DynRankView< D , P... > &src , Args...args)
+  {
+    return subdynrankview( src , args... );
+  }
+
+} // namespace Experimental
+} // namespace Kokkos
+
+namespace Kokkos {
+namespace Experimental {
+
+// overload == and !=
+template< class LT , class ... LP , class RT , class ... RP >
+KOKKOS_INLINE_FUNCTION
+bool operator == ( const DynRankView<LT,LP...> & lhs ,
+                   const DynRankView<RT,RP...> & rhs )
+{
+  // Same data, layout, dimensions
+  typedef ViewTraits<LT,LP...>  lhs_traits ;
+  typedef ViewTraits<RT,RP...>  rhs_traits ;
+
+  return
+    std::is_same< typename lhs_traits::const_value_type ,
+                  typename rhs_traits::const_value_type >::value &&
+    std::is_same< typename lhs_traits::array_layout ,
+                  typename rhs_traits::array_layout >::value &&
+    std::is_same< typename lhs_traits::memory_space ,
+                  typename rhs_traits::memory_space >::value &&
+    lhs.rank()       ==  rhs.rank() &&
+    lhs.data()       == rhs.data() &&
+    lhs.span()       == rhs.span() &&
+    lhs.dimension(0) == rhs.dimension(0) &&
+    lhs.dimension(1) == rhs.dimension(1) &&
+    lhs.dimension(2) == rhs.dimension(2) &&
+    lhs.dimension(3) == rhs.dimension(3) &&
+    lhs.dimension(4) == rhs.dimension(4) &&
+    lhs.dimension(5) == rhs.dimension(5) &&
+    lhs.dimension(6) == rhs.dimension(6) &&
+    lhs.dimension(7) == rhs.dimension(7);
+}
+
+template< class LT , class ... LP , class RT , class ... RP >
+KOKKOS_INLINE_FUNCTION
+bool operator != ( const DynRankView<LT,LP...> & lhs ,
+                   const DynRankView<RT,RP...> & rhs )
+{
+  return ! ( operator==(lhs,rhs) );
+}
+
+} //end Experimental
+} //end Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template< class OutputView , typename Enable = void >
+struct DynRankViewFill {
+
+  typedef typename OutputView::traits::const_value_type  const_value_type ;
+
+  const OutputView output ;
+  const_value_type input ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_t i0 ) const
+  {
+    const size_t n1 = output.dimension_1();
+    const size_t n2 = output.dimension_2();
+    const size_t n3 = output.dimension_3();
+    const size_t n4 = output.dimension_4();
+    const size_t n5 = output.dimension_5();
+    const size_t n6 = output.dimension_6();
+
+    for ( size_t i1 = 0 ; i1 < n1 ; ++i1 ) {
+    for ( size_t i2 = 0 ; i2 < n2 ; ++i2 ) {
+    for ( size_t i3 = 0 ; i3 < n3 ; ++i3 ) {
+    for ( size_t i4 = 0 ; i4 < n4 ; ++i4 ) {
+    for ( size_t i5 = 0 ; i5 < n5 ; ++i5 ) {
+    for ( size_t i6 = 0 ; i6 < n6 ; ++i6 ) {
+      output(i0,i1,i2,i3,i4,i5,i6) = input ;
+    }}}}}}
+  }
+
+  DynRankViewFill( const OutputView & arg_out , const_value_type & arg_in )
+    : output( arg_out ), input( arg_in )
+    {
+      typedef typename OutputView::execution_space  execution_space ;
+      typedef Kokkos::RangePolicy< execution_space > Policy ;
+
+      const Kokkos::Impl::ParallelFor< DynRankViewFill , Policy > closure( *this , Policy( 0 , output.dimension_0() ) );
+
+      closure.execute();
+
+      execution_space::fence();
+    }
+};
+
+template< class OutputView >
+struct DynRankViewFill< OutputView , typename std::enable_if< OutputView::Rank == 0 >::type > { 
+  DynRankViewFill( const OutputView & dst , const typename OutputView::const_value_type & src )
+    {
+      Kokkos::Impl::DeepCopy< typename OutputView::memory_space , Kokkos::HostSpace >
+        ( dst.data() , & src , sizeof(typename OutputView::const_value_type) );
+    }
+};
+
+template< class OutputView , class InputView , class ExecSpace = typename OutputView::execution_space >
+struct DynRankViewRemap {
+
+  const OutputView output ;
+  const InputView  input ;
+  const size_t n0 ;
+  const size_t n1 ;
+  const size_t n2 ;
+  const size_t n3 ;
+  const size_t n4 ;
+  const size_t n5 ;
+  const size_t n6 ;
+  const size_t n7 ;
+
+  DynRankViewRemap( const OutputView & arg_out , const InputView & arg_in )
+    : output( arg_out ), input( arg_in )
+    , n0( std::min( (size_t)arg_out.dimension_0() , (size_t)arg_in.dimension_0() ) )
+    , n1( std::min( (size_t)arg_out.dimension_1() , (size_t)arg_in.dimension_1() ) )
+    , n2( std::min( (size_t)arg_out.dimension_2() , (size_t)arg_in.dimension_2() ) )
+    , n3( std::min( (size_t)arg_out.dimension_3() , (size_t)arg_in.dimension_3() ) )
+    , n4( std::min( (size_t)arg_out.dimension_4() , (size_t)arg_in.dimension_4() ) )
+    , n5( std::min( (size_t)arg_out.dimension_5() , (size_t)arg_in.dimension_5() ) )
+    , n6( std::min( (size_t)arg_out.dimension_6() , (size_t)arg_in.dimension_6() ) )
+    , n7( std::min( (size_t)arg_out.dimension_7() , (size_t)arg_in.dimension_7() ) )
+    {
+      typedef Kokkos::RangePolicy< ExecSpace > Policy ;
+      const Kokkos::Impl::ParallelFor< DynRankViewRemap , Policy > closure( *this , Policy( 0 , n0 ) );
+      closure.execute();
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_t i0 ) const
+  {
+    for ( size_t i1 = 0 ; i1 < n1 ; ++i1 ) {
+    for ( size_t i2 = 0 ; i2 < n2 ; ++i2 ) {
+    for ( size_t i3 = 0 ; i3 < n3 ; ++i3 ) {
+    for ( size_t i4 = 0 ; i4 < n4 ; ++i4 ) {
+    for ( size_t i5 = 0 ; i5 < n5 ; ++i5 ) {
+    for ( size_t i6 = 0 ; i6 < n6 ; ++i6 ) {
+      output(i0,i1,i2,i3,i4,i5,i6) = input(i0,i1,i2,i3,i4,i5,i6);
+    }}}}}}
+  }
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+
+namespace Kokkos {
+namespace Experimental {
+
+/** \brief  Deep copy a value from Host memory into a view.  */
+template< class DT , class ... DP >
+inline
+void deep_copy
+  ( const DynRankView<DT,DP...> & dst
+  , typename ViewTraits<DT,DP...>::const_value_type & value
+  , typename std::enable_if<
+    std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value
+    >::type * = 0 )
+{
+  static_assert(
+    std::is_same< typename ViewTraits<DT,DP...>::non_const_value_type ,
+                  typename ViewTraits<DT,DP...>::value_type >::value
+    , "deep_copy requires non-const type" );
+
+  Kokkos::Experimental::Impl::DynRankViewFill< DynRankView<DT,DP...> >( dst , value );
+}
+
+/** \brief  Deep copy into a value in Host memory from a view.  */
+template< class ST , class ... SP >
+inline
+void deep_copy
+  ( typename ViewTraits<ST,SP...>::non_const_value_type & dst
+  , const DynRankView<ST,SP...> & src
+  , typename std::enable_if<
+    std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value
+    >::type * = 0 )
+{
+  if ( src.rank() != 0 )
+  {
+    Kokkos::abort("");
+  }
+
+  typedef ViewTraits<ST,SP...>               src_traits ;
+  typedef typename src_traits::memory_space  src_memory_space ;
+  Kokkos::Impl::DeepCopy< HostSpace , src_memory_space >( & dst , src.data() , sizeof(ST) );
+}
+
+//----------------------------------------------------------------------------
+/** \brief  A deep copy between views of the default specialization, compatible type,
+ *          same rank, same contiguous layout.
+ */
+template< class DstType , class SrcType >
+inline
+void deep_copy
+  ( const DstType & dst
+  , const SrcType & src
+  , typename std::enable_if<(
+    std::is_same< typename DstType::traits::specialize , void >::value &&
+    std::is_same< typename SrcType::traits::specialize , void >::value
+    &&
+    ( Kokkos::Experimental::is_dyn_rank_view<DstType>::value || Kokkos::Experimental::is_dyn_rank_view<SrcType>::value)
+  )>::type * = 0 )
+{
+  static_assert(
+    std::is_same< typename DstType::traits::value_type ,
+                  typename DstType::traits::non_const_value_type >::value
+    , "deep_copy requires non-const destination type" );
+
+  typedef DstType  dst_type ;
+  typedef SrcType  src_type ;
+
+  typedef typename dst_type::execution_space  dst_execution_space ;
+  typedef typename src_type::execution_space  src_execution_space ;
+  typedef typename dst_type::memory_space     dst_memory_space ;
+  typedef typename src_type::memory_space     src_memory_space ;
+
+  enum { DstExecCanAccessSrc =
+   Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename dst_execution_space::memory_space , src_memory_space >::value };
+
+  enum { SrcExecCanAccessDst =
+   Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename src_execution_space::memory_space , dst_memory_space >::value };
+
+  if ( (void *) dst.data() != (void*) src.data() ) {
+
+    // Concern: If overlapping views then a parallel copy will be erroneous.
+    // ...
+
+    // If same type, equal layout, equal dimensions, equal span, and contiguous memory then can byte-wise copy
+    if ( rank(src) == 0 && rank(dst) == 0 )
+    { 
+      typedef typename dst_type::value_type    value_type ;
+      Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , sizeof(value_type) ); 
+    }
+    else if ( std::is_same< typename DstType::traits::value_type ,
+                       typename SrcType::traits::non_const_value_type >::value &&
+         (
+           ( std::is_same< typename DstType::traits::array_layout ,
+                           typename SrcType::traits::array_layout >::value
+             &&
+             ( std::is_same< typename DstType::traits::array_layout ,
+                             typename Kokkos::LayoutLeft>::value
+             ||
+               std::is_same< typename DstType::traits::array_layout ,
+                             typename Kokkos::LayoutRight>::value
+             )
+           )
+           ||
+           (
+             rank(dst) == 1
+             &&
+             rank(src) == 1
+           )
+         ) &&
+         dst.span_is_contiguous() &&
+         src.span_is_contiguous() &&
+         dst.span() == src.span() &&
+         dst.dimension_0() == src.dimension_0() &&
+         dst.dimension_1() == src.dimension_1() &&
+         dst.dimension_2() == src.dimension_2() &&
+         dst.dimension_3() == src.dimension_3() &&
+         dst.dimension_4() == src.dimension_4() &&
+         dst.dimension_5() == src.dimension_5() &&
+         dst.dimension_6() == src.dimension_6() &&
+         dst.dimension_7() == src.dimension_7() ) {
+
+      const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
+
+      Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , nbytes );
+    }
+    else if ( std::is_same< typename DstType::traits::value_type ,
+                            typename SrcType::traits::non_const_value_type >::value &&
+         (
+           ( std::is_same< typename DstType::traits::array_layout ,
+                           typename SrcType::traits::array_layout >::value
+             &&
+             std::is_same< typename DstType::traits::array_layout ,
+                          typename Kokkos::LayoutStride>::value
+           )
+           ||
+           (
+             rank(dst) == 1
+             &&
+             rank(src) == 1
+           )
+         ) &&
+         dst.span_is_contiguous() &&
+         src.span_is_contiguous() &&
+         dst.span() == src.span() &&
+         dst.dimension_0() == src.dimension_0() &&
+         dst.dimension_1() == src.dimension_1() &&
+         dst.dimension_2() == src.dimension_2() &&
+         dst.dimension_3() == src.dimension_3() &&
+         dst.dimension_4() == src.dimension_4() &&
+         dst.dimension_5() == src.dimension_5() &&
+         dst.dimension_6() == src.dimension_6() &&
+         dst.dimension_7() == src.dimension_7() &&
+         dst.stride_0() == src.stride_0() &&
+         dst.stride_1() == src.stride_1() &&
+         dst.stride_2() == src.stride_2() &&
+         dst.stride_3() == src.stride_3() &&
+         dst.stride_4() == src.stride_4() &&
+         dst.stride_5() == src.stride_5() &&
+         dst.stride_6() == src.stride_6() &&
+         dst.stride_7() == src.stride_7()
+         ) {
+
+      const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
+
+      Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , nbytes );
+    }
+    else if ( DstExecCanAccessSrc ) {
+      // Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
+      Kokkos::Experimental::Impl::DynRankViewRemap< dst_type , src_type >( dst , src );
+    }
+    else if ( SrcExecCanAccessDst ) {
+      // Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
+      Kokkos::Experimental::Impl::DynRankViewRemap< dst_type , src_type , src_execution_space >( dst , src );
+    }
+    else {
+      Kokkos::Impl::throw_runtime_exception("deep_copy given views that would require a temporary allocation");
+    }
+  }
+}
+
+} //end Experimental
+} //end Kokkos
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+namespace Impl {
+
+
+// Deduce Mirror Types
+template<class Space, class T, class ... P>
+struct MirrorDRViewType {
+  // The incoming view_type
+  typedef typename Kokkos::Experimental::DynRankView<T,P...> src_view_type;
+  // The memory space for the mirror view
+  typedef typename Space::memory_space memory_space;
+  // Check whether it is the same memory space
+  enum { is_same_memspace = std::is_same<memory_space,typename src_view_type::memory_space>::value };
+  // The array_layout
+  typedef typename src_view_type::array_layout array_layout;
+  // The data type (we probably want it non-const since otherwise we can't even deep_copy to it.
+  typedef typename src_view_type::non_const_data_type data_type;
+  // The destination view type if it is not the same memory space
+  typedef Kokkos::Experimental::DynRankView<data_type,array_layout,Space> dest_view_type;
+  // If it is the same memory_space return the existsing view_type
+  // This will also keep the unmanaged trait if necessary
+  typedef typename std::conditional<is_same_memspace,src_view_type,dest_view_type>::type view_type;
+};
+
+template<class Space, class T, class ... P>
+struct MirrorDRVType {
+  // The incoming view_type
+  typedef typename Kokkos::Experimental::DynRankView<T,P...> src_view_type;
+  // The memory space for the mirror view
+  typedef typename Space::memory_space memory_space;
+  // Check whether it is the same memory space
+  enum { is_same_memspace = std::is_same<memory_space,typename src_view_type::memory_space>::value };
+  // The array_layout
+  typedef typename src_view_type::array_layout array_layout;
+  // The data type (we probably want it non-const since otherwise we can't even deep_copy to it.
+  typedef typename src_view_type::non_const_data_type data_type;
+  // The destination view type if it is not the same memory space
+  typedef Kokkos::Experimental::DynRankView<data_type,array_layout,Space> view_type;
+};
+
+}
+
+
+template< class T , class ... P >
+inline
+typename DynRankView<T,P...>::HostMirror
+create_mirror( const DynRankView<T,P...> & src
+             , typename std::enable_if<
+                 ! std::is_same< typename Kokkos::Experimental::ViewTraits<T,P...>::array_layout
+                               , Kokkos::LayoutStride >::value
+               >::type * = 0
+             )
+{
+  typedef DynRankView<T,P...>                   src_type ;
+  typedef typename src_type::HostMirror  dst_type ;
+
+  return dst_type( std::string( src.label() ).append("_mirror")
+                 , Impl::reconstructLayout(src.layout(), src.rank()) );
+}
+
+
+template< class T , class ... P >
+inline
+typename DynRankView<T,P...>::HostMirror
+create_mirror( const DynRankView<T,P...> & src
+             , typename std::enable_if<
+                 std::is_same< typename Kokkos::Experimental::ViewTraits<T,P...>::array_layout
+                             , Kokkos::LayoutStride >::value
+               >::type * = 0
+             )
+{
+  typedef DynRankView<T,P...>                   src_type ;
+  typedef typename src_type::HostMirror  dst_type ;
+
+  return dst_type( std::string( src.label() ).append("_mirror") 
+                 , Impl::reconstructLayout(src.layout(), src.rank()) );
+}
+
+
+// Create a mirror in a new space (specialization for different space)
+template<class Space, class T, class ... P>
+typename Impl::MirrorDRVType<Space,T,P ...>::view_type create_mirror(const Space& , const Kokkos::Experimental::DynRankView<T,P...> & src) {
+  return typename Impl::MirrorDRVType<Space,T,P ...>::view_type(src.label(), Impl::reconstructLayout(src.layout(), src.rank()) );
+}
+
+template< class T , class ... P >
+inline
+typename DynRankView<T,P...>::HostMirror
+create_mirror_view( const DynRankView<T,P...> & src
+                  , typename std::enable_if<(
+                      std::is_same< typename DynRankView<T,P...>::memory_space
+                                  , typename DynRankView<T,P...>::HostMirror::memory_space
+                                  >::value
+                      &&
+                      std::is_same< typename DynRankView<T,P...>::data_type
+                                  , typename DynRankView<T,P...>::HostMirror::data_type
+                                  >::value
+                    )>::type * = 0
+                  )
+{
+  return src ;
+}
+
+template< class T , class ... P >
+inline
+typename DynRankView<T,P...>::HostMirror
+create_mirror_view( const DynRankView<T,P...> & src
+                  , typename std::enable_if< ! (
+                      std::is_same< typename DynRankView<T,P...>::memory_space
+                                  , typename DynRankView<T,P...>::HostMirror::memory_space
+                                  >::value
+                      &&
+                      std::is_same< typename DynRankView<T,P...>::data_type
+                                  , typename DynRankView<T,P...>::HostMirror::data_type
+                                  >::value
+                    )>::type * = 0
+                  )
+{
+  return Kokkos::Experimental::create_mirror( src ); 
+}
+
+// Create a mirror view in a new space (specialization for same space)
+template<class Space, class T, class ... P>
+typename Impl::MirrorDRViewType<Space,T,P ...>::view_type
+create_mirror_view(const Space& , const Kokkos::Experimental::DynRankView<T,P...> & src
+  , typename std::enable_if<Impl::MirrorDRViewType<Space,T,P ...>::is_same_memspace>::type* = 0 ) {
+  return src;
+}
+
+// Create a mirror view in a new space (specialization for different space)
+template<class Space, class T, class ... P>
+typename Impl::MirrorDRViewType<Space,T,P ...>::view_type
+create_mirror_view(const Space& , const Kokkos::Experimental::DynRankView<T,P...> & src
+  , typename std::enable_if<!Impl::MirrorDRViewType<Space,T,P ...>::is_same_memspace>::type* = 0 ) {
+  return typename Impl::MirrorDRViewType<Space,T,P ...>::view_type(src.label(), Impl::reconstructLayout(src.layout(), src.rank()) );
+}
+
+} //end Experimental
+} //end Kokkos
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+/** \brief  Resize a view with copying old data to new data at the corresponding indices. */
+template< class T , class ... P >
+inline
+void resize( DynRankView<T,P...> & v ,
+             const size_t n0 = ~size_t(0) ,
+             const size_t n1 = ~size_t(0) ,
+             const size_t n2 = ~size_t(0) ,
+             const size_t n3 = ~size_t(0) ,
+             const size_t n4 = ~size_t(0) ,
+             const size_t n5 = ~size_t(0) ,
+             const size_t n6 = ~size_t(0) ,
+             const size_t n7 = ~size_t(0) )
+{
+  typedef DynRankView<T,P...>  drview_type ;
+
+  static_assert( Kokkos::Experimental::ViewTraits<T,P...>::is_managed , "Can only resize managed views" );
+
+  drview_type v_resized( v.label(), n0, n1, n2, n3, n4, n5, n6 );
+
+  Kokkos::Experimental::Impl::DynRankViewRemap< drview_type , drview_type >( v_resized, v );
+
+  v = v_resized ;
+}
+
+/** \brief  Resize a view with copying old data to new data at the corresponding indices. */
+template< class T , class ... P >
+inline
+void realloc( DynRankView<T,P...> & v ,
+              const size_t n0 = ~size_t(0) ,
+              const size_t n1 = ~size_t(0) ,
+              const size_t n2 = ~size_t(0) ,
+              const size_t n3 = ~size_t(0) ,
+              const size_t n4 = ~size_t(0) ,
+              const size_t n5 = ~size_t(0) ,
+              const size_t n6 = ~size_t(0) ,
+              const size_t n7 = ~size_t(0) )
+{
+  typedef DynRankView<T,P...>  drview_type ;
+
+  static_assert( Kokkos::Experimental::ViewTraits<T,P...>::is_managed , "Can only realloc managed views" );
+
+  const std::string label = v.label();
+
+  v = drview_type(); // Deallocate first, if the only view to allocation
+  v = drview_type( label, n0, n1, n2, n3, n4, n5, n6 );
+}
+
+} //end Experimental
+
+} //end Kokkos
+
+using Kokkos::Experimental::is_dyn_rank_view ;
+
+namespace Kokkos {
+
+template< typename D , class ... P >
+using DynRankView = Kokkos::Experimental::DynRankView< D , P... > ;
+
+using Kokkos::Experimental::deep_copy ;
+using Kokkos::Experimental::create_mirror ;
+using Kokkos::Experimental::create_mirror_view ;
+using Kokkos::Experimental::subdynrankview ;
+using Kokkos::Experimental::subview ;
+using Kokkos::Experimental::resize ;
+using Kokkos::Experimental::realloc ;
+
+} //end Kokkos
+#endif
diff --git a/lib/kokkos/containers/src/Kokkos_DynamicView.hpp b/lib/kokkos/containers/src/Kokkos_DynamicView.hpp
new file mode 100644
index 0000000000..fb364f0bf2
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_DynamicView.hpp
@@ -0,0 +1,494 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_DYNAMIC_VIEW_HPP
+#define KOKKOS_DYNAMIC_VIEW_HPP
+
+#include <cstdio>
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Error.hpp>
+
+namespace Kokkos {
+namespace Experimental {
+
+/** \brief Dynamic views are restricted to rank-one and no layout.
+ *         Subviews are not allowed.
+ */
+template< typename DataType , typename ... P >
+class DynamicView : public Kokkos::Experimental::ViewTraits< DataType , P ... >
+{ 
+public:
+
+  typedef ViewTraits< DataType , P ... >  traits ;
+
+private:
+
+  template< class , class ... > friend class DynamicView ;
+
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker   track_type ;
+
+  static_assert( traits::rank == 1 && traits::rank_dynamic == 1 
+               , "DynamicView must be rank-one" );
+
+  static_assert( std::is_trivial< typename traits::value_type >::value &&
+                 std::is_same< typename traits::specialize , void >::value
+               , "DynamicView must have trivial data type" );
+
+public:
+
+  typedef Kokkos::Experimental::MemoryPool< typename traits::device_type > memory_pool ;
+
+private:
+
+  memory_pool                    m_pool ;
+  track_type                     m_track ;
+  typename traits::value_type ** m_chunks ;
+  unsigned                       m_chunk_shift ;
+  unsigned                       m_chunk_mask ;
+  unsigned                       m_chunk_max ;
+
+public:
+
+  //----------------------------------------------------------------------
+
+  /** \brief  Compatible view of array of scalar types */
+  typedef DynamicView< typename traits::data_type ,
+                       typename traits::device_type >
+    array_type ;
+
+  /** \brief  Compatible view of const data type */
+  typedef DynamicView< typename traits::const_data_type ,
+                       typename traits::device_type >
+    const_type ;
+
+  /** \brief  Compatible view of non-const data type */
+  typedef DynamicView< typename traits::non_const_data_type ,
+                       typename traits::device_type >
+    non_const_type ;
+
+  /** \brief  Must be accessible everywhere */
+  typedef DynamicView  HostMirror ;
+
+  //----------------------------------------------------------------------
+
+  enum { Rank = 1 };
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t size() const
+    {
+      return
+        Kokkos::Impl::VerifyExecutionCanAccessMemorySpace
+          < Kokkos::Impl::ActiveExecutionMemorySpace
+          , typename traits::memory_space
+          >::value 
+        ? // Runtime size is at the end of the chunk pointer array
+          (*reinterpret_cast<const uintptr_t*>( m_chunks + m_chunk_max ))
+          << m_chunk_shift
+        : 0 ;
+    }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_t extent( const iType & r ) const
+    { return r == 0 ? size() : 1 ; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_t extent_int( const iType & r ) const
+    { return r == 0 ? size() : 1 ; }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_0() const { return size(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return 1 ; }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return 0 ; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION void stride( iType * const s ) const { *s = 0 ; }
+
+  //----------------------------------------------------------------------
+  // Range span is the span which contains all members.
+
+  typedef typename traits::value_type &  reference_type ;
+  typedef typename traits::value_type *  pointer_type ;
+
+  enum { reference_type_is_lvalue_reference = std::is_lvalue_reference< reference_type >::value };
+
+  KOKKOS_INLINE_FUNCTION constexpr bool   span_is_contiguous() const { return false ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const { return 0 ; }
+
+  //----------------------------------------
+
+  template< typename I0 , class ... Args >
+  KOKKOS_INLINE_FUNCTION
+  reference_type operator()( const I0 & i0 , const Args & ... args ) const
+    {
+      static_assert( Kokkos::Impl::are_integral<I0,Args...>::value
+                   , "Indices must be integral type" );
+
+      Kokkos::Impl::VerifyExecutionCanAccessMemorySpace
+        < Kokkos::Impl::ActiveExecutionMemorySpace
+        , typename traits::memory_space
+        >::verify();
+
+      // Which chunk is being indexed.
+      const uintptr_t ic = uintptr_t( i0 >> m_chunk_shift );
+
+      typename traits::value_type * volatile * const ch = m_chunks + ic ;
+
+      // Do bounds checking if enabled or if the chunk pointer is zero.
+      // If not bounds checking then we assume a non-zero pointer is valid.
+
+#if ! defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+      if ( 0 == *ch )
+#endif
+      {
+        // Verify that allocation of the requested chunk in in progress.
+
+        // The allocated chunk counter is m_chunks[ m_chunk_max ]
+        const uintptr_t n = 
+          *reinterpret_cast<uintptr_t volatile *>( m_chunks + m_chunk_max );
+
+        if ( n <= ic ) {
+          Kokkos::abort("Kokkos::DynamicView array bounds error");
+        }
+
+        // Allocation of this chunk is in progress 
+        // so wait for allocation to complete.
+        while ( 0 == *ch );
+      }
+
+      return (*ch)[ i0 & m_chunk_mask ];
+    }
+
+  //----------------------------------------
+  /** \brief  Resizing in parallel only increases the array size,
+   *          never decrease.
+   */
+  KOKKOS_INLINE_FUNCTION
+  void resize_parallel( size_t n ) const
+    {
+      typedef typename traits::value_type value_type ;
+
+      Kokkos::Impl::VerifyExecutionCanAccessMemorySpace
+        < Kokkos::Impl::ActiveExecutionMemorySpace
+        , typename traits::memory_space >::verify();
+
+      const uintptr_t NC = ( n + m_chunk_mask ) >> m_chunk_shift ;
+
+      if ( m_chunk_max < NC ) {
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+        printf("DynamicView::resize_parallel(%lu) m_chunk_max(%lu) NC(%lu)\n"
+              , n , m_chunk_max , NC );
+#endif
+        Kokkos::abort("DynamicView::resize_parallel exceeded maximum size");
+      }
+
+      typename traits::value_type * volatile * const ch = m_chunks ;
+
+      // The allocated chunk counter is m_chunks[ m_chunk_max ]
+      uintptr_t volatile * const pc =
+        reinterpret_cast<uintptr_t volatile*>( m_chunks + m_chunk_max );
+
+      // Potentially concurrent iteration of allocation to the required size.
+
+      for ( uintptr_t jc = *pc ; jc < NC ; ) {
+
+        // Claim the 'jc' chunk to-be-allocated index
+
+        const uintptr_t jc_try = jc ;
+
+        // Jump iteration to the chunk counter.
+        
+        jc = atomic_compare_exchange( pc , jc_try , jc_try + 1 );
+
+        if ( jc_try == jc ) {
+
+          ch[jc_try] = reinterpret_cast<value_type*>(
+            m_pool.allocate( sizeof(value_type) << m_chunk_shift ));
+
+          Kokkos::memory_fence();
+        }
+      }
+    }
+
+  /** \brief  Resizing in serial can grow or shrink the array size, */
+  inline
+  void resize_serial( size_t n )
+    {
+      Kokkos::Impl::VerifyExecutionCanAccessMemorySpace
+        < Kokkos::Impl::ActiveExecutionMemorySpace
+        , typename traits::memory_space >::verify();
+
+      const uintptr_t NC = ( n + m_chunk_mask ) >> m_chunk_shift ;
+
+      if ( m_chunk_max < NC ) {
+        Kokkos::abort("DynamicView::resize_serial exceeded maximum size");
+      }
+
+      uintptr_t * const pc =
+        reinterpret_cast<uintptr_t*>( m_chunks + m_chunk_max );
+
+      if ( *pc < NC ) {
+        while ( *pc < NC ) {
+          m_chunks[*pc] =
+            m_pool.allocate( sizeof(traits::value_type) << m_chunk_shift );
+          ++*pc ;
+        }
+      }
+      else {
+        while ( NC + 1 <= *pc ) {
+          --*pc ;        
+          m_pool.deallocate( m_chunks[*pc]
+                           , sizeof(traits::value_type) << m_chunk_shift );
+          m_chunks[*pc] = 0 ;
+        }
+      }
+    }
+
+  //----------------------------------------------------------------------
+
+  ~DynamicView() = default ;
+  DynamicView() = default ;
+  DynamicView( DynamicView && ) = default ;
+  DynamicView( const DynamicView & ) = default ;
+  DynamicView & operator = ( DynamicView && ) = default ;
+  DynamicView & operator = ( const DynamicView & ) = default ;
+
+  template< class RT , class ... RP >
+  KOKKOS_INLINE_FUNCTION
+  DynamicView( const DynamicView<RT,RP...> & rhs )
+    : m_pool( rhs.m_pool )
+    , m_track( rhs.m_track )
+    , m_chunks( rhs.m_chunks )
+    , m_chunk_shift( rhs.m_chunk_shift )
+    , m_chunk_mask( rhs.m_chunk_mask )
+    , m_chunk_max( rhs.m_chunk_max )
+    {
+    }
+
+  //----------------------------------------------------------------------
+
+  struct Destroy {
+    memory_pool                    m_pool ;
+    typename traits::value_type ** m_chunks ;
+    unsigned                       m_chunk_max ;
+    bool                           m_destroy ;
+
+    // Initialize or destroy array of chunk pointers.
+    // Two entries beyond the max chunks are allocation counters.
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()( unsigned i ) const
+      {
+        if ( m_destroy && i < m_chunk_max && 0 != m_chunks[i] ) {
+          m_pool.deallocate( m_chunks[i] , m_pool.get_min_block_size() );
+        }
+        m_chunks[i] = 0 ;
+      }
+
+    void execute( bool arg_destroy )
+      {
+        typedef Kokkos::RangePolicy< typename traits::execution_space > Range ;
+
+        m_destroy = arg_destroy ;
+
+        Kokkos::Impl::ParallelFor<Destroy,Range>
+          closure( *this , Range(0, m_chunk_max + 1) );
+
+        closure.execute();
+
+        traits::execution_space::fence();
+      }
+
+    void construct_shared_allocation()
+      { execute( false ); }
+
+    void destroy_shared_allocation()
+      { execute( true ); }
+
+    Destroy() = default ;
+    Destroy( Destroy && ) = default ;
+    Destroy( const Destroy & ) = default ;
+    Destroy & operator = ( Destroy && ) = default ;
+    Destroy & operator = ( const Destroy & ) = default ;
+
+    Destroy( const memory_pool & arg_pool
+           , typename traits::value_type ** arg_chunk
+           , const unsigned arg_chunk_max )
+     : m_pool( arg_pool )
+     , m_chunks( arg_chunk )
+     , m_chunk_max( arg_chunk_max )
+     , m_destroy( false )
+     {}
+  };
+
+
+  /**\brief  Allocation constructor 
+   *
+   *  Memory is allocated in chunks from the memory pool.
+   *  The chunk size conforms to the memory pool's chunk size.
+   *  A maximum size is required in order to allocate a
+   *  chunk-pointer array.
+   */
+  explicit inline
+  DynamicView( const std::string & arg_label
+             , const memory_pool & arg_pool
+             , const size_t        arg_size_max )
+    : m_pool( arg_pool )
+    , m_track()
+    , m_chunks(0)
+    // The memory pool chunk is guaranteed to be a power of two
+    , m_chunk_shift(
+        Kokkos::Impl::integral_power_of_two(
+          m_pool.get_min_block_size()/sizeof(typename traits::value_type)) )
+    , m_chunk_mask( ( 1 << m_chunk_shift ) - 1 )
+    , m_chunk_max( ( arg_size_max + m_chunk_mask ) >> m_chunk_shift )
+    {
+      Kokkos::Impl::VerifyExecutionCanAccessMemorySpace
+        < Kokkos::Impl::ActiveExecutionMemorySpace
+        , typename traits::memory_space >::verify();
+
+      // A functor to deallocate all of the chunks upon final destruction
+
+      typedef typename traits::memory_space  memory_space ;
+      typedef Kokkos::Experimental::Impl::SharedAllocationRecord< memory_space , Destroy > record_type ;
+
+      // Allocate chunk pointers and allocation counter
+      record_type * const record =
+        record_type::allocate( memory_space()
+                             , arg_label
+                             , ( sizeof(pointer_type) * ( m_chunk_max + 1 ) ) );
+
+      m_chunks = reinterpret_cast<pointer_type*>( record->data() );
+
+      record->m_destroy = Destroy( m_pool , m_chunks , m_chunk_max );
+
+      // Initialize to zero
+
+      record->m_destroy.construct_shared_allocation();
+
+      m_track.assign_allocated_record_to_uninitialized( record );
+    }
+};
+
+} // namespace Experimental
+} // namespace Kokkos
+
+namespace Kokkos {
+namespace Experimental {
+
+template< class T , class ... P >
+inline
+typename Kokkos::Experimental::DynamicView<T,P...>::HostMirror
+create_mirror_view( const Kokkos::Experimental::DynamicView<T,P...> & src )
+{
+  return src ;
+}
+
+template< class T , class ... DP , class ... SP >
+inline
+void deep_copy( const View<T,DP...> & dst
+              , const DynamicView<T,SP...> & src
+              )
+{
+  typedef View<T,DP...>        dst_type ;
+  typedef DynamicView<T,SP...> src_type ;
+
+  typedef typename ViewTraits<T,DP...>::execution_space  dst_execution_space ;
+  typedef typename ViewTraits<T,SP...>::memory_space     src_memory_space ;
+
+  enum { DstExecCanAccessSrc =
+   Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename dst_execution_space::memory_space , src_memory_space >::value };
+
+  if ( DstExecCanAccessSrc ) {
+    // Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
+    Kokkos::Experimental::Impl::ViewRemap< dst_type , src_type >( dst , src );
+  }
+  else {
+    Kokkos::Impl::throw_runtime_exception("deep_copy given views that would require a temporary allocation");
+  }
+}
+
+template< class T , class ... DP , class ... SP >
+inline
+void deep_copy( const DynamicView<T,DP...> & dst
+              , const View<T,SP...> & src
+              )
+{
+  typedef DynamicView<T,SP...> dst_type ;
+  typedef View<T,DP...>        src_type ;
+
+  typedef typename ViewTraits<T,DP...>::execution_space  dst_execution_space ;
+  typedef typename ViewTraits<T,SP...>::memory_space     src_memory_space ;
+
+  enum { DstExecCanAccessSrc =
+   Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename dst_execution_space::memory_space , src_memory_space >::value };
+
+  if ( DstExecCanAccessSrc ) {
+    // Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
+    Kokkos::Experimental::Impl::ViewRemap< dst_type , src_type >( dst , src );
+  }
+  else {
+    Kokkos::Impl::throw_runtime_exception("deep_copy given views that would require a temporary allocation");
+  }
+}
+
+} // namespace Experimental
+} // namespace Kokkos
+
+#endif /* #ifndef KOKKOS_DYNAMIC_VIEW_HPP */
+
diff --git a/lib/kokkos/containers/src/Kokkos_Functional.hpp b/lib/kokkos/containers/src/Kokkos_Functional.hpp
new file mode 100644
index 0000000000..5c7350ef1c
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_Functional.hpp
@@ -0,0 +1,173 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_FUNCTIONAL_HPP
+#define KOKKOS_FUNCTIONAL_HPP
+
+#include <Kokkos_Macros.hpp>
+#include <impl/Kokkos_Functional_impl.hpp>
+
+namespace Kokkos {
+
+// These should work for most types
+
+template <typename T>
+struct pod_hash
+{
+  typedef T argument_type;
+  typedef T first_argument_type;
+  typedef uint32_t second_argument_type;
+  typedef uint32_t result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  uint32_t operator()(T const & t) const
+  { return Impl::MurmurHash3_x86_32( &t, sizeof(T), 0); }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  uint32_t operator()(T const & t, uint32_t seed) const
+  { return Impl::MurmurHash3_x86_32( &t, sizeof(T), seed); }
+};
+
+template <typename T>
+struct pod_equal_to
+{
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  typedef bool result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool operator()(T const & a, T const & b) const
+  { return Impl::bitwise_equal(&a,&b); }
+};
+
+template <typename T>
+struct pod_not_equal_to
+{
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  typedef bool result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool operator()(T const & a, T const & b) const
+  { return !Impl::bitwise_equal(&a,&b); }
+};
+
+template <typename T>
+struct equal_to
+{
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  typedef bool result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool operator()(T const & a, T const & b) const
+  { return a == b; }
+};
+
+template <typename T>
+struct not_equal_to
+{
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  typedef bool result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool operator()(T const & a, T const & b) const
+  { return a != b; }
+};
+
+
+template <typename T>
+struct greater
+{
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  typedef bool result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool operator()(T const & a, T const & b) const
+  { return a > b; }
+};
+
+
+template <typename T>
+struct less
+{
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  typedef bool result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool operator()(T const & a, T const & b) const
+  { return a < b; }
+};
+
+template <typename T>
+struct greater_equal
+{
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  typedef bool result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool operator()(T const & a, T const & b) const
+  { return a >= b; }
+};
+
+
+template <typename T>
+struct less_equal
+{
+  typedef T first_argument_type;
+  typedef T second_argument_type;
+  typedef bool result_type;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool operator()(T const & a, T const & b) const
+  { return a <= b; }
+};
+
+} // namespace Kokkos
+
+
+#endif //KOKKOS_FUNCTIONAL_HPP
+
+
diff --git a/lib/kokkos/containers/src/Kokkos_SegmentedView.hpp b/lib/kokkos/containers/src/Kokkos_SegmentedView.hpp
new file mode 100644
index 0000000000..5dd7a98b89
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_SegmentedView.hpp
@@ -0,0 +1,531 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_SEGMENTED_VIEW_HPP_
+#define KOKKOS_SEGMENTED_VIEW_HPP_
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <cstdio>
+
+#if ! KOKKOS_USING_EXP_VIEW
+
+namespace Kokkos {
+namespace Experimental {
+
+namespace Impl {
+
+template<class DataType, class Arg1Type, class Arg2Type, class Arg3Type>
+struct delete_segmented_view;
+
+template<class MemorySpace>
+inline
+void DeviceSetAllocatableMemorySize(size_t) {}
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+template<>
+inline
+void DeviceSetAllocatableMemorySize<Kokkos::CudaSpace>(size_t size) {
+#ifdef __CUDACC__
+  size_t size_limit;
+  cudaDeviceGetLimit(&size_limit,cudaLimitMallocHeapSize);
+  if(size_limit<size)
+    cudaDeviceSetLimit(cudaLimitMallocHeapSize,2*size);
+  cudaDeviceGetLimit(&size_limit,cudaLimitMallocHeapSize);
+#endif
+}
+
+template<>
+inline
+void DeviceSetAllocatableMemorySize<Kokkos::CudaUVMSpace>(size_t size) {
+#ifdef __CUDACC__
+  size_t size_limit;
+  cudaDeviceGetLimit(&size_limit,cudaLimitMallocHeapSize);
+  if(size_limit<size)
+    cudaDeviceSetLimit(cudaLimitMallocHeapSize,2*size);
+  cudaDeviceGetLimit(&size_limit,cudaLimitMallocHeapSize);
+#endif
+}
+
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) */
+
+}
+
+template< class DataType ,
+          class Arg1Type = void ,
+          class Arg2Type = void ,
+          class Arg3Type = void>
+class SegmentedView : public Kokkos::ViewTraits< DataType , Arg1Type , Arg2Type, Arg3Type >
+{
+public:
+  //! \name Typedefs for device types and various Kokkos::View specializations.
+  //@{
+  typedef Kokkos::ViewTraits< DataType , Arg1Type , Arg2Type, Arg3Type > traits ;
+
+  //! The type of a Kokkos::View on the device.
+  typedef Kokkos::View< typename traits::data_type ,
+                typename traits::array_layout ,
+                typename traits::memory_space ,
+                Kokkos::MemoryUnmanaged > t_dev ;
+
+
+private:
+  Kokkos::View<t_dev*,typename traits::memory_space> segments_;
+
+  Kokkos::View<int,typename traits::memory_space> realloc_lock;
+  Kokkos::View<int,typename traits::memory_space> nsegments_;
+
+  size_t segment_length_;
+  size_t segment_length_m1_;
+  int max_segments_;
+
+  int segment_length_log2;
+
+  // Dimensions, cardinality, capacity, and offset computation for
+  // multidimensional array view of contiguous memory.
+  // Inherits from Impl::Shape
+  typedef Kokkos::Impl::ViewOffset< typename traits::shape_type
+                          , typename traits::array_layout
+                          > offset_map_type ;
+
+  offset_map_type               m_offset_map ;
+
+  typedef Kokkos::View< typename traits::array_intrinsic_type ,
+                typename traits::array_layout ,
+                typename traits::memory_space ,
+                typename traits::memory_traits > array_type ;
+
+  typedef Kokkos::View< typename traits::const_data_type ,
+                typename traits::array_layout ,
+                typename traits::memory_space ,
+                typename traits::memory_traits > const_type ;
+
+  typedef Kokkos::View< typename traits::non_const_data_type ,
+                typename traits::array_layout ,
+                typename traits::memory_space ,
+                typename traits::memory_traits > non_const_type ;
+
+  typedef Kokkos::View< typename traits::non_const_data_type ,
+                typename traits::array_layout ,
+                HostSpace ,
+                void > HostMirror ;
+
+  template< bool Accessible >
+  KOKKOS_INLINE_FUNCTION
+  typename Kokkos::Impl::enable_if< Accessible , typename traits::size_type >::type
+  dimension_0_intern() const { return nsegments_() * segment_length_ ; }
+
+  template< bool Accessible >
+  KOKKOS_INLINE_FUNCTION
+  typename Kokkos::Impl::enable_if< ! Accessible , typename traits::size_type >::type
+  dimension_0_intern() const
+  {
+    // In Host space
+    int n = 0 ;
+#if ! defined( __CUDA_ARCH__ )
+    Kokkos::Impl::DeepCopy< HostSpace , typename traits::memory_space >( & n , nsegments_.ptr_on_device() , sizeof(int) );
+#endif
+
+    return n * segment_length_ ;
+  }
+
+public:
+
+  enum { Rank = traits::rank };
+
+  KOKKOS_INLINE_FUNCTION offset_map_type shape() const { return m_offset_map ; }
+
+  /* \brief return (current) size of dimension 0 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type dimension_0() const {
+    enum { Accessible = Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<
+      Kokkos::Impl::ActiveExecutionMemorySpace, typename traits::memory_space >::value };
+    int n = SegmentedView::dimension_0_intern< Accessible >();
+    return n ;
+  }
+
+  /* \brief return size of dimension 1 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type dimension_1() const { return m_offset_map.N1 ; }
+  /* \brief return size of dimension 2 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type dimension_2() const { return m_offset_map.N2 ; }
+  /* \brief return size of dimension 3 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type dimension_3() const { return m_offset_map.N3 ; }
+  /* \brief return size of dimension 4 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type dimension_4() const { return m_offset_map.N4 ; }
+  /* \brief return size of dimension 5 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type dimension_5() const { return m_offset_map.N5 ; }
+  /* \brief return size of dimension 6 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type dimension_6() const { return m_offset_map.N6 ; }
+  /* \brief return size of dimension 7 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type dimension_7() const { return m_offset_map.N7 ; }
+
+  /* \brief return size of dimension 2 */
+  KOKKOS_INLINE_FUNCTION typename traits::size_type size() const {
+    return dimension_0() *
+        m_offset_map.N1 * m_offset_map.N2 * m_offset_map.N3 * m_offset_map.N4 *
+        m_offset_map.N5 * m_offset_map.N6 * m_offset_map.N7 ;
+  }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  typename traits::size_type dimension( const iType & i ) const {
+    if(i==0)
+      return dimension_0();
+    else
+      return Kokkos::Impl::dimension( m_offset_map , i );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  typename traits::size_type capacity() {
+    return segments_.dimension_0() *
+        m_offset_map.N1 * m_offset_map.N2 * m_offset_map.N3 * m_offset_map.N4 *
+        m_offset_map.N5 * m_offset_map.N6 * m_offset_map.N7;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  typename traits::size_type get_num_segments() {
+    enum { Accessible = Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<
+      Kokkos::Impl::ActiveExecutionMemorySpace, typename traits::memory_space >::value };
+    int n = SegmentedView::dimension_0_intern< Accessible >();
+    return n/segment_length_ ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  typename traits::size_type get_max_segments() {
+    return max_segments_;
+  }
+
+  /// \brief Constructor that allocates View objects with an initial length of 0.
+  ///
+  /// This constructor works mostly like the analogous constructor of View.
+  /// The first argument is a string label, which is entirely for your
+  /// benefit.  (Different SegmentedView objects may have the same label if
+  /// you like.)  The second argument 'view_length' is the size of the segments.
+  /// This number must be a power of two. The third argument n0 is the maximum
+  /// value for the first dimension of the segmented view. The maximal allocatable
+  /// number of Segments is thus: (n0+view_length-1)/view_length.
+  /// The arguments that follow are the other dimensions of the (1-7) of the
+  /// View objects.  For example, for a View with 3 runtime dimensions,
+  /// the first 4 integer arguments will be nonzero:
+  /// SegmentedView("Name",32768,10000000,8,4). This allocates a SegmentedView
+  /// with a maximum of 306 segments of dimension (32768,8,4). The logical size of
+  /// the segmented view is (n,8,4) with n between 0 and 10000000.
+  /// You may omit the integer arguments that follow.
+  template< class LabelType >
+  SegmentedView(const LabelType & label ,
+      const size_t view_length ,
+      const size_t n0 ,
+      const size_t n1 = 0 ,
+      const size_t n2 = 0 ,
+      const size_t n3 = 0 ,
+      const size_t n4 = 0 ,
+      const size_t n5 = 0 ,
+      const size_t n6 = 0 ,
+      const size_t n7 = 0
+      ): segment_length_(view_length),segment_length_m1_(view_length-1)
+  {
+    segment_length_log2 = -1;
+    size_t l = segment_length_;
+    while(l>0) {
+      l>>=1;
+      segment_length_log2++;
+    }
+    l = 1<<segment_length_log2;
+    if(l!=segment_length_)
+      Kokkos::Impl::throw_runtime_exception("Kokkos::SegmentedView requires a 'power of 2' segment length");
+
+    max_segments_ = (n0+segment_length_m1_)/segment_length_;
+
+    Impl::DeviceSetAllocatableMemorySize<typename traits::memory_space>(segment_length_*max_segments_*sizeof(typename traits::value_type));
+
+    segments_ = Kokkos::View<t_dev*,typename traits::execution_space>(label , max_segments_);
+    realloc_lock = Kokkos::View<int,typename traits::execution_space>("Lock");
+    nsegments_ = Kokkos::View<int,typename traits::execution_space>("nviews");
+    m_offset_map.assign( n0, n1, n2, n3, n4, n5, n6, n7, n0*n1*n2*n3*n4*n5*n6*n7 );
+
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  SegmentedView(const SegmentedView& src):
+    segments_(src.segments_),
+    realloc_lock (src.realloc_lock),
+    nsegments_ (src.nsegments_),
+    segment_length_(src.segment_length_),
+    segment_length_m1_(src.segment_length_m1_),
+    max_segments_ (src.max_segments_),
+    segment_length_log2(src.segment_length_log2),
+    m_offset_map (src.m_offset_map)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  SegmentedView& operator= (const SegmentedView& src) {
+    segments_ = src.segments_;
+    realloc_lock = src.realloc_lock;
+    nsegments_ = src.nsegments_;
+    segment_length_= src.segment_length_;
+    segment_length_m1_= src.segment_length_m1_;
+    max_segments_ = src.max_segments_;
+    segment_length_log2= src.segment_length_log2;
+    m_offset_map = src.m_offset_map;
+    return *this;
+  }
+
+  ~SegmentedView() {
+    if ( !segments_.tracker().ref_counting()) { return; }
+    size_t ref_count = segments_.tracker().ref_count();
+    if(ref_count == 1u) {
+      Kokkos::fence();
+      typename Kokkos::View<int,typename traits::execution_space>::HostMirror h_nviews("h_nviews");
+      Kokkos::deep_copy(h_nviews,nsegments_);
+      Kokkos::parallel_for(h_nviews(),Impl::delete_segmented_view<DataType , Arg1Type , Arg2Type, Arg3Type>(*this));
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  t_dev get_segment(const int& i) const {
+    return segments_[i];
+  }
+
+  template< class MemberType>
+  KOKKOS_INLINE_FUNCTION
+  void grow (MemberType& team_member, const size_t& growSize) const {
+    if (growSize>max_segments_*segment_length_) {
+      printf ("Exceeding maxSize: %lu %lu\n", growSize, max_segments_*segment_length_);
+      return;
+    }
+
+    if(team_member.team_rank()==0) {
+      bool too_small = growSize > segment_length_ * nsegments_();
+      if (too_small) {
+        while(Kokkos::atomic_compare_exchange(&realloc_lock(),0,1) )
+          ; // get the lock
+        too_small = growSize > segment_length_ * nsegments_(); // Recheck once we have the lock
+        if(too_small) {
+          while(too_small) {
+            const size_t alloc_size = segment_length_*m_offset_map.N1*m_offset_map.N2*m_offset_map.N3*
+                m_offset_map.N4*m_offset_map.N5*m_offset_map.N6*m_offset_map.N7;
+            typename traits::non_const_value_type* const ptr = new typename traits::non_const_value_type[alloc_size];
+
+            segments_(nsegments_()) =
+                t_dev(ptr,segment_length_,m_offset_map.N1,m_offset_map.N2,m_offset_map.N3,m_offset_map.N4,m_offset_map.N5,m_offset_map.N6,m_offset_map.N7);
+            nsegments_()++;
+            too_small = growSize > segment_length_ * nsegments_();
+          }
+        }
+        realloc_lock() = 0; //release the lock
+      }
+    }
+    team_member.team_barrier();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void grow_non_thread_safe (const size_t& growSize) const {
+    if (growSize>max_segments_*segment_length_) {
+      printf ("Exceeding maxSize: %lu %lu\n", growSize, max_segments_*segment_length_);
+      return;
+    }
+    bool too_small = growSize > segment_length_ * nsegments_();
+    if(too_small) {
+      while(too_small) {
+        const size_t alloc_size = segment_length_*m_offset_map.N1*m_offset_map.N2*m_offset_map.N3*
+                            m_offset_map.N4*m_offset_map.N5*m_offset_map.N6*m_offset_map.N7;
+        typename traits::non_const_value_type* const ptr =
+          new typename traits::non_const_value_type[alloc_size];
+
+        segments_(nsegments_()) =
+          t_dev (ptr, segment_length_, m_offset_map.N1, m_offset_map.N2,
+                 m_offset_map.N3, m_offset_map.N4, m_offset_map.N5,
+                 m_offset_map.N6, m_offset_map.N7);
+        nsegments_()++;
+        too_small = growSize > segment_length_ * nsegments_();
+      }
+    }
+  }
+
+  template< typename iType0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( std::is_integral<iType0>::value && traits::rank == 1 )
+                         , typename traits::value_type &
+                         >::type
+    operator() ( const iType0 & i0 ) const
+    {
+      return segments_[i0>>segment_length_log2](i0&(segment_length_m1_));
+    }
+
+  template< typename iType0 , typename iType1 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( std::is_integral<iType0>::value &&
+                            std::is_integral<iType1>::value &&
+                            traits::rank == 2 )
+                         , typename traits::value_type &
+                         >::type
+    operator() ( const iType0 & i0 , const iType1 & i1 ) const
+    {
+      return segments_[i0>>segment_length_log2](i0&(segment_length_m1_),i1);
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( std::is_integral<iType0>::value &&
+                            std::is_integral<iType1>::value &&
+                            std::is_integral<iType2>::value &&
+                            traits::rank == 3 )
+                         , typename traits::value_type &
+                         >::type
+    operator() ( const iType0 & i0 , const iType1 & i1 , const iType2 & i2 ) const
+    {
+      return segments_[i0>>segment_length_log2](i0&(segment_length_m1_),i1,i2);
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( std::is_integral<iType0>::value &&
+                            std::is_integral<iType1>::value &&
+                            std::is_integral<iType2>::value &&
+                            std::is_integral<iType3>::value &&
+                            traits::rank == 4 )
+                         , typename traits::value_type &
+                         >::type
+    operator() ( const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 ) const
+    {
+      return segments_[i0>>segment_length_log2](i0&(segment_length_m1_),i1,i2,i3);
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3 ,
+            typename iType4 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( std::is_integral<iType0>::value &&
+                            std::is_integral<iType1>::value &&
+                            std::is_integral<iType2>::value &&
+                            std::is_integral<iType3>::value &&
+                            std::is_integral<iType4>::value &&
+                            traits::rank == 5 )
+                         , typename traits::value_type &
+                         >::type
+    operator() ( const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 ,
+                 const iType4 & i4 ) const
+    {
+      return segments_[i0>>segment_length_log2](i0&(segment_length_m1_),i1,i2,i3,i4);
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3 ,
+            typename iType4 , typename iType5 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( std::is_integral<iType0>::value &&
+                            std::is_integral<iType1>::value &&
+                            std::is_integral<iType2>::value &&
+                            std::is_integral<iType3>::value &&
+                            std::is_integral<iType4>::value &&
+                            std::is_integral<iType5>::value &&
+                            traits::rank == 6 )
+                         , typename traits::value_type &
+                         >::type
+    operator() ( const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 ,
+                 const iType4 & i4 , const iType5 & i5 ) const
+    {
+      return segments_[i0>>segment_length_log2](i0&(segment_length_m1_),i1,i2,i3,i4,i5);
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3 ,
+            typename iType4 , typename iType5 , typename iType6 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( std::is_integral<iType0>::value &&
+                            std::is_integral<iType1>::value &&
+                            std::is_integral<iType2>::value &&
+                            std::is_integral<iType3>::value &&
+                            std::is_integral<iType4>::value &&
+                            std::is_integral<iType5>::value &&
+                            std::is_integral<iType6>::value &&
+                            traits::rank == 7 )
+                         , typename traits::value_type &
+                         >::type
+    operator() ( const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 ,
+                 const iType4 & i4 , const iType5 & i5 , const iType6 & i6 ) const
+    {
+      return segments_[i0>>segment_length_log2](i0&(segment_length_m1_),i1,i2,i3,i4,i5,i6);
+    }
+
+  template< typename iType0 , typename iType1 , typename iType2 , typename iType3 ,
+            typename iType4 , typename iType5 , typename iType6 , typename iType7 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( std::is_integral<iType0>::value &&
+                            std::is_integral<iType1>::value &&
+                            std::is_integral<iType2>::value &&
+                            std::is_integral<iType3>::value &&
+                            std::is_integral<iType4>::value &&
+                            std::is_integral<iType5>::value &&
+                            std::is_integral<iType6>::value &&
+                            std::is_integral<iType7>::value &&
+                            traits::rank == 8 )
+                         , typename traits::value_type &
+                         >::type
+    operator() ( const iType0 & i0 , const iType1 & i1 , const iType2 & i2 , const iType3 & i3 ,
+                 const iType4 & i4 , const iType5 & i5 , const iType6 & i6 , const iType7 & i7 ) const
+    {
+      return segments_[i0>>segment_length_log2](i0&(segment_length_m1_),i1,i2,i3,i4,i5,i6,i7);
+    }
+};
+
+namespace Impl {
+template<class DataType, class Arg1Type, class Arg2Type, class Arg3Type>
+struct delete_segmented_view {
+  typedef SegmentedView<DataType , Arg1Type , Arg2Type, Arg3Type> view_type;
+  typedef typename view_type::execution_space execution_space;
+
+  view_type view_;
+  delete_segmented_view(view_type view):view_(view) {
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i) const {
+    delete [] view_.get_segment(i).ptr_on_device();
+  }
+};
+
+}
+}
+}
+
+#endif
+
+#endif
diff --git a/lib/kokkos/containers/src/Kokkos_StaticCrsGraph.hpp b/lib/kokkos/containers/src/Kokkos_StaticCrsGraph.hpp
new file mode 100644
index 0000000000..1ce38638a2
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_StaticCrsGraph.hpp
@@ -0,0 +1,226 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_STATICCRSGRAPH_HPP
+#define KOKKOS_STATICCRSGRAPH_HPP
+
+#include <string>
+#include <vector>
+
+#include <Kokkos_Core.hpp>
+
+namespace Kokkos {
+
+/// \class StaticCrsGraph
+/// \brief Compressed row storage array.
+///
+/// \tparam DataType The type of stored entries.  If a StaticCrsGraph is
+///   used as the graph of a sparse matrix, then this is usually an
+///   integer type, the type of the column indices in the sparse
+///   matrix.
+///
+/// \tparam Arg1Type The second template parameter, corresponding
+///   either to the Device type (if there are no more template
+///   parameters) or to the Layout type (if there is at least one more
+///   template parameter).
+///
+/// \tparam Arg2Type The third template parameter, which if provided
+///   corresponds to the Device type.
+///
+/// \tparam SizeType The type of row offsets.  Usually the default
+///   parameter suffices.  However, setting a nondefault value is
+///   necessary in some cases, for example, if you want to have a
+///   sparse matrices with dimensions (and therefore column indices)
+///   that fit in \c int, but want to store more than <tt>INT_MAX</tt>
+///   entries in the sparse matrix.
+///
+/// A row has a range of entries:
+/// <ul>
+/// <li> <tt> row_map[i0] <= entry < row_map[i0+1] </tt> </li>
+/// <li> <tt> 0 <= i1 < row_map[i0+1] - row_map[i0] </tt> </li>
+/// <li> <tt> entries( entry ,            i2 , i3 , ... ); </tt> </li>
+/// <li> <tt> entries( row_map[i0] + i1 , i2 , i3 , ... ); </tt> </li>
+/// </ul>
+template< class DataType,
+          class Arg1Type,
+          class Arg2Type = void,
+          typename SizeType = typename ViewTraits<DataType*, Arg1Type, Arg2Type, void >::size_type>
+class StaticCrsGraph {
+private:
+  typedef ViewTraits<DataType*, Arg1Type, Arg2Type, void> traits;
+
+public:
+  typedef DataType                                            data_type;
+  typedef typename traits::array_layout                       array_layout;
+  typedef typename traits::execution_space                    execution_space;
+  typedef typename traits::device_type                        device_type;
+  typedef SizeType                                            size_type;
+
+  typedef StaticCrsGraph< DataType , Arg1Type , Arg2Type , SizeType > staticcrsgraph_type;
+  typedef StaticCrsGraph< DataType , array_layout , typename traits::host_mirror_space , SizeType > HostMirror;
+  typedef View< const size_type* , array_layout, device_type >  row_map_type;
+  typedef View<       DataType*  , array_layout, device_type >  entries_type;
+
+  entries_type entries;
+  row_map_type row_map;
+
+  //! Construct an empty view.
+  StaticCrsGraph () : entries(), row_map() {}
+
+  //! Copy constructor (shallow copy).
+  StaticCrsGraph (const StaticCrsGraph& rhs) : entries (rhs.entries), row_map (rhs.row_map)
+  {}
+
+  template<class EntriesType, class RowMapType>
+  StaticCrsGraph (const EntriesType& entries_,const RowMapType& row_map_) : entries (entries_), row_map (row_map_)
+  {}
+
+  /** \brief  Assign to a view of the rhs array.
+   *          If the old view is the last view
+   *          then allocated memory is deallocated.
+   */
+  StaticCrsGraph& operator= (const StaticCrsGraph& rhs) {
+    entries = rhs.entries;
+    row_map = rhs.row_map;
+    return *this;
+  }
+
+  /**  \brief  Destroy this view of the array.
+   *           If the last view then allocated memory is deallocated.
+   */
+  ~StaticCrsGraph() {}
+
+  KOKKOS_INLINE_FUNCTION
+  size_type numRows() const {
+    return (row_map.dimension_0 () != 0) ?
+      row_map.dimension_0 () - static_cast<size_type> (1) :
+      static_cast<size_type> (0);
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< class StaticCrsGraphType , class InputSizeType >
+typename StaticCrsGraphType::staticcrsgraph_type
+create_staticcrsgraph( const std::string & label ,
+                 const std::vector< InputSizeType > & input );
+
+template< class StaticCrsGraphType , class InputSizeType >
+typename StaticCrsGraphType::staticcrsgraph_type
+create_staticcrsgraph( const std::string & label ,
+                 const std::vector< std::vector< InputSizeType > > & input );
+
+//----------------------------------------------------------------------------
+
+template< class DataType ,
+          class Arg1Type ,
+          class Arg2Type ,
+          typename SizeType >
+typename StaticCrsGraph< DataType , Arg1Type , Arg2Type , SizeType >::HostMirror
+create_mirror_view( const StaticCrsGraph<DataType,Arg1Type,Arg2Type,SizeType > & input );
+
+template< class DataType ,
+          class Arg1Type ,
+          class Arg2Type ,
+          typename SizeType >
+typename StaticCrsGraph< DataType , Arg1Type , Arg2Type , SizeType >::HostMirror
+create_mirror( const StaticCrsGraph<DataType,Arg1Type,Arg2Type,SizeType > & input );
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#include <impl/Kokkos_StaticCrsGraph_factory.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class GraphType >
+struct StaticCrsGraphMaximumEntry {
+
+  typedef typename GraphType::execution_space execution_space ;
+  typedef typename GraphType::data_type value_type ;
+
+  const typename GraphType::entries_type entries ;
+
+  StaticCrsGraphMaximumEntry( const GraphType & graph ) : entries( graph.entries ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned i , value_type & update ) const
+    { if ( update < entries(i) ) update = entries(i); }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & update ) const
+    { update = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & update ,
+             volatile const value_type & input ) const
+    { if ( update < input ) update = input ; }
+};
+
+}
+
+template< class DataType, class Arg1Type, class Arg2Type, typename SizeType >
+DataType maximum_entry( const StaticCrsGraph< DataType , Arg1Type , Arg2Type , SizeType > & graph )
+{
+  typedef StaticCrsGraph<DataType,Arg1Type,Arg2Type,SizeType> GraphType ;
+  typedef Impl::StaticCrsGraphMaximumEntry< GraphType > FunctorType ;
+
+  DataType result = 0 ;
+  Kokkos::parallel_reduce( graph.entries.dimension_0(),
+                           FunctorType(graph), result );
+  return result ;
+}
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_CRSARRAY_HPP */
+
diff --git a/lib/kokkos/containers/src/Kokkos_UnorderedMap.hpp b/lib/kokkos/containers/src/Kokkos_UnorderedMap.hpp
new file mode 100644
index 0000000000..7a916c6ef7
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_UnorderedMap.hpp
@@ -0,0 +1,848 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/// \file Kokkos_UnorderedMap.hpp
+/// \brief Declaration and definition of Kokkos::UnorderedMap.
+///
+/// This header file declares and defines Kokkos::UnorderedMap and its
+/// related nonmember functions.
+
+#ifndef KOKKOS_UNORDERED_MAP_HPP
+#define KOKKOS_UNORDERED_MAP_HPP
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Functional.hpp>
+
+#include <Kokkos_Bitset.hpp>
+
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_UnorderedMap_impl.hpp>
+
+
+#include <iostream>
+
+#include <stdint.h>
+#include <stdexcept>
+
+
+namespace Kokkos {
+
+enum { UnorderedMapInvalidIndex = ~0u };
+
+/// \brief First element of the return value of UnorderedMap::insert().
+///
+/// Inserting an element into an UnorderedMap is not guaranteed to
+/// succeed.  There are three possible conditions:
+/// <ol>
+/// <li> <tt>INSERT_FAILED</tt>: The insert failed.  This usually
+///      means that the UnorderedMap ran out of space. </li>
+/// <li> <tt>INSERT_SUCCESS</tt>: The insert succeeded, and the key
+///      did <i>not</i> exist in the table before. </li>
+/// <li> <tt>INSERT_EXISTING</tt>: The insert succeeded, and the key
+///      <i>did</i> exist in the table before.  The new value was
+///      ignored and the old value was left in place. </li>
+/// </ol>
+
+class UnorderedMapInsertResult
+{
+private:
+  enum Status{
+     SUCCESS = 1u << 31
+   , EXISTING = 1u << 30
+   , FREED_EXISTING = 1u << 29
+   , LIST_LENGTH_MASK = ~(SUCCESS | EXISTING | FREED_EXISTING)
+  };
+
+public:
+  /// Did the map successful insert the key/value pair
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool success() const { return (m_status & SUCCESS); }
+
+  /// Was the key already present in the map
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool existing() const { return (m_status & EXISTING); }
+
+  /// Did the map fail to insert the key due to insufficent capacity
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool failed() const { return m_index == UnorderedMapInvalidIndex; }
+
+  /// Did the map lose a race condition to insert a dupulicate key/value pair
+  /// where an index was claimed that needed to be released
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool freed_existing() const { return (m_status & FREED_EXISTING); }
+
+  /// How many iterations through the insert loop did it take before the
+  /// map returned
+  KOKKOS_FORCEINLINE_FUNCTION
+  uint32_t list_position() const { return (m_status & LIST_LENGTH_MASK); }
+
+  /// Index where the key can be found as long as the insert did not fail
+  KOKKOS_FORCEINLINE_FUNCTION
+  uint32_t index() const { return m_index; }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  UnorderedMapInsertResult()
+    : m_index(UnorderedMapInvalidIndex)
+    , m_status(0)
+  {}
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  void increment_list_position()
+  {
+    m_status += (list_position() < LIST_LENGTH_MASK) ? 1u : 0u;
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  void set_existing(uint32_t i, bool arg_freed_existing)
+  {
+    m_index = i;
+    m_status = EXISTING | (arg_freed_existing ? FREED_EXISTING : 0u) | list_position();
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  void set_success(uint32_t i)
+  {
+    m_index = i;
+    m_status = SUCCESS | list_position();
+  }
+
+private:
+  uint32_t m_index;
+  uint32_t m_status;
+};
+
+/// \class UnorderedMap
+/// \brief Thread-safe, performance-portable lookup table.
+///
+/// This class provides a lookup table.  In terms of functionality,
+/// this class compares to std::unordered_map (new in C++11).
+/// "Unordered" means that keys are not stored in any particular
+/// order, unlike (for example) std::map.  "Thread-safe" means that
+/// lookups, insertion, and deletion are safe to call by multiple
+/// threads in parallel.  "Performance-portable" means that parallel
+/// performance of these operations is reasonable, on multiple
+/// hardware platforms.  Platforms on which performance has been
+/// tested include conventional Intel x86 multicore processors, Intel
+/// Xeon Phi ("MIC"), and NVIDIA GPUs.
+///
+/// Parallel performance portability entails design decisions that
+/// might differ from one's expectation for a sequential interface.
+/// This particularly affects insertion of single elements.  In an
+/// interface intended for sequential use, insertion might reallocate
+/// memory if the original allocation did not suffice to hold the new
+/// element.  In this class, insertion does <i>not</i> reallocate
+/// memory.  This means that it might fail.  insert() returns an enum
+/// which indicates whether the insert failed.  There are three
+/// possible conditions:
+/// <ol>
+/// <li> <tt>INSERT_FAILED</tt>: The insert failed.  This usually
+///      means that the UnorderedMap ran out of space. </li>
+/// <li> <tt>INSERT_SUCCESS</tt>: The insert succeeded, and the key
+///      did <i>not</i> exist in the table before. </li>
+/// <li> <tt>INSERT_EXISTING</tt>: The insert succeeded, and the key
+///      <i>did</i> exist in the table before.  The new value was
+///      ignored and the old value was left in place. </li>
+/// </ol>
+///
+/// \tparam Key Type of keys of the lookup table.  If \c const, users
+///   are not allowed to add or remove keys, though they are allowed
+///   to change values.  In that case, the implementation may make
+///   optimizations specific to the <tt>Device</tt>.  For example, if
+///   <tt>Device</tt> is \c Cuda, it may use texture fetches to access
+///   keys.
+///
+/// \tparam Value Type of values stored in the lookup table.  You may use
+///   \c void here, in which case the table will be a set of keys.  If
+///   \c const, users are not allowed to change entries.
+///   In that case, the implementation may make
+///   optimizations specific to the \c Device, such as using texture
+///   fetches to access values.
+///
+/// \tparam Device The Kokkos Device type.
+///
+/// \tparam Hasher Definition of the hash function for instances of
+///   <tt>Key</tt>.  The default will calculate a bitwise hash.
+///
+/// \tparam EqualTo Definition of the equality function for instances of
+///   <tt>Key</tt>.  The default will do a bitwise equality comparison.
+///
+template <   typename Key
+           , typename Value
+           , typename Device = Kokkos::DefaultExecutionSpace
+           , typename Hasher = pod_hash<typename Impl::remove_const<Key>::type>
+           , typename EqualTo = pod_equal_to<typename Impl::remove_const<Key>::type>
+        >
+class UnorderedMap
+{
+private:
+  typedef typename ViewTraits<Key,Device,void,void>::host_mirror_space host_mirror_space ;
+public:
+  //! \name Public types and constants
+  //@{
+
+  //key_types
+  typedef Key declared_key_type;
+  typedef typename Impl::remove_const<declared_key_type>::type key_type;
+  typedef typename Impl::add_const<key_type>::type const_key_type;
+
+  //value_types
+  typedef Value declared_value_type;
+  typedef typename Impl::remove_const<declared_value_type>::type value_type;
+  typedef typename Impl::add_const<value_type>::type const_value_type;
+
+  typedef Device execution_space;
+  typedef Hasher hasher_type;
+  typedef EqualTo  equal_to_type;
+  typedef uint32_t size_type;
+
+  //map_types
+  typedef UnorderedMap<declared_key_type,declared_value_type,execution_space,hasher_type,equal_to_type> declared_map_type;
+  typedef UnorderedMap<key_type,value_type,execution_space,hasher_type,equal_to_type>                   insertable_map_type;
+  typedef UnorderedMap<const_key_type,value_type,execution_space,hasher_type,equal_to_type>             modifiable_map_type;
+  typedef UnorderedMap<const_key_type,const_value_type,execution_space,hasher_type,equal_to_type>       const_map_type;
+
+  static const bool is_set = Impl::is_same<void,value_type>::value;
+  static const bool has_const_key = Impl::is_same<const_key_type,declared_key_type>::value;
+  static const bool has_const_value = is_set || Impl::is_same<const_value_type,declared_value_type>::value;
+
+  static const bool is_insertable_map = !has_const_key && (is_set || !has_const_value);
+  static const bool is_modifiable_map = has_const_key && !has_const_value;
+  static const bool is_const_map = has_const_key && has_const_value;
+
+
+  typedef UnorderedMapInsertResult insert_result;
+
+  typedef UnorderedMap<Key,Value,host_mirror_space,Hasher,EqualTo> HostMirror;
+
+  typedef Impl::UnorderedMapHistogram<const_map_type> histogram_type;
+
+  //@}
+
+private:
+  enum { invalid_index = ~static_cast<size_type>(0) };
+
+  typedef typename Impl::if_c< is_set, int, declared_value_type>::type impl_value_type;
+
+  typedef typename Impl::if_c<   is_insertable_map
+                               , View< key_type *, execution_space>
+                               , View< const key_type *, execution_space, MemoryTraits<RandomAccess> >
+                             >::type key_type_view;
+
+  typedef typename Impl::if_c<   is_insertable_map || is_modifiable_map
+                               , View< impl_value_type *, execution_space>
+                               , View< const impl_value_type *, execution_space, MemoryTraits<RandomAccess> >
+                             >::type value_type_view;
+
+  typedef typename Impl::if_c<   is_insertable_map
+                               , View< size_type *, execution_space>
+                               , View< const size_type *, execution_space, MemoryTraits<RandomAccess> >
+                             >::type size_type_view;
+
+  typedef typename Impl::if_c<   is_insertable_map
+                               , Bitset< execution_space >
+                               , ConstBitset< execution_space>
+                             >::type bitset_type;
+
+  enum { modified_idx = 0, erasable_idx = 1, failed_insert_idx = 2 };
+  enum { num_scalars = 3 };
+  typedef View< int[num_scalars], LayoutLeft, execution_space> scalars_view;
+
+public:
+  //! \name Public member functions
+  //@{
+
+  UnorderedMap()
+    : m_bounded_insert()
+    , m_hasher()
+    , m_equal_to()
+    , m_size()
+    , m_available_indexes()
+    , m_hash_lists()
+    , m_next_index()
+    , m_keys()
+    , m_values()
+    , m_scalars()
+  {}
+
+  /// \brief Constructor
+  ///
+  /// \param capacity_hint [in] Initial guess of how many unique keys will be inserted into the map
+  /// \param hash [in] Hasher function for \c Key instances.  The
+  ///   default value usually suffices.
+  UnorderedMap(  size_type capacity_hint, hasher_type hasher = hasher_type(), equal_to_type equal_to = equal_to_type() )
+    : m_bounded_insert(true)
+    , m_hasher(hasher)
+    , m_equal_to(equal_to)
+    , m_size()
+    , m_available_indexes(calculate_capacity(capacity_hint))
+    , m_hash_lists(ViewAllocateWithoutInitializing("UnorderedMap hash list"), Impl::find_hash_size(capacity()))
+    , m_next_index(ViewAllocateWithoutInitializing("UnorderedMap next index"), capacity()+1) // +1 so that the *_at functions can always return a valid reference
+    , m_keys("UnorderedMap keys",capacity()+1)
+    , m_values("UnorderedMap values",(is_set? 1 : capacity()+1))
+    , m_scalars("UnorderedMap scalars")
+  {
+    if (!is_insertable_map) {
+      throw std::runtime_error("Cannot construct a non-insertable (i.e. const key_type) unordered_map");
+    }
+
+    Kokkos::deep_copy(m_hash_lists, invalid_index);
+    Kokkos::deep_copy(m_next_index, invalid_index);
+  }
+
+  void reset_failed_insert_flag()
+  {
+    reset_flag(failed_insert_idx);
+  }
+
+  histogram_type get_histogram()
+  {
+    return histogram_type(*this);
+  }
+
+  //! Clear all entries in the table.
+  void clear()
+  {
+    m_bounded_insert = true;
+
+    if (capacity() == 0) return;
+
+    m_available_indexes.clear();
+
+    Kokkos::deep_copy(m_hash_lists, invalid_index);
+    Kokkos::deep_copy(m_next_index, invalid_index);
+    {
+      const key_type tmp = key_type();
+      Kokkos::deep_copy(m_keys,tmp);
+    }
+    if (is_set){
+      const impl_value_type tmp = impl_value_type();
+      Kokkos::deep_copy(m_values,tmp);
+    }
+    {
+      Kokkos::deep_copy(m_scalars, 0);
+    }
+  }
+
+  /// \brief Change the capacity of the the map
+  ///
+  /// If there are no failed inserts the current size of the map will
+  /// be used as a lower bound for the input capacity.
+  /// If the map is not empty and does not have failed inserts
+  /// and the capacity changes then the current data is copied
+  /// into the resized / rehashed map.
+  ///
+  /// This is <i>not</i> a device function; it may <i>not</i> be
+  /// called in a parallel kernel.
+  bool rehash(size_type requested_capacity = 0)
+  {
+    const bool bounded_insert = (capacity() == 0) || (size() == 0u);
+    return rehash(requested_capacity, bounded_insert );
+  }
+
+  bool rehash(size_type requested_capacity, bool bounded_insert)
+  {
+    if(!is_insertable_map) return false;
+
+    const size_type curr_size = size();
+    requested_capacity = (requested_capacity < curr_size) ? curr_size : requested_capacity;
+
+    insertable_map_type tmp(requested_capacity, m_hasher, m_equal_to);
+
+    if (curr_size) {
+      tmp.m_bounded_insert = false;
+      Impl::UnorderedMapRehash<insertable_map_type> f(tmp,*this);
+      f.apply();
+    }
+    tmp.m_bounded_insert = bounded_insert;
+
+    *this = tmp;
+
+    return true;
+  }
+
+  /// \brief The number of entries in the table.
+  ///
+  /// This method has undefined behavior when erasable() is true.
+  ///
+  /// Note that this is not a device function; it cannot be called in
+  /// a parallel kernel.  The value is not stored as a variable; it
+  /// must be computed.
+  size_type size() const
+  {
+    if( capacity() == 0u ) return 0u;
+    if (modified()) {
+      m_size = m_available_indexes.count();
+      reset_flag(modified_idx);
+    }
+    return m_size;
+  }
+
+  /// \brief The current number of failed insert() calls.
+  ///
+  /// This is <i>not</i> a device function; it may <i>not</i> be
+  /// called in a parallel kernel.  The value is not stored as a
+  /// variable; it must be computed.
+  bool failed_insert() const
+  {
+    return get_flag(failed_insert_idx);
+  }
+
+  bool erasable() const
+  {
+    return is_insertable_map ? get_flag(erasable_idx) : false;
+  }
+
+  bool begin_erase()
+  {
+    bool result = !erasable();
+    if (is_insertable_map && result) {
+      execution_space::fence();
+      set_flag(erasable_idx);
+      execution_space::fence();
+    }
+    return result;
+  }
+
+  bool end_erase()
+  {
+    bool result = erasable();
+    if (is_insertable_map && result) {
+      execution_space::fence();
+      Impl::UnorderedMapErase<declared_map_type> f(*this);
+      f.apply();
+      execution_space::fence();
+      reset_flag(erasable_idx);
+    }
+    return result;
+  }
+
+  /// \brief The maximum number of entries that the table can hold.
+  ///
+  /// This <i>is</i> a device function; it may be called in a parallel
+  /// kernel.
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type capacity() const
+  { return m_available_indexes.size(); }
+
+  /// \brief The number of hash table "buckets."
+  ///
+  /// This is different than the number of entries that the table can
+  /// hold.  Each key hashes to an index in [0, hash_capacity() - 1].
+  /// That index can hold zero or more entries.  This class decides
+  /// what hash_capacity() should be, given the user's upper bound on
+  /// the number of entries the table must be able to hold.
+  ///
+  /// This <i>is</i> a device function; it may be called in a parallel
+  /// kernel.
+  KOKKOS_INLINE_FUNCTION
+  size_type hash_capacity() const
+  { return m_hash_lists.dimension_0(); }
+
+  //---------------------------------------------------------------------------
+  //---------------------------------------------------------------------------
+
+
+  /// This <i>is</i> a device function; it may be called in a parallel
+  /// kernel.  As discussed in the class documentation, it need not
+  /// succeed.  The return value tells you if it did.
+  ///
+  /// \param k [in] The key to attempt to insert.
+  /// \param v [in] The corresponding value to attempt to insert.  If
+  ///   using this class as a set (with Value = void), then you need not
+  ///   provide this value.
+  KOKKOS_INLINE_FUNCTION
+  insert_result insert(key_type const& k, impl_value_type const&v = impl_value_type()) const
+  {
+    insert_result result;
+
+    if ( !is_insertable_map || capacity() == 0u || m_scalars((int)erasable_idx) ) {
+      return result;
+    }
+
+    if ( !m_scalars((int)modified_idx) ) {
+      m_scalars((int)modified_idx) = true;
+    }
+
+    int volatile & failed_insert_ref = m_scalars((int)failed_insert_idx) ;
+
+    const size_type hash_value = m_hasher(k);
+    const size_type hash_list = hash_value % m_hash_lists.dimension_0();
+
+    size_type * curr_ptr   = & m_hash_lists[ hash_list ];
+    size_type new_index    = invalid_index ;
+
+    // Force integer multiply to long
+    size_type index_hint = static_cast<size_type>( (static_cast<double>(hash_list) * capacity()) / m_hash_lists.dimension_0());
+
+    size_type find_attempts = 0;
+
+    enum { bounded_find_attempts = 32u };
+    const size_type max_attempts = (m_bounded_insert && (bounded_find_attempts < m_available_indexes.max_hint()) ) ?
+                                    bounded_find_attempts :
+                                    m_available_indexes.max_hint();
+
+    bool not_done = true ;
+
+#if defined( __MIC__ )
+      #pragma noprefetch
+#endif
+    while ( not_done ) {
+
+      // Continue searching the unordered list for this key,
+      // list will only be appended during insert phase.
+      // Need volatile_load as other threads may be appending.
+      size_type curr = volatile_load(curr_ptr);
+
+      KOKKOS_NONTEMPORAL_PREFETCH_LOAD(&m_keys[curr != invalid_index ? curr : 0]);
+#if defined( __MIC__ )
+      #pragma noprefetch
+#endif
+      while ( curr != invalid_index && ! m_equal_to( volatile_load(&m_keys[curr]), k) ) {
+        result.increment_list_position();
+        index_hint = curr;
+        curr_ptr = &m_next_index[curr];
+        curr = volatile_load(curr_ptr);
+        KOKKOS_NONTEMPORAL_PREFETCH_LOAD(&m_keys[curr != invalid_index ? curr : 0]);
+      }
+
+      //------------------------------------------------------------
+      // If key already present then return that index.
+      if ( curr != invalid_index ) {
+
+        const bool free_existing = new_index != invalid_index;
+        if ( free_existing ) {
+          // Previously claimed an unused entry that was not inserted.
+          // Release this unused entry immediately.
+          if (!m_available_indexes.reset(new_index) ) {
+            printf("Unable to free existing\n");
+          }
+
+        }
+
+        result.set_existing(curr, free_existing);
+        not_done = false ;
+      }
+      //------------------------------------------------------------
+      // Key is not currently in the map.
+      // If the thread has claimed an entry try to insert now.
+      else {
+
+        //------------------------------------------------------------
+        // If have not already claimed an unused entry then do so now.
+        if (new_index == invalid_index) {
+
+          bool found = false;
+          // use the hash_list as the flag for the search direction
+          Kokkos::tie(found, index_hint) = m_available_indexes.find_any_unset_near( index_hint, hash_list );
+
+          // found and index and this thread set it
+          if ( !found && ++find_attempts >= max_attempts ) {
+            failed_insert_ref = true;
+            not_done = false ;
+          }
+          else if (m_available_indexes.set(index_hint) ) {
+            new_index = index_hint;
+            // Set key and value
+            KOKKOS_NONTEMPORAL_PREFETCH_STORE(&m_keys[new_index]);
+            m_keys[new_index] = k ;
+
+            if (!is_set) {
+              KOKKOS_NONTEMPORAL_PREFETCH_STORE(&m_values[new_index]);
+              m_values[new_index] = v ;
+            }
+
+            // Do not proceed until key and value are updated in global memory
+            memory_fence();
+          }
+        }
+        else if (failed_insert_ref) {
+          not_done = false;
+        }
+
+        // Attempt to append claimed entry into the list.
+        // Another thread may also be trying to append the same list so protect with atomic.
+        if ( new_index != invalid_index &&
+             curr ==  atomic_compare_exchange(curr_ptr, static_cast<size_type>(invalid_index), new_index) ) {
+          // Succeeded in appending
+          result.set_success(new_index);
+          not_done = false ;
+        }
+      }
+    } // while ( not_done )
+
+    return result ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool erase(key_type const& k) const
+  {
+    bool result = false;
+
+    if(is_insertable_map && 0u < capacity() && m_scalars((int)erasable_idx)) {
+
+      if ( ! m_scalars((int)modified_idx) ) {
+        m_scalars((int)modified_idx) = true;
+      }
+
+      size_type index = find(k);
+      if (valid_at(index)) {
+        m_available_indexes.reset(index);
+        result = true;
+      }
+    }
+
+    return result;
+  }
+
+  /// \brief Find the given key \c k, if it exists in the table.
+  ///
+  /// \return If the key exists in the table, the index of the
+  ///   value corresponding to that key; otherwise, an invalid index.
+  ///
+  /// This <i>is</i> a device function; it may be called in a parallel
+  /// kernel.
+  KOKKOS_INLINE_FUNCTION
+  size_type find( const key_type & k) const
+  {
+    size_type curr = 0u < capacity() ? m_hash_lists( m_hasher(k) % m_hash_lists.dimension_0() ) : invalid_index ;
+
+    KOKKOS_NONTEMPORAL_PREFETCH_LOAD(&m_keys[curr != invalid_index ? curr : 0]);
+    while (curr != invalid_index && !m_equal_to( m_keys[curr], k) ) {
+      KOKKOS_NONTEMPORAL_PREFETCH_LOAD(&m_keys[curr != invalid_index ? curr : 0]);
+      curr = m_next_index[curr];
+    }
+
+    return curr;
+  }
+
+  /// \brief Does the key exist in the map
+  ///
+  /// This <i>is</i> a device function; it may be called in a parallel
+  /// kernel.
+  KOKKOS_INLINE_FUNCTION
+  bool exists( const key_type & k) const
+  {
+    return valid_at(find(k));
+  }
+
+
+  /// \brief Get the value with \c i as its direct index.
+  ///
+  /// \param i [in] Index directly into the array of entries.
+  ///
+  /// This <i>is</i> a device function; it may be called in a parallel
+  /// kernel.
+  ///
+  /// 'const value_type' via Cuda texture fetch must return by value.
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename Impl::if_c< (is_set || has_const_value), impl_value_type, impl_value_type &>::type
+  value_at(size_type i) const
+  {
+    return m_values[ is_set ? 0 : (i < capacity() ? i : capacity()) ];
+  }
+
+  /// \brief Get the key with \c i as its direct index.
+  ///
+  /// \param i [in] Index directly into the array of entries.
+  ///
+  /// This <i>is</i> a device function; it may be called in a parallel
+  /// kernel.
+  KOKKOS_FORCEINLINE_FUNCTION
+  key_type key_at(size_type i) const
+  {
+    return m_keys[ i < capacity() ? i : capacity() ];
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool valid_at(size_type i) const
+  {
+    return m_available_indexes.test(i);
+  }
+
+  template <typename SKey, typename SValue>
+  UnorderedMap( UnorderedMap<SKey,SValue,Device,Hasher,EqualTo> const& src,
+                typename Impl::enable_if< Impl::UnorderedMapCanAssign<declared_key_type,declared_value_type,SKey,SValue>::value,int>::type = 0
+              )
+    : m_bounded_insert(src.m_bounded_insert)
+    , m_hasher(src.m_hasher)
+    , m_equal_to(src.m_equal_to)
+    , m_size(src.m_size)
+    , m_available_indexes(src.m_available_indexes)
+    , m_hash_lists(src.m_hash_lists)
+    , m_next_index(src.m_next_index)
+    , m_keys(src.m_keys)
+    , m_values(src.m_values)
+    , m_scalars(src.m_scalars)
+  {}
+
+
+  template <typename SKey, typename SValue>
+  typename Impl::enable_if< Impl::UnorderedMapCanAssign<declared_key_type,declared_value_type,SKey,SValue>::value
+                           ,declared_map_type & >::type
+  operator=( UnorderedMap<SKey,SValue,Device,Hasher,EqualTo> const& src)
+  {
+    m_bounded_insert = src.m_bounded_insert;
+    m_hasher = src.m_hasher;
+    m_equal_to = src.m_equal_to;
+    m_size = src.m_size;
+    m_available_indexes = src.m_available_indexes;
+    m_hash_lists = src.m_hash_lists;
+    m_next_index = src.m_next_index;
+    m_keys = src.m_keys;
+    m_values = src.m_values;
+    m_scalars = src.m_scalars;
+    return *this;
+  }
+
+  template <typename SKey, typename SValue, typename SDevice>
+  typename Impl::enable_if< Impl::is_same< typename Impl::remove_const<SKey>::type, key_type>::value &&
+                            Impl::is_same< typename Impl::remove_const<SValue>::type, value_type>::value
+                          >::type
+  create_copy_view( UnorderedMap<SKey, SValue, SDevice, Hasher,EqualTo> const& src)
+  {
+    if (m_hash_lists.ptr_on_device() != src.m_hash_lists.ptr_on_device()) {
+
+      insertable_map_type tmp;
+
+      tmp.m_bounded_insert = src.m_bounded_insert;
+      tmp.m_hasher = src.m_hasher;
+      tmp.m_equal_to = src.m_equal_to;
+      tmp.m_size = src.size();
+      tmp.m_available_indexes = bitset_type( src.capacity() );
+      tmp.m_hash_lists        = size_type_view( ViewAllocateWithoutInitializing("UnorderedMap hash list"), src.m_hash_lists.dimension_0() );
+      tmp.m_next_index        = size_type_view( ViewAllocateWithoutInitializing("UnorderedMap next index"), src.m_next_index.dimension_0() );
+      tmp.m_keys              = key_type_view( ViewAllocateWithoutInitializing("UnorderedMap keys"), src.m_keys.dimension_0() );
+      tmp.m_values            = value_type_view( ViewAllocateWithoutInitializing("UnorderedMap values"), src.m_values.dimension_0() );
+      tmp.m_scalars           = scalars_view("UnorderedMap scalars");
+
+      Kokkos::deep_copy(tmp.m_available_indexes, src.m_available_indexes);
+
+      typedef Kokkos::Impl::DeepCopy< typename execution_space::memory_space, typename SDevice::memory_space > raw_deep_copy;
+
+      raw_deep_copy(tmp.m_hash_lists.ptr_on_device(), src.m_hash_lists.ptr_on_device(), sizeof(size_type)*src.m_hash_lists.dimension_0());
+      raw_deep_copy(tmp.m_next_index.ptr_on_device(), src.m_next_index.ptr_on_device(), sizeof(size_type)*src.m_next_index.dimension_0());
+      raw_deep_copy(tmp.m_keys.ptr_on_device(), src.m_keys.ptr_on_device(), sizeof(key_type)*src.m_keys.dimension_0());
+      if (!is_set) {
+        raw_deep_copy(tmp.m_values.ptr_on_device(), src.m_values.ptr_on_device(), sizeof(impl_value_type)*src.m_values.dimension_0());
+      }
+      raw_deep_copy(tmp.m_scalars.ptr_on_device(), src.m_scalars.ptr_on_device(), sizeof(int)*num_scalars );
+
+      *this = tmp;
+    }
+  }
+
+  //@}
+private: // private member functions
+
+  bool modified() const
+  {
+    return get_flag(modified_idx);
+  }
+
+  void set_flag(int flag) const
+  {
+    typedef Kokkos::Impl::DeepCopy< typename execution_space::memory_space, Kokkos::HostSpace > raw_deep_copy;
+    const int true_ = true;
+    raw_deep_copy(m_scalars.ptr_on_device() + flag, &true_, sizeof(int));
+  }
+
+  void reset_flag(int flag) const
+  {
+    typedef Kokkos::Impl::DeepCopy< typename execution_space::memory_space, Kokkos::HostSpace > raw_deep_copy;
+    const int false_ = false;
+    raw_deep_copy(m_scalars.ptr_on_device() + flag, &false_, sizeof(int));
+  }
+
+  bool get_flag(int flag) const
+  {
+    typedef Kokkos::Impl::DeepCopy< Kokkos::HostSpace, typename execution_space::memory_space > raw_deep_copy;
+    int result = false;
+    raw_deep_copy(&result, m_scalars.ptr_on_device() + flag, sizeof(int));
+    return result;
+  }
+
+  static uint32_t calculate_capacity(uint32_t capacity_hint)
+  {
+    // increase by 16% and round to nears multiple of 128
+    return capacity_hint ? ((static_cast<uint32_t>(7ull*capacity_hint/6u) + 127u)/128u)*128u : 128u;
+  }
+
+private: // private members
+  bool              m_bounded_insert;
+  hasher_type       m_hasher;
+  equal_to_type     m_equal_to;
+  mutable size_type m_size;
+  bitset_type       m_available_indexes;
+  size_type_view    m_hash_lists;
+  size_type_view    m_next_index;
+  key_type_view     m_keys;
+  value_type_view   m_values;
+  scalars_view      m_scalars;
+
+  template <typename KKey, typename VValue, typename DDevice, typename HHash, typename EEqualTo>
+  friend class UnorderedMap;
+
+  template <typename UMap>
+  friend struct Impl::UnorderedMapErase;
+
+  template <typename UMap>
+  friend struct Impl::UnorderedMapHistogram;
+
+  template <typename UMap>
+  friend struct Impl::UnorderedMapPrint;
+};
+
+// Specialization of deep_copy for two UnorderedMap objects.
+template <  typename DKey, typename DT, typename DDevice
+          , typename SKey, typename ST, typename SDevice
+          , typename Hasher, typename EqualTo >
+inline void deep_copy(         UnorderedMap<DKey, DT, DDevice, Hasher, EqualTo> & dst
+                       , const UnorderedMap<SKey, ST, SDevice, Hasher, EqualTo> & src )
+{
+  dst.create_copy_view(src);
+}
+
+
+} // namespace Kokkos
+
+#endif //KOKKOS_UNORDERED_MAP_HPP
diff --git a/lib/kokkos/containers/src/Kokkos_Vector.hpp b/lib/kokkos/containers/src/Kokkos_Vector.hpp
new file mode 100644
index 0000000000..6a360e8d19
--- /dev/null
+++ b/lib/kokkos/containers/src/Kokkos_Vector.hpp
@@ -0,0 +1,283 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_VECTOR_HPP
+#define KOKKOS_VECTOR_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_DualView.hpp>
+
+/* Drop in replacement for std::vector based on Kokkos::DualView
+ * Most functions only work on the host (it will not compile if called from device kernel)
+ *
+ */
+  namespace Kokkos {
+
+template< class Scalar, class Arg1Type = void>
+class vector : public DualView<Scalar*,LayoutLeft,Arg1Type> {
+
+  typedef Scalar value_type;
+  typedef Scalar* pointer;
+  typedef const Scalar* const_pointer;
+  typedef Scalar* reference;
+  typedef const Scalar* const_reference;
+  typedef Scalar* iterator;
+  typedef const Scalar* const_iterator;
+
+private:
+  size_t _size;
+  typedef size_t size_type;
+  float _extra_storage;
+  typedef DualView<Scalar*,LayoutLeft,Arg1Type> DV;
+
+
+public:
+#ifdef KOKKOS_CUDA_USE_UVM
+  KOKKOS_INLINE_FUNCTION Scalar& operator() (int i) const {return DV::h_view(i);};
+  KOKKOS_INLINE_FUNCTION Scalar& operator[] (int i) const {return DV::h_view(i);};
+#else
+  inline Scalar& operator() (int i) const {return DV::h_view(i);};
+  inline Scalar& operator[] (int i) const {return DV::h_view(i);};
+#endif
+
+  /* Member functions which behave like std::vector functions */
+
+  vector():DV() {
+    _size = 0;
+    _extra_storage = 1.1;
+    DV::modified_host() = 1;
+  };
+
+
+  vector(int n, Scalar val=Scalar()):DualView<Scalar*,LayoutLeft,Arg1Type>("Vector",size_t(n*(1.1))) {
+    _size = n;
+    _extra_storage = 1.1;
+    DV::modified_host() = 1;
+
+    assign(n,val);
+  }
+
+
+  void resize(size_t n) {
+    if(n>=capacity())
+      DV::resize(size_t (n*_extra_storage));
+    _size = n;
+  }
+
+  void resize(size_t n, const Scalar& val) {
+    assign(n,val);
+  }
+
+  void assign (size_t n, const Scalar& val) {
+
+    /* Resize if necessary (behavour of std:vector) */
+
+    if(n>capacity())
+      DV::resize(size_t (n*_extra_storage));
+    _size = n;
+
+          /* Assign value either on host or on device */
+
+    if( DV::modified_host() >= DV::modified_device() ) {
+      set_functor_host f(DV::h_view,val);
+      parallel_for(n,f);
+      DV::t_host::execution_space::fence();
+      DV::modified_host()++;
+    } else {
+      set_functor f(DV::d_view,val);
+      parallel_for(n,f);
+      DV::t_dev::execution_space::fence();
+      DV::modified_device()++;
+    }
+  }
+
+  void reserve(size_t n) {
+    DV::resize(size_t (n*_extra_storage));
+  }
+
+  void push_back(Scalar val) {
+    DV::modified_host()++;
+    if(_size == capacity()) {
+      size_t new_size = _size*_extra_storage;
+      if(new_size == _size) new_size++;
+      DV::resize(new_size);
+    }
+
+    DV::h_view(_size) = val;
+    _size++;
+
+  };
+
+  void pop_back() {
+    _size--;
+  };
+
+  void clear() {
+    _size = 0;
+  }
+
+  size_type size() const {return _size;};
+  size_type max_size() const {return 2000000000;}
+  size_type capacity() const {return DV::capacity();};
+  bool empty() const {return _size==0;};
+
+  iterator begin() const {return &DV::h_view(0);};
+
+  iterator end() const {return &DV::h_view(_size);};
+
+
+  /* std::algorithms wich work originally with iterators, here they are implemented as member functions */
+
+  size_t
+  lower_bound (const size_t& start,
+               const size_t& theEnd,
+               const Scalar& comp_val) const
+  {
+    int lower = start; // FIXME (mfh 24 Apr 2014) narrowing conversion
+    int upper = _size > theEnd? theEnd : _size-1; // FIXME (mfh 24 Apr 2014) narrowing conversion
+    if (upper <= lower) {
+      return theEnd;
+    }
+
+    Scalar lower_val = DV::h_view(lower);
+    Scalar upper_val = DV::h_view(upper);
+    size_t idx = (upper+lower)/2;
+    Scalar val = DV::h_view(idx);
+    if(val>upper_val) return upper;
+    if(val<lower_val) return start;
+
+    while(upper>lower) {
+      if(comp_val>val) {
+        lower = ++idx;
+      } else {
+        upper = idx;
+      }
+      idx = (upper+lower)/2;
+      val = DV::h_view(idx);
+    }
+    return idx;
+  }
+
+  bool is_sorted() {
+    for(int i=0;i<_size-1;i++) {
+      if(DV::h_view(i)>DV::h_view(i+1)) return false;
+    }
+    return true;
+  }
+
+  iterator find(Scalar val) const {
+    if(_size == 0) return end();
+
+    int upper,lower,current;
+    current = _size/2;
+    upper = _size-1;
+    lower = 0;
+
+    if((val<DV::h_view(0)) || (val>DV::h_view(_size-1)) ) return end();
+
+    while(upper>lower)
+    {
+      if(val>DV::h_view(current)) lower = current+1;
+      else upper = current;
+      current = (upper+lower)/2;
+    }
+
+    if(val==DV::h_view(current)) return &DV::h_view(current);
+    else return end();
+  }
+
+  /* Additional functions for data management */
+
+  void device_to_host(){
+    deep_copy(DV::h_view,DV::d_view);
+  }
+  void host_to_device() const {
+    deep_copy(DV::d_view,DV::h_view);
+  }
+
+  void on_host() {
+    DV::modified_host() = DV::modified_device() + 1;
+  }
+  void on_device() {
+    DV::modified_device() = DV::modified_host() + 1;
+  }
+
+  void set_overallocation(float extra) {
+    _extra_storage = 1.0 + extra;
+  }
+
+
+public:
+  struct set_functor {
+    typedef typename DV::t_dev::execution_space execution_space;
+    typename DV::t_dev _data;
+    Scalar _val;
+
+    set_functor(typename DV::t_dev data, Scalar val) :
+      _data(data),_val(val) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int &i) const {
+      _data(i) = _val;
+    }
+  };
+
+  struct set_functor_host {
+    typedef typename DV::t_host::execution_space execution_space;
+    typename DV::t_host _data;
+    Scalar _val;
+
+    set_functor_host(typename DV::t_host data, Scalar val) :
+      _data(data),_val(val) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int &i) const {
+      _data(i) = _val;
+    }
+  };
+
+};
+
+
+}
+#endif
diff --git a/lib/kokkos/containers/src/impl/Kokkos_Bitset_impl.hpp b/lib/kokkos/containers/src/impl/Kokkos_Bitset_impl.hpp
new file mode 100644
index 0000000000..df2fbed5a6
--- /dev/null
+++ b/lib/kokkos/containers/src/impl/Kokkos_Bitset_impl.hpp
@@ -0,0 +1,109 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_BITSET_IMPL_HPP
+#define KOKKOS_BITSET_IMPL_HPP
+
+#include <Kokkos_Macros.hpp>
+#include <impl/Kokkos_BitOps.hpp>
+#include <stdint.h>
+
+#include <cstdio>
+#include <climits>
+#include <iostream>
+#include <iomanip>
+
+namespace Kokkos {
+namespace Impl {
+
+KOKKOS_FORCEINLINE_FUNCTION
+unsigned rotate_right( unsigned i, int r )
+{
+  enum { size = static_cast<int>( sizeof(unsigned) * CHAR_BIT ) };
+  return r ? ( ( i >> r ) | ( i << ( size - r ) ) ) : i ;
+}
+
+template < typename Bitset >
+struct BitsetCount
+{
+  typedef Bitset                                                  bitset_type;
+  typedef typename bitset_type::execution_space::execution_space  execution_space;
+  typedef typename bitset_type::size_type                         size_type;
+  typedef size_type                                               value_type;
+
+  bitset_type m_bitset;
+
+  BitsetCount( bitset_type const& bitset )
+    : m_bitset(bitset)
+  {}
+
+  size_type apply() const
+  {
+    size_type count = 0u;
+    parallel_reduce( m_bitset.m_blocks.dimension_0(), *this, count );
+    return count;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & count ) const
+  {
+    count = 0u;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & count, const volatile size_type & incr ) const
+  {
+    count += incr;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i, value_type & count ) const
+  {
+    count += bit_count( m_bitset.m_blocks[i] );
+  }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+#endif // KOKKOS_BITSET_IMPL_HPP
diff --git a/lib/kokkos/containers/src/impl/Kokkos_Functional_impl.hpp b/lib/kokkos/containers/src/impl/Kokkos_Functional_impl.hpp
new file mode 100644
index 0000000000..c87bb8a3a3
--- /dev/null
+++ b/lib/kokkos/containers/src/impl/Kokkos_Functional_impl.hpp
@@ -0,0 +1,195 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_FUNCTIONAL_IMPL_HPP
+#define KOKKOS_FUNCTIONAL_IMPL_HPP
+
+#include <Kokkos_Macros.hpp>
+#include <stdint.h>
+
+namespace Kokkos { namespace Impl {
+
+// MurmurHash3 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+KOKKOS_FORCEINLINE_FUNCTION
+uint32_t getblock32 ( const uint8_t * p, int i )
+{
+// used to avoid aliasing error which could cause errors with
+// forced inlining
+  return    ((uint32_t)p[i*4+0])
+          | ((uint32_t)p[i*4+1] << 8)
+          | ((uint32_t)p[i*4+2] << 16)
+          | ((uint32_t)p[i*4+3] << 24);
+}
+
+KOKKOS_FORCEINLINE_FUNCTION
+uint32_t rotl32 ( uint32_t x, int8_t r )
+{ return (x << r) | (x >> (32 - r)); }
+
+KOKKOS_FORCEINLINE_FUNCTION
+uint32_t fmix32 ( uint32_t h )
+{
+  h ^= h >> 16;
+  h *= 0x85ebca6b;
+  h ^= h >> 13;
+  h *= 0xc2b2ae35;
+  h ^= h >> 16;
+
+  return h;
+}
+
+KOKKOS_INLINE_FUNCTION
+uint32_t MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed )
+{
+  const uint8_t * data = (const uint8_t*)key;
+  const int nblocks = len / 4;
+
+  uint32_t h1 = seed;
+
+  const uint32_t c1 = 0xcc9e2d51;
+  const uint32_t c2 = 0x1b873593;
+
+  //----------
+  // body
+
+  for(int i=0; i<nblocks; ++i)
+  {
+    uint32_t k1 = getblock32(data,i);
+
+    k1 *= c1;
+    k1 = rotl32(k1,15);
+    k1 *= c2;
+
+    h1 ^= k1;
+    h1 = rotl32(h1,13);
+    h1 = h1*5+0xe6546b64;
+  }
+
+  //----------
+  // tail
+
+  const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
+
+  uint32_t k1 = 0;
+
+  switch(len & 3)
+  {
+  case 3: k1 ^= tail[2] << 16;
+  case 2: k1 ^= tail[1] << 8;
+  case 1: k1 ^= tail[0];
+          k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1;
+  };
+
+  //----------
+  // finalization
+
+  h1 ^= len;
+
+  h1 = fmix32(h1);
+
+  return h1;
+}
+
+
+#if defined( __GNUC__ ) /* GNU C   */ || \
+    defined( __GNUG__ ) /* GNU C++ */ || \
+    defined( __clang__ )
+
+#define KOKKOS_MAY_ALIAS __attribute__((__may_alias__))
+
+#else
+
+#define KOKKOS_MAY_ALIAS
+
+#endif
+
+template <typename T>
+KOKKOS_FORCEINLINE_FUNCTION
+bool bitwise_equal(T const * const a_ptr, T const * const b_ptr)
+{
+  typedef uint64_t KOKKOS_MAY_ALIAS T64;
+  typedef uint32_t KOKKOS_MAY_ALIAS T32;
+  typedef uint16_t KOKKOS_MAY_ALIAS T16;
+  typedef uint8_t  KOKKOS_MAY_ALIAS T8;
+
+  enum {
+    NUM_8  = sizeof(T),
+    NUM_16 = NUM_8 / 2,
+    NUM_32 = NUM_8 / 4,
+    NUM_64 = NUM_8 / 8
+  };
+
+  union {
+    T   const * const ptr;
+    T64 const * const ptr64;
+    T32 const * const ptr32;
+    T16 const * const ptr16;
+    T8  const * const ptr8;
+  } a = {a_ptr}, b = {b_ptr};
+
+  bool result = true;
+
+  for (int i=0; i < NUM_64; ++i) {
+    result = result && a.ptr64[i] == b.ptr64[i];
+  }
+
+  if ( NUM_64*2 < NUM_32 ) {
+    result = result && a.ptr32[NUM_64*2] == b.ptr32[NUM_64*2];
+  }
+
+  if ( NUM_32*2 < NUM_16 ) {
+    result = result && a.ptr16[NUM_32*2] == b.ptr16[NUM_32*2];
+  }
+
+  if ( NUM_16*2 < NUM_8 ) {
+    result = result && a.ptr8[NUM_16*2] == b.ptr8[NUM_16*2];
+  }
+
+  return result;
+}
+
+
+
+#undef KOKKOS_MAY_ALIAS
+
+}} // namespace Kokkos::Impl
+
+#endif //KOKKOS_FUNCTIONAL_IMPL_HPP
diff --git a/lib/kokkos/containers/src/impl/Kokkos_StaticCrsGraph_factory.hpp b/lib/kokkos/containers/src/impl/Kokkos_StaticCrsGraph_factory.hpp
new file mode 100644
index 0000000000..c52fc24359
--- /dev/null
+++ b/lib/kokkos/containers/src/impl/Kokkos_StaticCrsGraph_factory.hpp
@@ -0,0 +1,208 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_IMPL_STATICCRSGRAPH_FACTORY_HPP
+#define KOKKOS_IMPL_STATICCRSGRAPH_FACTORY_HPP
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template< class DataType , class Arg1Type , class Arg2Type , typename SizeType >
+inline
+typename StaticCrsGraph< DataType , Arg1Type , Arg2Type , SizeType >::HostMirror
+create_mirror_view( const StaticCrsGraph<DataType,Arg1Type,Arg2Type,SizeType > & view ,
+                    typename Impl::enable_if< ViewTraits<DataType,Arg1Type,Arg2Type,void>::is_hostspace >::type * = 0 )
+{
+  return view ;
+}
+
+template< class DataType , class Arg1Type , class Arg2Type , typename SizeType >
+inline
+typename StaticCrsGraph< DataType , Arg1Type , Arg2Type , SizeType >::HostMirror
+create_mirror( const StaticCrsGraph<DataType,Arg1Type,Arg2Type,SizeType > & view )
+{
+  // Force copy:
+  //typedef Impl::ViewAssignment< Impl::ViewDefault > alloc ; // unused
+  typedef StaticCrsGraph< DataType , Arg1Type , Arg2Type , SizeType >  staticcrsgraph_type ;
+
+  typename staticcrsgraph_type::HostMirror               tmp ;
+  typename staticcrsgraph_type::row_map_type::HostMirror tmp_row_map = create_mirror( view.row_map);
+
+  // Allocation to match:
+  tmp.row_map = tmp_row_map ; // Assignment of 'const' from 'non-const'
+  tmp.entries = create_mirror( view.entries );
+
+
+  // Deep copy:
+  deep_copy( tmp_row_map , view.row_map );
+  deep_copy( tmp.entries , view.entries );
+
+  return tmp ;
+}
+
+template< class DataType , class Arg1Type , class Arg2Type , typename SizeType >
+inline
+typename StaticCrsGraph< DataType , Arg1Type , Arg2Type , SizeType >::HostMirror
+create_mirror_view( const StaticCrsGraph<DataType,Arg1Type,Arg2Type,SizeType > & view ,
+                    typename Impl::enable_if< ! ViewTraits<DataType,Arg1Type,Arg2Type,void>::is_hostspace >::type * = 0 )
+{
+  return create_mirror( view );
+}
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template< class StaticCrsGraphType , class InputSizeType >
+inline
+typename StaticCrsGraphType::staticcrsgraph_type
+create_staticcrsgraph( const std::string & label ,
+                 const std::vector< InputSizeType > & input )
+{
+  typedef StaticCrsGraphType                  output_type ;
+  //typedef std::vector< InputSizeType >  input_type ; // unused
+
+  typedef typename output_type::entries_type   entries_type ;
+
+  typedef View< typename output_type::size_type [] ,
+                typename output_type::array_layout ,
+                typename output_type::execution_space > work_type ;
+
+  output_type output ;
+
+  // Create the row map:
+
+  const size_t length = input.size();
+
+  {
+    work_type row_work( "tmp" , length + 1 );
+
+    typename work_type::HostMirror row_work_host =
+      create_mirror_view( row_work );
+
+    size_t sum = 0 ;
+    row_work_host[0] = 0 ;
+    for ( size_t i = 0 ; i < length ; ++i ) {
+      row_work_host[i+1] = sum += input[i];
+    }
+
+    deep_copy( row_work , row_work_host );
+
+    output.entries   = entries_type( label , sum );
+    output.row_map   = row_work ;
+  }
+
+  return output ;
+}
+
+//----------------------------------------------------------------------------
+
+template< class StaticCrsGraphType , class InputSizeType >
+inline
+typename StaticCrsGraphType::staticcrsgraph_type
+create_staticcrsgraph( const std::string & label ,
+                 const std::vector< std::vector< InputSizeType > > & input )
+{
+  typedef StaticCrsGraphType                  output_type ;
+  typedef typename output_type::entries_type  entries_type ;
+
+  static_assert( entries_type::rank == 1
+               , "Graph entries view must be rank one" );
+
+  typedef View< typename output_type::size_type [] ,
+                typename output_type::array_layout ,
+                typename output_type::execution_space > work_type ;
+
+  output_type output ;
+
+    // Create the row map:
+
+  const size_t length = input.size();
+
+  {
+    work_type row_work( "tmp" , length + 1 );
+
+    typename work_type::HostMirror row_work_host =
+      create_mirror_view( row_work );
+
+    size_t sum = 0 ;
+    row_work_host[0] = 0 ;
+    for ( size_t i = 0 ; i < length ; ++i ) {
+      row_work_host[i+1] = sum += input[i].size();
+    }
+
+    deep_copy( row_work , row_work_host );
+
+    output.entries   = entries_type( label , sum );
+    output.row_map   = row_work ;
+  }
+
+  // Fill in the entries:
+  {
+    typename entries_type::HostMirror host_entries =
+      create_mirror_view( output.entries );
+
+    size_t sum = 0 ;
+    for ( size_t i = 0 ; i < length ; ++i ) {
+      for ( size_t j = 0 ; j < input[i].size() ; ++j , ++sum ) {
+        host_entries( sum ) = input[i][j] ;
+      }
+    }
+
+    deep_copy( output.entries , host_entries );
+  }
+
+  return output ;
+}
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_IMPL_CRSARRAY_FACTORY_HPP */
+
diff --git a/lib/kokkos/containers/src/impl/Kokkos_UnorderedMap_impl.cpp b/lib/kokkos/containers/src/impl/Kokkos_UnorderedMap_impl.cpp
new file mode 100644
index 0000000000..843fd3a808
--- /dev/null
+++ b/lib/kokkos/containers/src/impl/Kokkos_UnorderedMap_impl.cpp
@@ -0,0 +1,101 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_UnorderedMap.hpp>
+
+namespace Kokkos { namespace Impl {
+
+uint32_t find_hash_size(uint32_t size)
+{
+  if (size == 0u) return 0u;
+
+  // these primes try to preserve randomness of hash
+  static const uint32_t primes [] = {
+        3, 7, 13, 23, 53, 97, 193, 389, 769, 1543
+      , 2237, 2423, 2617, 2797, 2999, 3167, 3359, 3539
+      , 3727, 3911, 4441 , 4787 , 5119 , 5471 , 5801 , 6143 , 6521 , 6827
+      , 7177 , 7517 , 7853 , 8887 , 9587 , 10243 , 10937 , 11617 , 12289
+      , 12967 , 13649 , 14341 , 15013 , 15727
+      , 17749 , 19121 , 20479 , 21859 , 23209 , 24593 , 25939 , 27329
+      , 28669 , 30047 , 31469 , 35507 , 38231 , 40961 , 43711 , 46439
+      , 49157 , 51893 , 54617 , 57347 , 60077 , 62801 , 70583 , 75619
+      , 80669 , 85703 , 90749 , 95783 , 100823 , 105871 , 110909 , 115963
+      , 120997 , 126031 , 141157 , 151237 , 161323 , 171401 , 181499 , 191579
+      , 201653 , 211741 , 221813 , 231893 , 241979 , 252079
+      , 282311 , 302483 , 322649 , 342803 , 362969 , 383143 , 403301 , 423457
+      , 443629 , 463787 , 483953 , 504121 , 564617 , 604949 , 645313 , 685609
+      , 725939 , 766273 , 806609 , 846931 , 887261 , 927587 , 967919 , 1008239
+      , 1123477 , 1198397 , 1273289 , 1348177 , 1423067 , 1497983 , 1572869
+      , 1647761 , 1722667 , 1797581 , 1872461 , 1947359 , 2022253
+      , 2246953 , 2396759 , 2546543 , 2696363 , 2846161 , 2995973 , 3145739
+      , 3295541 , 3445357 , 3595117 , 3744941 , 3894707 , 4044503
+      , 4493921 , 4793501 , 5093089 , 5392679 , 5692279 , 5991883 , 6291469
+      , 6591059 , 6890641 , 7190243 , 7489829 , 7789447 , 8089033
+      , 8987807 , 9586981 , 10186177 , 10785371 , 11384539 , 11983729
+      , 12582917 , 13182109 , 13781291 , 14380469 , 14979667 , 15578861
+      , 16178053 , 17895707 , 19014187 , 20132683 , 21251141 , 22369661
+      , 23488103 , 24606583 , 25725083 , 26843549 , 27962027 , 29080529
+      , 30198989 , 31317469 , 32435981 , 35791397 , 38028379 , 40265327
+      , 42502283 , 44739259 , 46976221 , 49213237 , 51450131 , 53687099
+      , 55924061 , 58161041 , 60397993 , 62634959 , 64871921
+      , 71582857 , 76056727 , 80530643 , 85004567 , 89478503 , 93952427
+      , 98426347 , 102900263 , 107374217 , 111848111 , 116322053 , 120795971
+      , 125269877 , 129743807 , 143165587 , 152113427 , 161061283 , 170009141
+      , 178956983 , 187904819 , 196852693 , 205800547 , 214748383 , 223696237
+      , 232644089 , 241591943 , 250539763 , 259487603 , 268435399
+  };
+
+  const uint32_t num_primes = sizeof(primes)/sizeof(uint32_t);
+
+  uint32_t hsize = primes[num_primes-1] ;
+  for (uint32_t i = 0; i < num_primes; ++i) {
+    if (size <= primes[i]) {
+      hsize = primes[i];
+      break;
+    }
+  }
+  return hsize;
+}
+
+}} // namespace Kokkos::Impl
+
diff --git a/lib/kokkos/containers/src/impl/Kokkos_UnorderedMap_impl.hpp b/lib/kokkos/containers/src/impl/Kokkos_UnorderedMap_impl.hpp
new file mode 100644
index 0000000000..b788c966e9
--- /dev/null
+++ b/lib/kokkos/containers/src/impl/Kokkos_UnorderedMap_impl.hpp
@@ -0,0 +1,297 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_UNORDERED_MAP_IMPL_HPP
+#define KOKKOS_UNORDERED_MAP_IMPL_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+#include <stdint.h>
+
+#include <cstdio>
+#include <climits>
+#include <iostream>
+#include <iomanip>
+
+namespace Kokkos { namespace Impl {
+
+uint32_t find_hash_size( uint32_t size );
+
+template <typename Map>
+struct UnorderedMapRehash
+{
+  typedef Map map_type;
+  typedef typename map_type::const_map_type const_map_type;
+  typedef typename map_type::execution_space execution_space;
+  typedef typename map_type::size_type size_type;
+
+  map_type       m_dst;
+  const_map_type m_src;
+
+  UnorderedMapRehash( map_type const& dst, const_map_type const& src)
+    : m_dst(dst), m_src(src)
+  {}
+
+  void apply() const
+  {
+    parallel_for(m_src.capacity(), *this);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(size_type i) const
+  {
+    if ( m_src.valid_at(i) )
+      m_dst.insert(m_src.key_at(i), m_src.value_at(i));
+  }
+
+};
+
+template <typename UMap>
+struct UnorderedMapErase
+{
+  typedef UMap map_type;
+  typedef typename map_type::execution_space execution_space;
+  typedef typename map_type::size_type size_type;
+  typedef typename map_type::key_type key_type;
+  typedef typename map_type::impl_value_type value_type;
+
+  map_type m_map;
+
+  UnorderedMapErase( map_type const& map)
+    : m_map(map)
+  {}
+
+  void apply() const
+  {
+    parallel_for(m_map.m_hash_lists.dimension_0(), *this);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const
+  {
+    const size_type invalid_index = map_type::invalid_index;
+
+    size_type curr = m_map.m_hash_lists(i);
+    size_type next = invalid_index;
+
+    // remove erased head of the linked-list
+    while (curr != invalid_index && !m_map.valid_at(curr)) {
+      next = m_map.m_next_index[curr];
+      m_map.m_next_index[curr] = invalid_index;
+      m_map.m_keys[curr] = key_type();
+      if (m_map.is_set) m_map.m_values[curr] = value_type();
+      curr = next;
+      m_map.m_hash_lists(i) = next;
+    }
+
+    // if the list is non-empty and the head is valid
+    if (curr != invalid_index && m_map.valid_at(curr) ) {
+      size_type prev = curr;
+      curr = m_map.m_next_index[prev];
+
+      while (curr != invalid_index) {
+        next = m_map.m_next_index[curr];
+        if (m_map.valid_at(curr)) {
+          prev = curr;
+        }
+        else {
+          // remove curr from list
+          m_map.m_next_index[prev] = next;
+          m_map.m_next_index[curr] = invalid_index;
+          m_map.m_keys[curr] = key_type();
+          if (map_type::is_set) m_map.m_values[curr] = value_type();
+        }
+        curr = next;
+      }
+    }
+  }
+};
+
+template <typename UMap>
+struct UnorderedMapHistogram
+{
+  typedef UMap map_type;
+  typedef typename map_type::execution_space execution_space;
+  typedef typename map_type::size_type size_type;
+
+  typedef View<int[100], execution_space> histogram_view;
+  typedef typename histogram_view::HostMirror host_histogram_view;
+
+  map_type m_map;
+  histogram_view m_length;
+  histogram_view m_distance;
+  histogram_view m_block_distance;
+
+  UnorderedMapHistogram( map_type const& map)
+    : m_map(map)
+    , m_length("UnorderedMap Histogram")
+    , m_distance("UnorderedMap Histogram")
+    , m_block_distance("UnorderedMap Histogram")
+  {}
+
+  void calculate()
+  {
+    parallel_for(m_map.m_hash_lists.dimension_0(), *this);
+  }
+
+  void clear()
+  {
+    Kokkos::deep_copy(m_length, 0);
+    Kokkos::deep_copy(m_distance, 0);
+    Kokkos::deep_copy(m_block_distance, 0);
+  }
+
+  void print_length(std::ostream &out)
+  {
+    host_histogram_view host_copy = create_mirror_view(m_length);
+    Kokkos::deep_copy(host_copy, m_length);
+
+    for (int i=0, size = host_copy.dimension_0(); i<size; ++i)
+    {
+      out << host_copy[i] << " , ";
+    }
+    out << "\b\b\b   " << std::endl;
+  }
+
+  void print_distance(std::ostream &out)
+  {
+    host_histogram_view host_copy = create_mirror_view(m_distance);
+    Kokkos::deep_copy(host_copy, m_distance);
+
+    for (int i=0, size = host_copy.dimension_0(); i<size; ++i)
+    {
+      out << host_copy[i] << " , ";
+    }
+    out << "\b\b\b   " << std::endl;
+  }
+
+  void print_block_distance(std::ostream &out)
+  {
+    host_histogram_view host_copy = create_mirror_view(m_block_distance);
+    Kokkos::deep_copy(host_copy, m_block_distance);
+
+    for (int i=0, size = host_copy.dimension_0(); i<size; ++i)
+    {
+      out << host_copy[i] << " , ";
+    }
+    out << "\b\b\b   " << std::endl;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const
+  {
+    const size_type invalid_index = map_type::invalid_index;
+
+    uint32_t length = 0;
+    size_type min_index = ~0u, max_index = 0;
+    for (size_type curr = m_map.m_hash_lists(i); curr != invalid_index; curr = m_map.m_next_index[curr]) {
+      ++length;
+      min_index = (curr < min_index) ? curr : min_index;
+      max_index = (max_index < curr) ? curr : max_index;
+    }
+
+    size_type distance = (0u < length) ? max_index - min_index : 0u;
+    size_type blocks = (0u < length) ? max_index/32u - min_index/32u : 0u;
+
+    // normalize data
+    length   = length   < 100u ? length   : 99u;
+    distance = distance < 100u ? distance : 99u;
+    blocks   = blocks   < 100u ? blocks   : 99u;
+
+    if (0u < length)
+    {
+      atomic_fetch_add( &m_length(length), 1);
+      atomic_fetch_add( &m_distance(distance), 1);
+      atomic_fetch_add( &m_block_distance(blocks), 1);
+    }
+  }
+};
+
+template <typename UMap>
+struct UnorderedMapPrint
+{
+  typedef UMap map_type;
+  typedef typename map_type::execution_space execution_space;
+  typedef typename map_type::size_type size_type;
+
+  map_type m_map;
+
+  UnorderedMapPrint( map_type const& map)
+    : m_map(map)
+  {}
+
+  void apply()
+  {
+    parallel_for(m_map.m_hash_lists.dimension_0(), *this);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const
+  {
+    const size_type invalid_index = map_type::invalid_index;
+
+    uint32_t list = m_map.m_hash_lists(i);
+    for (size_type curr = list, ii=0; curr != invalid_index; curr = m_map.m_next_index[curr], ++ii) {
+      printf("%d[%d]: %d->%d\n", list, ii, m_map.key_at(curr), m_map.value_at(curr));
+    }
+  }
+};
+
+template <typename DKey, typename DValue, typename SKey, typename SValue>
+struct UnorderedMapCanAssign : public false_ {};
+
+template <typename Key, typename Value>
+struct UnorderedMapCanAssign<Key,Value,Key,Value> : public true_ {};
+
+template <typename Key, typename Value>
+struct UnorderedMapCanAssign<const Key,Value,Key,Value> : public true_ {};
+
+template <typename Key, typename Value>
+struct UnorderedMapCanAssign<const Key,const Value,Key,Value> : public true_ {};
+
+template <typename Key, typename Value>
+struct UnorderedMapCanAssign<const Key,const Value,const Key,Value> : public true_ {};
+
+
+}} //Kokkos::Impl
+
+#endif // KOKKOS_UNORDERED_MAP_IMPL_HPP
diff --git a/lib/kokkos/containers/unit_tests/CMakeLists.txt b/lib/kokkos/containers/unit_tests/CMakeLists.txt
new file mode 100644
index 0000000000..7fff0f835b
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/CMakeLists.txt
@@ -0,0 +1,40 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../src )
+
+SET(SOURCES
+  UnitTestMain.cpp 
+  TestCuda.cpp
+  )
+
+SET(LIBRARIES kokkoscore)
+
+IF(Kokkos_ENABLE_Pthread)
+  LIST( APPEND SOURCES
+    TestThreads.cpp
+  )
+ENDIF()
+
+IF(Kokkos_ENABLE_Serial)
+  LIST( APPEND SOURCES
+    TestSerial.cpp
+  )
+ENDIF()
+
+IF(Kokkos_ENABLE_OpenMP)
+  LIST( APPEND SOURCES
+    TestOpenMP.cpp
+  )
+ENDIF()
+
+
+TRIBITS_ADD_EXECUTABLE_AND_TEST(
+  UnitTest
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  NUM_MPI_PROCS 1
+  FAIL_REGULAR_EXPRESSION "  FAILED  "
+  TESTONLYLIBS kokkos_gtest
+  )
+  
diff --git a/lib/kokkos/containers/unit_tests/Makefile b/lib/kokkos/containers/unit_tests/Makefile
new file mode 100644
index 0000000000..48e3ff61d0
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/Makefile
@@ -0,0 +1,92 @@
+KOKKOS_PATH = ../..
+
+GTEST_PATH = ../../TPL/gtest
+
+vpath %.cpp ${KOKKOS_PATH}/containers/unit_tests
+
+default: build_all
+	echo "End Build"
+
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?= -lpthread
+endif
+
+KOKKOS_CXXFLAGS += -I$(GTEST_PATH) -I${KOKKOS_PATH}/containers/unit_tests
+
+TEST_TARGETS = 
+TARGETS = 
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	OBJ_CUDA = TestCuda.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosContainers_UnitTest_Cuda
+	TEST_TARGETS += test-cuda
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+	OBJ_THREADS = TestThreads.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosContainers_UnitTest_Threads
+	TEST_TARGETS += test-threads
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+	OBJ_OPENMP = TestOpenMP.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosContainers_UnitTest_OpenMP
+	TEST_TARGETS += test-openmp
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_SERIAL), 1)
+	OBJ_SERIAL = TestSerial.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosContainers_UnitTest_Serial
+	TEST_TARGETS += test-serial
+endif
+
+KokkosContainers_UnitTest_Cuda: $(OBJ_CUDA) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_CUDA) $(KOKKOS_LIBS) $(LIB) -o KokkosContainers_UnitTest_Cuda
+
+KokkosContainers_UnitTest_Threads: $(OBJ_THREADS) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_THREADS) $(KOKKOS_LIBS) $(LIB) -o KokkosContainers_UnitTest_Threads
+
+KokkosContainers_UnitTest_OpenMP: $(OBJ_OPENMP) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_OPENMP) $(KOKKOS_LIBS) $(LIB) -o KokkosContainers_UnitTest_OpenMP
+
+KokkosContainers_UnitTest_Serial: $(OBJ_SERIAL) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_SERIAL) $(KOKKOS_LIBS) $(LIB) -o KokkosContainers_UnitTest_Serial
+
+test-cuda: KokkosContainers_UnitTest_Cuda
+	./KokkosContainers_UnitTest_Cuda
+
+test-threads: KokkosContainers_UnitTest_Threads
+	./KokkosContainers_UnitTest_Threads
+
+test-openmp: KokkosContainers_UnitTest_OpenMP
+	./KokkosContainers_UnitTest_OpenMP
+
+test-serial: KokkosContainers_UnitTest_Serial
+	./KokkosContainers_UnitTest_Serial
+
+build_all: $(TARGETS)
+
+test: $(TEST_TARGETS)
+
+clean: kokkos-clean 
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
+gtest-all.o:$(GTEST_PATH)/gtest/gtest-all.cc 
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $(GTEST_PATH)/gtest/gtest-all.cc
+
diff --git a/lib/kokkos/containers/unit_tests/TestBitset.hpp b/lib/kokkos/containers/unit_tests/TestBitset.hpp
new file mode 100644
index 0000000000..76fb30edcb
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestBitset.hpp
@@ -0,0 +1,285 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_TEST_BITSET_HPP
+#define KOKKOS_TEST_BITSET_HPP
+
+#include <gtest/gtest.h>
+#include <iostream>
+
+
+namespace Test {
+
+namespace Impl {
+
+template <typename Bitset, bool Set>
+struct TestBitset
+{
+  typedef Bitset bitset_type;
+  typedef typename bitset_type::execution_space execution_space;
+  typedef uint32_t value_type;
+
+  bitset_type m_bitset;
+
+  TestBitset( bitset_type const& bitset)
+    : m_bitset(bitset)
+  {}
+
+  unsigned testit(unsigned collisions)
+  {
+    execution_space::fence();
+
+    unsigned count = 0;
+    Kokkos::parallel_reduce( m_bitset.size()*collisions, *this, count);
+    return count;
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & v ) const { v = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst, const volatile value_type & src ) const
+  { dst += src; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(uint32_t i, value_type & v) const
+  {
+    i = i % m_bitset.size();
+    if (Set) {
+      if (m_bitset.set(i)) {
+        if (m_bitset.test(i)) ++v;
+      }
+    }
+    else {
+      if (m_bitset.reset(i)) {
+        if (!m_bitset.test(i)) ++v;
+      }
+    }
+  }
+
+};
+
+template <typename Bitset>
+struct TestBitsetTest
+{
+  typedef Bitset bitset_type;
+  typedef typename bitset_type::execution_space execution_space;
+  typedef uint32_t value_type;
+
+  bitset_type m_bitset;
+
+  TestBitsetTest( bitset_type const& bitset)
+    : m_bitset(bitset)
+  {}
+
+  unsigned testit()
+  {
+    execution_space::fence();
+
+    unsigned count = 0;
+    Kokkos::parallel_reduce( m_bitset.size(), *this, count);
+    return count;
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & v ) const { v = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst, const volatile value_type & src ) const
+  { dst += src; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(uint32_t i, value_type & v) const
+  {
+    if (m_bitset.test( i )) ++v;
+  }
+};
+
+template <typename Bitset, bool Set>
+struct TestBitsetAny
+{
+  typedef Bitset bitset_type;
+  typedef typename bitset_type::execution_space execution_space;
+  typedef uint32_t value_type;
+
+  bitset_type m_bitset;
+
+  TestBitsetAny( bitset_type const& bitset)
+    : m_bitset(bitset)
+  {}
+
+  unsigned testit()
+  {
+    execution_space::fence();
+
+    unsigned count = 0;
+    Kokkos::parallel_reduce( m_bitset.size(), *this, count);
+    return count;
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & v ) const { v = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst, const volatile value_type & src ) const
+  { dst += src; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(uint32_t i, value_type & v) const
+  {
+    bool result = false;
+    unsigned attempts = 0;
+    uint32_t hint = (i >> 4) << 4;
+    while (attempts < m_bitset.max_hint()) {
+      if (Set) {
+        Kokkos::tie(result, hint) = m_bitset.find_any_unset_near(hint, i);
+        if (result && m_bitset.set(hint)) {
+          ++v;
+          break;
+        }
+        else if (!result) {
+          ++attempts;
+        }
+      }
+      else {
+        Kokkos::tie(result, hint) = m_bitset.find_any_set_near(hint, i);
+        if (result && m_bitset.reset(hint)) {
+          ++v;
+          break;
+        }
+        else if (!result) {
+          ++attempts;
+        }
+      }
+    }
+  }
+
+};
+} // namespace Impl
+
+
+
+template <typename Device>
+void test_bitset()
+{
+  typedef Kokkos::Bitset< Device > bitset_type;
+  typedef Kokkos::ConstBitset< Device > const_bitset_type;
+
+  //unsigned test_sizes[] = { 0u, 1000u, 1u<<14, 1u<<16, 10000001 };
+  unsigned test_sizes[] = { 1000u, 1u<<14, 1u<<16, 10000001 };
+
+  for (int i=0, end = sizeof(test_sizes)/sizeof(unsigned); i<end; ++i) {
+
+    //std::cout << "Bitset " << test_sizes[i] << std::endl;
+
+    bitset_type bitset(test_sizes[i]);
+
+    //std::cout << "  Check inital count " << std::endl;
+    // nothing should be set
+    {
+      Impl::TestBitsetTest< bitset_type > f(bitset);
+      uint32_t count = f.testit();
+      EXPECT_EQ(0u, count);
+      EXPECT_EQ(count, bitset.count());
+    }
+
+    //std::cout << "  Check set() " << std::endl;
+    bitset.set();
+    // everything should be set
+    {
+      Impl::TestBitsetTest< const_bitset_type > f(bitset);
+      uint32_t count = f.testit();
+      EXPECT_EQ(bitset.size(), count);
+      EXPECT_EQ(count, bitset.count());
+    }
+
+    //std::cout << "  Check reset() " << std::endl;
+    bitset.reset();
+    EXPECT_EQ(0u, bitset.count());
+
+    //std::cout << "  Check set(i) " << std::endl;
+    // test setting bits
+    {
+      Impl::TestBitset< bitset_type, true > f(bitset);
+      uint32_t count = f.testit(10u);
+      EXPECT_EQ( bitset.size(), bitset.count());
+      EXPECT_EQ( bitset.size(), count );
+    }
+
+    //std::cout << "  Check reset(i) " << std::endl;
+    // test resetting bits
+    {
+      Impl::TestBitset< bitset_type, false > f(bitset);
+      uint32_t count = f.testit(10u);
+      EXPECT_EQ( bitset.size(), count);
+      EXPECT_EQ( 0u, bitset.count() );
+    }
+
+
+    //std::cout << "  Check find_any_set(i) " << std::endl;
+    // test setting any bits
+    {
+      Impl::TestBitsetAny< bitset_type, true > f(bitset);
+      uint32_t count = f.testit();
+      EXPECT_EQ( bitset.size(), bitset.count());
+      EXPECT_EQ( bitset.size(), count );
+    }
+
+    //std::cout << "  Check find_any_unset(i) " << std::endl;
+    // test resetting any bits
+    {
+      Impl::TestBitsetAny< bitset_type, false > f(bitset);
+      uint32_t count = f.testit();
+      EXPECT_EQ( bitset.size(), count);
+      EXPECT_EQ( 0u, bitset.count() );
+    }
+
+  }
+
+}
+
+} // namespace Test
+
+#endif //KOKKOS_TEST_BITSET_HPP
+
diff --git a/lib/kokkos/containers/unit_tests/TestComplex.hpp b/lib/kokkos/containers/unit_tests/TestComplex.hpp
new file mode 100644
index 0000000000..94c04b61f4
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestComplex.hpp
@@ -0,0 +1,263 @@
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+
+
+#ifndef KOKKOS_TEST_COMPLEX_HPP
+#define KOKKOS_TEST_COMPLEX_HPP
+
+#include <Kokkos_Complex.hpp>
+#include <gtest/gtest.h>
+#include <iostream>
+
+namespace Test {
+
+namespace Impl {
+  template <typename RealType>
+  void testComplexConstructors () {
+    typedef Kokkos::complex<RealType> complex_type;
+
+    complex_type z1;
+    complex_type z2 (0.0, 0.0);
+    complex_type z3 (1.0, 0.0);
+    complex_type z4 (0.0, 1.0);
+    complex_type z5 (-1.0, -2.0);
+
+    ASSERT_TRUE( z1 == z2 );
+    ASSERT_TRUE( z1 != z3 );
+    ASSERT_TRUE( z1 != z4 );
+    ASSERT_TRUE( z1 != z5 );
+
+    ASSERT_TRUE( z2 != z3 );
+    ASSERT_TRUE( z2 != z4 );
+    ASSERT_TRUE( z2 != z5 );
+
+    ASSERT_TRUE( z3 != z4 );
+    ASSERT_TRUE( z3 != z5 );
+
+    complex_type z6 (-1.0, -2.0);
+    ASSERT_TRUE( z5 == z6 );
+
+    // Make sure that complex has value semantics, in particular, that
+    // equality tests use values and not pointers, so that
+    // reassignment actually changes the value.
+    z1 = complex_type (-3.0, -4.0);
+    ASSERT_TRUE( z1.real () == -3.0 );
+    ASSERT_TRUE( z1.imag () == -4.0 );
+    ASSERT_TRUE( z1 != z2 );
+
+    complex_type z7 (1.0);
+    ASSERT_TRUE( z3 == z7 );
+    ASSERT_TRUE( z7 == 1.0 );
+    ASSERT_TRUE( z7 != -1.0 );
+
+    z7 = complex_type (5.0);
+    ASSERT_TRUE( z7.real () == 5.0 );
+    ASSERT_TRUE( z7.imag () == 0.0 );
+  }
+
+  template <typename RealType>
+  void testPlus () {
+    typedef Kokkos::complex<RealType> complex_type;
+
+    complex_type z1 (1.0, -1.0);
+    complex_type z2 (-1.0, 1.0);
+    complex_type z3 = z1 + z2;
+    ASSERT_TRUE( z3 == complex_type (0.0, 0.0) );
+  }
+
+  template <typename RealType>
+  void testMinus () {
+    typedef Kokkos::complex<RealType> complex_type;
+
+    // Test binary minus.
+    complex_type z1 (1.0, -1.0);
+    complex_type z2 (-1.0, 1.0);
+    complex_type z3 = z1 - z2;
+    ASSERT_TRUE( z3 == complex_type (2.0, -2.0) );
+
+    // Test unary minus.
+    complex_type z4 (3.0, -4.0);
+    ASSERT_TRUE( -z1 == complex_type (-3.0, 4.0) );
+  }
+
+  template <typename RealType>
+  void testTimes () {
+    typedef Kokkos::complex<RealType> complex_type;
+
+    complex_type z1 (1.0, -1.0);
+    complex_type z2 (-1.0, 1.0);
+    complex_type z3 = z1 * z2;
+    ASSERT_TRUE( z3 == complex_type (0.0, 2.0) );
+
+    // Make sure that std::complex * Kokkos::complex works too.
+    std::complex<RealType> z4 (-1.0, 1.0);
+    complex_type z5 = z4 * z1;
+    ASSERT_TRUE( z5 == complex_type (0.0, 2.0) );
+  }
+
+  template <typename RealType>
+  void testDivide () {
+    typedef Kokkos::complex<RealType> complex_type;
+
+    // Test division of a complex number by a real number.
+    complex_type z1 (1.0, -1.0);
+    complex_type z2 (1.0 / 2.0, -1.0 / 2.0);
+    ASSERT_TRUE( z1 / 2.0 == z2 );
+
+    // (-1+2i)/(1-i) == ((-1+2i)(1+i)) / ((1-i)(1+i))
+    // (-1+2i)(1+i) == -3 + i
+    complex_type z3 (-1.0, 2.0);
+    complex_type z4 (1.0, -1.0);
+    complex_type z5 (-3.0, 1.0);
+    ASSERT_TRUE(z3 * Kokkos::conj (z4) == z5 );
+
+    // Test division of a complex number by a complex number.
+    // This assumes that RealType is a floating-point type.
+    complex_type z6 (Kokkos::real (z5) / 2.0,
+                     Kokkos::imag (z5) / 2.0);
+
+    complex_type z7 = z3 / z4;
+    ASSERT_TRUE( z7 == z6 );
+  }
+
+  template <typename RealType>
+  void testOutsideKernel () {
+    testComplexConstructors<RealType> ();
+    testPlus<RealType> ();
+    testTimes<RealType> ();
+    testDivide<RealType> ();
+  }
+
+
+  template<typename RealType, typename Device>
+  void testCreateView () {
+    typedef Kokkos::complex<RealType> complex_type;
+    Kokkos::View<complex_type*, Device> x ("x", 10);
+    ASSERT_TRUE( x.dimension_0 () == 10 );
+
+    // Test that View assignment works.
+    Kokkos::View<complex_type*, Device> x_nonconst = x;
+    Kokkos::View<const complex_type*, Device> x_const = x;
+  }
+
+  template<typename RealType, typename Device>
+  class Fill {
+  public:
+    typedef typename Device::execution_space execution_space;
+
+    typedef Kokkos::View<Kokkos::complex<RealType>*, Device> view_type;
+    typedef typename view_type::size_type size_type;
+
+    KOKKOS_INLINE_FUNCTION
+    void operator () (const size_type i) const {
+      x_(i) = val_;
+    }
+
+    Fill (const view_type& x, const Kokkos::complex<RealType>& val) :
+      x_ (x), val_ (val)
+    {}
+
+  private:
+    view_type x_;
+    const Kokkos::complex<RealType> val_;
+  };
+
+  template<typename RealType, typename Device>
+  class Sum {
+  public:
+    typedef typename Device::execution_space execution_space;
+
+    typedef Kokkos::View<const Kokkos::complex<RealType>*, Device> view_type;
+    typedef typename view_type::size_type size_type;
+    typedef Kokkos::complex<RealType> value_type;
+
+    KOKKOS_INLINE_FUNCTION
+    void operator () (const size_type i, Kokkos::complex<RealType>& sum) const {
+      sum += x_(i);
+    }
+
+    Sum (const view_type& x) : x_ (x) {}
+
+  private:
+    view_type x_;
+  };
+
+  template<typename RealType, typename Device>
+  void testInsideKernel () {
+    typedef Kokkos::complex<RealType> complex_type;
+    typedef Kokkos::View<complex_type*, Device> view_type;
+    typedef typename view_type::size_type size_type;
+
+    const size_type N = 1000;
+    view_type x ("x", N);
+    ASSERT_TRUE( x.dimension_0 () == N );
+
+    // Kokkos::parallel_reduce (N, [=] (const size_type i, complex_type& result) {
+    //     result += x[i];
+    //   });
+
+    Kokkos::parallel_for (N, Fill<RealType, Device> (x, complex_type (1.0, -1.0)));
+
+    complex_type sum;
+    Kokkos::parallel_reduce (N, Sum<RealType, Device> (x), sum);
+
+    ASSERT_TRUE( sum.real () == 1000.0 && sum.imag () == -1000.0 );
+  }
+} // namespace Impl
+
+
+template <typename Device>
+void testComplex ()
+{
+  Impl::testOutsideKernel<float> ();
+  Impl::testOutsideKernel<double> ();
+
+  Impl::testCreateView<float, Device> ();
+  Impl::testCreateView<double, Device> ();
+
+  Impl::testInsideKernel<float, Device> ();
+  Impl::testInsideKernel<double, Device> ();
+}
+
+
+} // namespace Test
+
+#endif // KOKKOS_TEST_COMPLEX_HPP
diff --git a/lib/kokkos/containers/unit_tests/TestCuda.cpp b/lib/kokkos/containers/unit_tests/TestCuda.cpp
new file mode 100644
index 0000000000..e30160b24e
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestCuda.cpp
@@ -0,0 +1,227 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <stdint.h>
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#include <Kokkos_Bitset.hpp>
+#include <Kokkos_UnorderedMap.hpp>
+#include <Kokkos_Vector.hpp>
+
+#include <TestBitset.hpp>
+#include <TestUnorderedMap.hpp>
+#include <TestStaticCrsGraph.hpp>
+#include <TestVector.hpp>
+#include <TestDualView.hpp>
+#include <TestDynamicView.hpp>
+#include <TestSegmentedView.hpp>
+
+#include <Kokkos_DynRankView.hpp>
+#include <TestDynViewAPI.hpp>
+
+//----------------------------------------------------------------------------
+
+
+#ifdef KOKKOS_HAVE_CUDA
+
+namespace Test {
+
+class cuda : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+    Kokkos::HostSpace::execution_space::initialize();
+    Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice(0) );
+  }
+  static void TearDownTestCase()
+  {
+    Kokkos::Cuda::finalize();
+    Kokkos::HostSpace::execution_space::finalize();
+  }
+};
+
+TEST_F( cuda , dyn_view_api) {
+  TestDynViewAPI< double , Kokkos::Cuda >();
+}
+
+TEST_F( cuda , staticcrsgraph )
+{
+  TestStaticCrsGraph::run_test_graph< Kokkos::Cuda >();
+  TestStaticCrsGraph::run_test_graph2< Kokkos::Cuda >();
+}
+
+
+void cuda_test_insert_close(  uint32_t num_nodes
+                            , uint32_t num_inserts
+                            , uint32_t num_duplicates
+                           )
+{
+  test_insert< Kokkos::Cuda >( num_nodes, num_inserts, num_duplicates, true);
+}
+
+void cuda_test_insert_far(  uint32_t num_nodes
+                          , uint32_t num_inserts
+                          , uint32_t num_duplicates
+                         )
+{
+  test_insert< Kokkos::Cuda >( num_nodes, num_inserts, num_duplicates, false);
+}
+
+void cuda_test_failed_insert(  uint32_t num_nodes )
+{
+  test_failed_insert< Kokkos::Cuda >( num_nodes );
+}
+
+void cuda_test_deep_copy(  uint32_t num_nodes )
+{
+  test_deep_copy< Kokkos::Cuda >( num_nodes );
+}
+
+void cuda_test_vector_combinations(unsigned int size)
+{
+  test_vector_combinations<int,Kokkos::Cuda>(size);
+}
+
+void cuda_test_dualview_combinations(unsigned int size)
+{
+  test_dualview_combinations<int,Kokkos::Cuda>(size);
+}
+
+void cuda_test_segmented_view(unsigned int size)
+{
+  test_segmented_view<double,Kokkos::Cuda>(size);
+}
+
+void cuda_test_bitset()
+{
+  test_bitset<Kokkos::Cuda>();
+}
+
+
+
+/*TEST_F( cuda, bitset )
+{
+  cuda_test_bitset();
+}*/
+
+#define CUDA_INSERT_TEST( name, num_nodes, num_inserts, num_duplicates, repeat )                                \
+  TEST_F( cuda, UnorderedMap_insert_##name##_##num_nodes##_##num_inserts##_##num_duplicates##_##repeat##x) {   \
+    for (int i=0; i<repeat; ++i)                                                                                \
+      cuda_test_insert_##name(num_nodes,num_inserts,num_duplicates);                                            \
+  }
+
+#define CUDA_FAILED_INSERT_TEST( num_nodes, repeat )                           \
+  TEST_F( cuda, UnorderedMap_failed_insert_##num_nodes##_##repeat##x) {       \
+    for (int i=0; i<repeat; ++i)                                               \
+      cuda_test_failed_insert(num_nodes);                                      \
+  }
+
+#define CUDA_ASSIGNEMENT_TEST( num_nodes, repeat )                               \
+  TEST_F( cuda, UnorderedMap_assignment_operators_##num_nodes##_##repeat##x) {  \
+    for (int i=0; i<repeat; ++i)                                                 \
+      cuda_test_assignment_operators(num_nodes);                                 \
+  }
+
+#define CUDA_DEEP_COPY( num_nodes, repeat )                             \
+  TEST_F( cuda, UnorderedMap_deep_copy##num_nodes##_##repeat##x) {       \
+    for (int i=0; i<repeat; ++i)                                               \
+      cuda_test_deep_copy(num_nodes);                     \
+  }
+
+#define CUDA_VECTOR_COMBINE_TEST( size )                             \
+  TEST_F( cuda, vector_combination##size##x) {       \
+      cuda_test_vector_combinations(size);                     \
+  }
+
+#define CUDA_DUALVIEW_COMBINE_TEST( size )                             \
+  TEST_F( cuda, dualview_combination##size##x) {       \
+      cuda_test_dualview_combinations(size);                     \
+  }
+
+#define CUDA_SEGMENTEDVIEW_TEST( size )                             \
+  TEST_F( cuda, segmentedview_##size##x) {       \
+      cuda_test_segmented_view(size);                     \
+  }
+
+CUDA_DUALVIEW_COMBINE_TEST( 10 )
+CUDA_VECTOR_COMBINE_TEST( 10 )
+CUDA_VECTOR_COMBINE_TEST( 3057 )
+
+
+CUDA_INSERT_TEST(close,               100000, 90000, 100, 500)
+CUDA_INSERT_TEST(far,                 100000, 90000, 100, 500)
+CUDA_DEEP_COPY( 10000, 1 )
+CUDA_FAILED_INSERT_TEST( 10000, 1000 )
+CUDA_SEGMENTEDVIEW_TEST( 200 )
+
+
+#undef CUDA_INSERT_TEST
+#undef CUDA_FAILED_INSERT_TEST
+#undef CUDA_ASSIGNEMENT_TEST
+#undef CUDA_DEEP_COPY
+#undef CUDA_VECTOR_COMBINE_TEST
+#undef CUDA_DUALVIEW_COMBINE_TEST
+#undef CUDA_SEGMENTEDVIEW_TEST
+
+
+TEST_F( cuda , dynamic_view )
+{
+  typedef TestDynamicView< double , Kokkos::CudaUVMSpace >
+    TestDynView ;
+
+  for ( int i = 0 ; i < 10 ; ++i ) {
+    TestDynView::run( 100000 + 100 * i );
+  }
+}
+
+
+}
+
+#endif  /* #ifdef KOKKOS_HAVE_CUDA */
+
diff --git a/lib/kokkos/containers/unit_tests/TestDualView.hpp b/lib/kokkos/containers/unit_tests/TestDualView.hpp
new file mode 100644
index 0000000000..e72c69f7d4
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestDualView.hpp
@@ -0,0 +1,121 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_TEST_DUALVIEW_HPP
+#define KOKKOS_TEST_DUALVIEW_HPP
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+#include <impl/Kokkos_Timer.hpp>
+
+namespace Test {
+
+namespace Impl {
+
+  template <typename Scalar, class Device>
+  struct test_dualview_combinations
+  {
+    typedef test_dualview_combinations<Scalar,Device> self_type;
+
+    typedef Scalar scalar_type;
+    typedef Device execution_space;
+
+    Scalar reference;
+    Scalar result;
+
+    template <typename ViewType>
+    Scalar run_me(unsigned int n,unsigned int m){
+      if(n<10) n = 10;
+      if(m<3) m = 3;
+      ViewType a("A",n,m);
+
+      Kokkos::deep_copy( a.d_view , 1 );
+
+      a.template modify<typename ViewType::execution_space>();
+      a.template sync<typename ViewType::host_mirror_space>();
+
+      a.h_view(5,1) = 3;
+      a.h_view(6,1) = 4;
+      a.h_view(7,2) = 5;
+      a.template modify<typename ViewType::host_mirror_space>();
+      ViewType b = Kokkos::subview(a,std::pair<unsigned int, unsigned int>(6,9),std::pair<unsigned int, unsigned int>(0,1));
+      a.template sync<typename ViewType::execution_space>();
+      b.template modify<typename ViewType::execution_space>();
+
+      Kokkos::deep_copy( b.d_view , 2 );
+
+      a.template sync<typename ViewType::host_mirror_space>();
+      Scalar count = 0;
+      for(unsigned int i = 0; i<a.d_view.dimension_0(); i++)
+        for(unsigned int j = 0; j<a.d_view.dimension_1(); j++)
+          count += a.h_view(i,j);
+      return count -  a.d_view.dimension_0()*a.d_view.dimension_1()-2-4-3*2;
+    }
+
+
+    test_dualview_combinations(unsigned int size)
+    {
+      result = run_me< Kokkos::DualView<Scalar**,Kokkos::LayoutLeft,Device> >(size,3);
+    }
+
+   };
+
+} // namespace Impl
+
+
+
+
+template <typename Scalar, typename Device>
+void test_dualview_combinations(unsigned int size)
+{
+  Impl::test_dualview_combinations<Scalar,Device> test(size);
+  ASSERT_EQ( test.result,0);
+
+}
+
+
+} // namespace Test
+
+#endif //KOKKOS_TEST_UNORDERED_MAP_HPP
diff --git a/lib/kokkos/containers/unit_tests/TestDynViewAPI.hpp b/lib/kokkos/containers/unit_tests/TestDynViewAPI.hpp
new file mode 100644
index 0000000000..e71ccc0091
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestDynViewAPI.hpp
@@ -0,0 +1,1559 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+/*--------------------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+template< class T , class ... P >
+size_t allocation_count( const Kokkos::Experimental::DynRankView<T,P...> & view )
+{
+  const size_t card  = view.size();
+  const size_t alloc = view.span();
+
+  return card <= alloc ? alloc : 0 ;
+}
+
+/*--------------------------------------------------------------------------*/
+
+template< typename T, class DeviceType>
+struct TestViewOperator
+{
+  typedef DeviceType  execution_space ;
+
+  static const unsigned N = 100 ;
+  static const unsigned D = 3 ;
+
+  typedef Kokkos::Experimental::DynRankView< T , execution_space > view_type ;
+
+  const view_type v1 ;
+  const view_type v2 ;
+
+  TestViewOperator()
+    : v1( "v1" , N , D )
+    , v2( "v2" , N , D )
+    {}
+
+  static void testit()
+  {
+    Kokkos::parallel_for( N , TestViewOperator() );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned i ) const
+  {
+    const unsigned X = 0 ;
+    const unsigned Y = 1 ;
+    const unsigned Z = 2 ;
+
+    v2(i,X) = v1(i,X);
+    v2(i,Y) = v1(i,Y);
+    v2(i,Z) = v1(i,Z);
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< class DataType ,
+          class DeviceType ,
+          unsigned Rank >
+struct TestViewOperator_LeftAndRight ;
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 7 >
+{
+  typedef DeviceType                          execution_space ;
+  typedef typename execution_space::memory_space  memory_space ;
+  typedef typename execution_space::size_type     size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  left_view    left ;
+  right_view   right ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, unsigned N5, unsigned N6 )
+    : left(  "left" , N0, N1, N2, N3, N4, N5, N6 )
+    , right( "right" , N0, N1, N2, N3, N4, N5, N6 )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit(unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, unsigned N5, unsigned N6 )
+  {
+    TestViewOperator_LeftAndRight driver(N0, N1, N2, N3, N4, N5, N6 );
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i6 = 0 ; i6 < unsigned(left.dimension_6()) ; ++i6 )
+    for ( unsigned i5 = 0 ; i5 < unsigned(left.dimension_5()) ; ++i5 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(left.dimension_4()) ; ++i4 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3, i4, i5, i6 ) -
+                     & left(  0,  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(right.dimension_4()) ; ++i4 )
+    for ( unsigned i5 = 0 ; i5 < unsigned(right.dimension_5()) ; ++i5 )
+    for ( unsigned i6 = 0 ; i6 < unsigned(right.dimension_6()) ; ++i6 )
+    {
+      const long j = & right( i0, i1, i2, i3, i4, i5, i6 ) -
+                     & right(  0,  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 6 >
+{
+  typedef DeviceType                          execution_space ;
+  typedef typename execution_space::memory_space  memory_space ;
+  typedef typename execution_space::size_type     size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  left_view    left ;
+  right_view   right ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, unsigned N5 )
+    : left(  "left" , N0, N1, N2, N3, N4, N5 )
+    , right( "right" , N0, N1, N2, N3, N4, N5 )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit(unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4, unsigned N5)
+  {
+    TestViewOperator_LeftAndRight driver (N0, N1, N2, N3, N4, N5);
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i5 = 0 ; i5 < unsigned(left.dimension_5()) ; ++i5 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(left.dimension_4()) ; ++i4 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3, i4, i5 ) -
+                     & left(  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(right.dimension_4()) ; ++i4 )
+    for ( unsigned i5 = 0 ; i5 < unsigned(right.dimension_5()) ; ++i5 )
+    {
+      const long j = & right( i0, i1, i2, i3, i4, i5 ) -
+                     & right(  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 5 >
+{
+  typedef DeviceType                          execution_space ;
+  typedef typename execution_space::memory_space  memory_space ;
+  typedef typename execution_space::size_type     size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutStride, execution_space > stride_view ;
+
+  left_view    left ;
+  right_view   right ;
+  stride_view  left_stride ;
+  stride_view  right_stride ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4 )
+    : left(  "left" , N0, N1, N2, N3, N4 )
+    , right( "right" , N0, N1, N2, N3, N4 )
+    , left_stride( left )
+    , right_stride( right )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit(unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4)
+  {
+    TestViewOperator_LeftAndRight driver(N0, N1, N2, N3, N4);
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i4 = 0 ; i4 < unsigned(left.dimension_4()) ; ++i4 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3, i4 ) -
+                     & left(  0,  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+
+      if ( & left( i0, i1, i2, i3, i4 ) !=
+           & left_stride( i0, i1, i2, i3, i4 ) ) { update |= 4 ; }
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(right.dimension_4()) ; ++i4 )
+    {
+      const long j = & right( i0, i1, i2, i3, i4 ) -
+                     & right(  0,  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+
+      if ( & right( i0, i1, i2, i3, i4 ) !=
+           & right_stride( i0, i1, i2, i3, i4 ) ) { update |= 8 ; }
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 4 >
+{
+  typedef DeviceType                          execution_space ;
+  typedef typename execution_space::memory_space  memory_space ;
+  typedef typename execution_space::size_type     size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+   Experimental::DynRankView< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  left_view    left ;
+  right_view   right ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2, unsigned N3)
+    : left(  "left" , N0, N1, N2, N3 )
+    , right( "right" , N0, N1, N2, N3 )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit(unsigned N0, unsigned N1, unsigned N2, unsigned N3)
+  {
+    TestViewOperator_LeftAndRight driver (N0, N1, N2, N3);
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3 ) -
+                     & left(  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    {
+      const long j = & right( i0, i1, i2, i3 ) -
+                     & right(  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 3 >
+{
+  typedef DeviceType                          execution_space ;
+  typedef typename execution_space::memory_space  memory_space ;
+  typedef typename execution_space::size_type     size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutStride, execution_space > stride_view ;
+
+  left_view    left ;
+  right_view   right ;
+  stride_view  left_stride ;
+  stride_view  right_stride ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight(unsigned N0, unsigned N1, unsigned N2)
+    : left(  std::string("left") , N0, N1, N2 )
+    , right( std::string("right") , N0, N1, N2 )
+    , left_stride( left )
+    , right_stride( right )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit(unsigned N0, unsigned N1, unsigned N2)
+  {
+    TestViewOperator_LeftAndRight driver (N0, N1, N2);
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2 ) -
+                     & left(  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+
+      if ( & left(i0,i1,i2) != & left_stride(i0,i1,i2) ) { update |= 4 ; }
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    {
+      const long j = & right( i0, i1, i2 ) -
+                     & right(  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+
+      if ( & right(i0,i1,i2) != & right_stride(i0,i1,i2) ) { update |= 8 ; }
+    }
+
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    {
+      if ( & left(i0,i1,i2)  != & left(i0,i1,i2,0,0,0,0) )  { update |= 3 ; }
+      if ( & right(i0,i1,i2) != & right(i0,i1,i2,0,0,0,0) ) { update |= 3 ; }
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 2 >
+{
+  typedef DeviceType                          execution_space ;
+  typedef typename execution_space::memory_space  memory_space ;
+  typedef typename execution_space::size_type     size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  left_view    left ;
+  right_view   right ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight(unsigned N0, unsigned N1)
+    : left(  "left" , N0, N1 )
+    , right( "right" , N0, N1 )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit(unsigned N0, unsigned N1)
+  {
+    TestViewOperator_LeftAndRight driver(N0, N1);
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1 ) -
+                     & left(  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    {
+      const long j = & right( i0, i1 ) -
+                     & right(  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+    }
+
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    {
+      if ( & left(i0,i1)  != & left(i0,i1,0,0,0,0,0) )  { update |= 3 ; }
+      if ( & right(i0,i1) != & right(i0,i1,0,0,0,0,0) ) { update |= 3 ; }
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 1 >
+{
+  typedef DeviceType                          execution_space ;
+  typedef typename execution_space::memory_space  memory_space ;
+  typedef typename execution_space::size_type     size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  typedef Kokkos::
+    Experimental::DynRankView< DataType, Kokkos::LayoutStride, execution_space > stride_view ;
+
+  left_view    left ;
+  right_view   right ;
+  stride_view  left_stride ;
+  stride_view  right_stride ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight(unsigned N0)
+    : left(  "left" , N0 )
+    , right( "right" , N0 )
+    , left_stride( left )
+    , right_stride( right )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit(unsigned N0)
+  {
+    TestViewOperator_LeftAndRight driver (N0) ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      if ( & left(i0)  != & left(i0,0,0,0,0,0,0) )  { update |= 3 ; }
+      if ( & right(i0) != & right(i0,0,0,0,0,0,0) ) { update |= 3 ; }
+      if ( & left(i0)  != & left_stride(i0) ) { update |= 4 ; }
+      if ( & right(i0) != & right_stride(i0) ) { update |= 8 ; }
+    }
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< typename T, class DeviceType >
+class TestDynViewAPI
+{
+public:
+  typedef DeviceType        device ;
+
+  enum { N0 = 1000 ,
+         N1 = 3 ,
+         N2 = 5 ,
+         N3 = 7 };
+
+  typedef Kokkos::Experimental::DynRankView< T , device > dView0 ;
+  typedef Kokkos::Experimental::DynRankView< const T , device > const_dView0 ;
+
+  typedef Kokkos::Experimental::DynRankView< T, device, Kokkos::MemoryUnmanaged > dView0_unmanaged ;
+  typedef typename dView0::host_mirror_space host_drv_space ;
+
+  typedef Kokkos::Experimental::View< T , device >        View0 ;
+  typedef Kokkos::Experimental::View< T* , device >       View1 ;
+  typedef Kokkos::Experimental::View< T******* , device > View7 ;
+
+  typedef typename View0::host_mirror_space  host_view_space ;
+
+  TestDynViewAPI()
+  {
+    run_test_resize_realloc();
+    run_test_mirror();
+    run_test_scalar();
+    run_test();
+    run_test_const();
+    run_test_subview();
+    run_test_subview_strided();
+    run_test_vector();
+
+    TestViewOperator< T , device >::testit();
+    TestViewOperator_LeftAndRight< int , device , 7 >::testit(2,3,4,2,3,4,2); 
+    TestViewOperator_LeftAndRight< int , device , 6 >::testit(2,3,4,2,3,4); 
+    TestViewOperator_LeftAndRight< int , device , 5 >::testit(2,3,4,2,3);
+    TestViewOperator_LeftAndRight< int , device , 4 >::testit(2,3,4,2);
+    TestViewOperator_LeftAndRight< int , device , 3 >::testit(2,3,4);
+    TestViewOperator_LeftAndRight< int , device , 2 >::testit(2,3);
+    TestViewOperator_LeftAndRight< int , device , 1 >::testit(2);
+  }
+
+  static void run_test_resize_realloc()
+  {
+    dView0 drv0("drv0", 10, 20, 30);
+    ASSERT_EQ( drv0.rank(), 3);
+
+    Kokkos::Experimental::resize(drv0, 5, 10);
+    ASSERT_EQ( drv0.rank(), 2);
+    ASSERT_EQ( drv0.dimension_0(), 5);
+    ASSERT_EQ( drv0.dimension_1(), 10);
+    ASSERT_EQ( drv0.dimension_2(), 1);
+
+    Kokkos::Experimental::realloc(drv0, 10, 20);
+    ASSERT_EQ( drv0.rank(), 2);
+    ASSERT_EQ( drv0.dimension_0(), 10);
+    ASSERT_EQ( drv0.dimension_1(), 20);
+    ASSERT_EQ( drv0.dimension_2(), 1);
+
+  }
+
+  static void run_test_mirror()
+  {
+    typedef Kokkos::Experimental::DynRankView< int , host_drv_space > view_type ;
+    typedef typename view_type::HostMirror mirror_type ;
+    view_type a("a");
+    mirror_type am = Kokkos::Experimental::create_mirror_view(a);
+    mirror_type ax = Kokkos::Experimental::create_mirror(a);
+    ASSERT_EQ( & a() , & am() );
+    ASSERT_EQ( a.rank() , am.rank() );
+    ASSERT_EQ( ax.rank() , am.rank() );
+
+    if (Kokkos::HostSpace::execution_space::is_initialized() )
+    {
+      Kokkos::DynRankView<double, Kokkos::LayoutLeft, Kokkos::HostSpace> a_h("A",1000);
+      auto a_h2 = Kokkos::create_mirror(Kokkos::HostSpace(),a_h);
+      auto a_d = Kokkos::create_mirror(typename device::memory_space(),a_h);
+  
+      int equal_ptr_h_h2  = (a_h.data() ==a_h2.data())?1:0;
+      int equal_ptr_h_d   = (a_h.data() ==a_d. data())?1:0;
+      int equal_ptr_h2_d  = (a_h2.data()==a_d. data())?1:0;
+  
+      ASSERT_EQ(equal_ptr_h_h2,0);
+      ASSERT_EQ(equal_ptr_h_d ,0);
+      ASSERT_EQ(equal_ptr_h2_d,0);
+  
+      ASSERT_EQ(a_h.dimension_0(),a_h2.dimension_0());
+      ASSERT_EQ(a_h.dimension_0(),a_d .dimension_0());
+
+      ASSERT_EQ(a_h.rank(),a_h2.rank());
+      ASSERT_EQ(a_h.rank(),a_d.rank());
+    }
+    if (Kokkos::HostSpace::execution_space::is_initialized() )
+    {
+      Kokkos::DynRankView<double, Kokkos::LayoutRight, Kokkos::HostSpace> a_h("A",1000);
+      auto a_h2 = Kokkos::create_mirror(Kokkos::HostSpace(),a_h);
+      auto a_d = Kokkos::create_mirror(typename device::memory_space(),a_h);
+  
+      int equal_ptr_h_h2  = (a_h.data() ==a_h2.data())?1:0;
+      int equal_ptr_h_d   = (a_h.data() ==a_d. data())?1:0;
+      int equal_ptr_h2_d  = (a_h2.data()==a_d. data())?1:0;
+  
+      ASSERT_EQ(equal_ptr_h_h2,0);
+      ASSERT_EQ(equal_ptr_h_d ,0);
+      ASSERT_EQ(equal_ptr_h2_d,0);
+  
+      ASSERT_EQ(a_h.dimension_0(),a_h2.dimension_0());
+      ASSERT_EQ(a_h.dimension_0(),a_d .dimension_0());
+
+      ASSERT_EQ(a_h.rank(),a_h2.rank());
+      ASSERT_EQ(a_h.rank(),a_d.rank());
+    }
+
+    if (Kokkos::HostSpace::execution_space::is_initialized() )
+    {
+      Kokkos::DynRankView<double, Kokkos::LayoutLeft, Kokkos::HostSpace> a_h("A",1000);
+      auto a_h2 = Kokkos::create_mirror_view(Kokkos::HostSpace(),a_h);
+      auto a_d = Kokkos::create_mirror_view(typename device::memory_space(),a_h);
+  
+      int equal_ptr_h_h2  = a_h.data() ==a_h2.data()?1:0;
+      int equal_ptr_h_d   = a_h.data() ==a_d. data()?1:0;
+      int equal_ptr_h2_d  = a_h2.data()==a_d. data()?1:0;
+  
+      int is_same_memspace = std::is_same<Kokkos::HostSpace,typename device::memory_space>::value?1:0; 
+      ASSERT_EQ(equal_ptr_h_h2,1);
+      ASSERT_EQ(equal_ptr_h_d ,is_same_memspace);
+      ASSERT_EQ(equal_ptr_h2_d ,is_same_memspace);
+  
+      ASSERT_EQ(a_h.dimension_0(),a_h2.dimension_0());
+      ASSERT_EQ(a_h.dimension_0(),a_d .dimension_0());
+
+      ASSERT_EQ(a_h.rank(),a_h2.rank());
+      ASSERT_EQ(a_h.rank(),a_d.rank());
+    } 
+    if (Kokkos::HostSpace::execution_space::is_initialized() )
+    {
+      Kokkos::DynRankView<double, Kokkos::LayoutRight, Kokkos::HostSpace> a_h("A",1000);
+      auto a_h2 = Kokkos::create_mirror_view(Kokkos::HostSpace(),a_h);
+      auto a_d = Kokkos::create_mirror_view(typename device::memory_space(),a_h);
+  
+      int equal_ptr_h_h2  = a_h.data() ==a_h2.data()?1:0;
+      int equal_ptr_h_d   = a_h.data() ==a_d. data()?1:0;
+      int equal_ptr_h2_d  = a_h2.data()==a_d. data()?1:0;
+  
+      int is_same_memspace = std::is_same<Kokkos::HostSpace,typename device::memory_space>::value?1:0; 
+      ASSERT_EQ(equal_ptr_h_h2,1);
+      ASSERT_EQ(equal_ptr_h_d ,is_same_memspace);
+      ASSERT_EQ(equal_ptr_h2_d ,is_same_memspace);
+  
+      ASSERT_EQ(a_h.dimension_0(),a_h2.dimension_0());
+      ASSERT_EQ(a_h.dimension_0(),a_d .dimension_0());
+
+      ASSERT_EQ(a_h.rank(),a_h2.rank());
+      ASSERT_EQ(a_h.rank(),a_d.rank());
+    } 
+    if (Kokkos::HostSpace::execution_space::is_initialized() )
+    {
+      typedef Kokkos::DynRankView< int , Kokkos::LayoutStride , Kokkos::HostSpace > view_stride_type ;
+      unsigned order[] = { 6,5,4,3,2,1,0 }, dimen[] = { N0, N1, N2, 2, 2, 2, 2 }; //LayoutRight equivalent
+      view_stride_type a_h( "a" , Kokkos::LayoutStride::order_dimensions(7, order, dimen) );
+      auto a_h2 = Kokkos::create_mirror_view(Kokkos::HostSpace(),a_h);
+      auto a_d = Kokkos::create_mirror_view(typename device::memory_space(),a_h);
+  
+      int equal_ptr_h_h2  = a_h.data() ==a_h2.data()?1:0;
+      int equal_ptr_h_d   = a_h.data() ==a_d. data()?1:0;
+      int equal_ptr_h2_d  = a_h2.data()==a_d. data()?1:0;
+  
+      int is_same_memspace = std::is_same<Kokkos::HostSpace,typename device::memory_space>::value?1:0; 
+      ASSERT_EQ(equal_ptr_h_h2,1);
+      ASSERT_EQ(equal_ptr_h_d ,is_same_memspace);
+      ASSERT_EQ(equal_ptr_h2_d ,is_same_memspace);
+  
+      ASSERT_EQ(a_h.dimension_0(),a_h2.dimension_0());
+      ASSERT_EQ(a_h.dimension_0(),a_d .dimension_0());
+
+      ASSERT_EQ(a_h.rank(),a_h2.rank());
+      ASSERT_EQ(a_h.rank(),a_d.rank());
+    }
+  }
+
+  static void run_test_scalar()
+  {
+    typedef typename dView0::HostMirror  hView0 ; //HostMirror of DynRankView is a DynRankView
+
+    dView0 dx , dy ;
+    hView0 hx , hy ;
+
+    dx = dView0( "dx" );
+    dy = dView0( "dy" );
+
+    hx = Kokkos::Experimental::create_mirror( dx );
+    hy = Kokkos::Experimental::create_mirror( dy );
+
+    hx() = 1 ;
+
+    Kokkos::Experimental::deep_copy( dx , hx );
+    Kokkos::Experimental::deep_copy( dy , dx );
+    Kokkos::Experimental::deep_copy( hy , dy );
+
+    ASSERT_EQ( hx(), hy() );
+    ASSERT_EQ( dx.rank() , hx.rank() );
+    ASSERT_EQ( dy.rank() , hy.rank() );
+
+  //View - DynRankView Interoperability tests
+  // deep_copy DynRankView to View
+    View0 vx("vx");
+    Kokkos::deep_copy( vx , dx );
+    ASSERT_EQ( rank(dx) , rank(vx) );
+
+    View0 vy("vy");
+    Kokkos::deep_copy( vy , dy );
+    ASSERT_EQ( rank(dy) , rank(vy) );
+
+  // deep_copy View to DynRankView 
+    dView0 dxx("dxx");
+    Kokkos::deep_copy( dxx , vx );
+    ASSERT_EQ( rank(dxx) , rank(vx) );
+
+
+    View7 vcast = dx.ConstDownCast();
+    ASSERT_EQ( dx.dimension_0() , vcast.dimension_0() );
+    ASSERT_EQ( dx.dimension_1() , vcast.dimension_1() );
+    ASSERT_EQ( dx.dimension_2() , vcast.dimension_2() );
+    ASSERT_EQ( dx.dimension_3() , vcast.dimension_3() );
+    ASSERT_EQ( dx.dimension_4() , vcast.dimension_4() );
+
+    View7 vcast1( dy.ConstDownCast() );
+    ASSERT_EQ( dy.dimension_0() , vcast1.dimension_0() );
+    ASSERT_EQ( dy.dimension_1() , vcast1.dimension_1() );
+    ASSERT_EQ( dy.dimension_2() , vcast1.dimension_2() );
+    ASSERT_EQ( dy.dimension_3() , vcast1.dimension_3() );
+    ASSERT_EQ( dy.dimension_4() , vcast1.dimension_4() );
+
+  //View - DynRankView Interoperability tests
+  // copy View to DynRankView
+    dView0 dfromvx( vx );
+    auto hmx = Kokkos::create_mirror_view(dfromvx) ;
+    Kokkos::deep_copy(hmx , dfromvx);
+    auto hvx = Kokkos::create_mirror_view(vx) ;
+    Kokkos::deep_copy(hvx , vx);
+    ASSERT_EQ( rank(hvx) , rank(hmx) );
+    ASSERT_EQ( hvx.dimension_0() , hmx.dimension_0() );
+    ASSERT_EQ( hvx.dimension_1() , hmx.dimension_1() );
+
+  // copy-assign View to DynRankView
+    dView0 dfromvy = vy ;
+    auto hmy = Kokkos::create_mirror_view(dfromvy) ;
+    Kokkos::deep_copy(hmy , dfromvy);
+    auto hvy = Kokkos::create_mirror_view(vy) ;
+    Kokkos::deep_copy(hvy , vy);
+    ASSERT_EQ( rank(hvy) , rank(hmy) );
+    ASSERT_EQ( hvy.dimension_0() , hmy.dimension_0() );
+    ASSERT_EQ( hvy.dimension_1() , hmy.dimension_1() );
+
+
+    View7 vtest1("vtest1",2,2,2,2,2,2,2);
+    dView0 dfromv1( vtest1 );
+    ASSERT_EQ( dfromv1.rank() , vtest1.Rank );
+    ASSERT_EQ( dfromv1.dimension_0() , vtest1.dimension_0() );
+    ASSERT_EQ( dfromv1.dimension_1() , vtest1.dimension_1() );
+    ASSERT_EQ( dfromv1.use_count() , vtest1.use_count() );
+
+    dView0 dfromv2( vcast );
+    ASSERT_EQ( dfromv2.rank() , vcast.Rank );
+    ASSERT_EQ( dfromv2.dimension_0() , vcast.dimension_0() );
+    ASSERT_EQ( dfromv2.dimension_1() , vcast.dimension_1() );
+    ASSERT_EQ( dfromv2.use_count() , vcast.use_count() );
+
+    dView0 dfromv3 = vcast1;
+    ASSERT_EQ( dfromv3.rank() , vcast1.Rank );
+    ASSERT_EQ( dfromv3.dimension_0() , vcast1.dimension_0() );
+    ASSERT_EQ( dfromv3.dimension_1() , vcast1.dimension_1() );
+    ASSERT_EQ( dfromv3.use_count() , vcast1.use_count() );
+  }
+
+  static void run_test()
+  {
+    // mfh 14 Feb 2014: This test doesn't actually create instances of
+    // these types.  In order to avoid "declared but unused typedef"
+    // warnings, we declare empty instances of these types, with the
+    // usual "(void)" marker to avoid compiler warnings for unused
+    // variables.
+
+    typedef typename dView0::HostMirror  hView0 ;
+
+    {
+      hView0 thing;
+      (void) thing;
+    }
+
+    dView0 d_uninitialized(Kokkos::ViewAllocateWithoutInitializing("uninit"),10,20);
+    ASSERT_TRUE( d_uninitialized.data() != nullptr );
+    ASSERT_EQ( d_uninitialized.rank() , 2 );
+    ASSERT_EQ( d_uninitialized.dimension_0() , 10 );
+    ASSERT_EQ( d_uninitialized.dimension_1() , 20 );
+    ASSERT_EQ( d_uninitialized.dimension_2() , 1  );
+
+    dView0 dx , dy , dz ;
+    hView0 hx , hy , hz ;
+
+    ASSERT_TRUE( Kokkos::Experimental::is_dyn_rank_view<dView0>::value );
+    ASSERT_FALSE( Kokkos::Experimental::is_dyn_rank_view< Kokkos::View<double> >::value );
+
+    ASSERT_TRUE( dx.ptr_on_device() == 0 ); //Okay with UVM
+    ASSERT_TRUE( dy.ptr_on_device() == 0 );  //Okay with UVM
+    ASSERT_TRUE( dz.ptr_on_device() == 0 ); //Okay with UVM
+    ASSERT_TRUE( hx.ptr_on_device() == 0 );
+    ASSERT_TRUE( hy.ptr_on_device() == 0 );
+    ASSERT_TRUE( hz.ptr_on_device() == 0 );
+    ASSERT_EQ( dx.dimension_0() , 0u ); //Okay with UVM
+    ASSERT_EQ( dy.dimension_0() , 0u ); //Okay with UVM
+    ASSERT_EQ( dz.dimension_0() , 0u ); //Okay with UVM
+    ASSERT_EQ( hx.dimension_0() , 0u );
+    ASSERT_EQ( hy.dimension_0() , 0u );
+    ASSERT_EQ( hz.dimension_0() , 0u );
+    ASSERT_EQ( dx.rank() , 0u ); //Okay with UVM
+    ASSERT_EQ( hx.rank() , 0u );
+
+    dx = dView0( "dx" , N1 , N2 , N3 );
+    dy = dView0( "dy" , N1 , N2 , N3 );
+
+    hx = hView0( "hx" , N1 , N2 , N3 );
+    hy = hView0( "hy" , N1 , N2 , N3 );
+
+    ASSERT_EQ( dx.dimension_0() , unsigned(N1) ); //Okay with UVM
+    ASSERT_EQ( dy.dimension_0() , unsigned(N1) ); //Okay with UVM
+    ASSERT_EQ( hx.dimension_0() , unsigned(N1) );
+    ASSERT_EQ( hy.dimension_0() , unsigned(N1) );
+    ASSERT_EQ( dx.rank() , 3 ); //Okay with UVM
+    ASSERT_EQ( hx.rank() , 3 );
+
+    dx = dView0( "dx" , N0 , N1 , N2 , N3 );
+    dy = dView0( "dy" , N0 , N1 , N2 , N3 );
+    hx = hView0( "hx" , N0 , N1 , N2 , N3 );
+    hy = hView0( "hy" , N0 , N1 , N2 , N3 );
+
+    ASSERT_EQ( dx.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( dy.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( hx.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( hy.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( dx.rank() , 4 );
+    ASSERT_EQ( dy.rank() , 4 );
+    ASSERT_EQ( hx.rank() , 4 );
+    ASSERT_EQ( hy.rank() , 4 );
+
+    ASSERT_EQ( dx.use_count() , size_t(1) );
+
+    dView0_unmanaged unmanaged_dx = dx;
+    ASSERT_EQ( dx.use_count() , size_t(1) );
+
+
+    dView0_unmanaged unmanaged_from_ptr_dx = dView0_unmanaged(dx.ptr_on_device(),
+                                                              dx.dimension_0(),
+                                                              dx.dimension_1(),
+                                                              dx.dimension_2(),
+                                                              dx.dimension_3());
+
+
+    {
+      // Destruction of this view should be harmless
+      const_dView0 unmanaged_from_ptr_const_dx( dx.ptr_on_device() ,
+                                                dx.dimension_0() ,
+                                                dx.dimension_1() ,
+                                                dx.dimension_2() ,
+                                                dx.dimension_3() );
+    }
+
+    const_dView0 const_dx = dx ;
+    ASSERT_EQ( dx.use_count() , size_t(2) );
+
+    {
+      const_dView0 const_dx2;
+      const_dx2 = const_dx;
+      ASSERT_EQ( dx.use_count() , size_t(3) );
+
+      const_dx2 = dy;
+      ASSERT_EQ( dx.use_count() , size_t(2) );
+
+      const_dView0 const_dx3(dx);
+      ASSERT_EQ( dx.use_count() , size_t(3) );
+      
+      dView0_unmanaged dx4_unmanaged(dx);
+      ASSERT_EQ( dx.use_count() , size_t(3) );
+    }
+
+    ASSERT_EQ( dx.use_count() , size_t(2) );
+
+
+    ASSERT_FALSE( dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( const_dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( unmanaged_dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( unmanaged_from_ptr_dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( dy.ptr_on_device() == 0 );
+    ASSERT_NE( dx , dy );
+
+    ASSERT_EQ( dx.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( dx.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( dx.dimension_2() , unsigned(N2) );
+    ASSERT_EQ( dx.dimension_3() , unsigned(N3) );
+
+    ASSERT_EQ( dy.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( dy.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( dy.dimension_2() , unsigned(N2) );
+    ASSERT_EQ( dy.dimension_3() , unsigned(N3) );
+
+    ASSERT_EQ( unmanaged_from_ptr_dx.capacity(),unsigned(N0)*unsigned(N1)*unsigned(N2)*unsigned(N3) );
+
+    hx = Kokkos::Experimental::create_mirror( dx );
+    hy = Kokkos::Experimental::create_mirror( dy );
+
+    ASSERT_EQ( hx.rank() , dx.rank() );
+    ASSERT_EQ( hy.rank() , dy.rank() );
+
+    ASSERT_EQ( hx.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( hx.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( hx.dimension_2() , unsigned(N2) );
+    ASSERT_EQ( hx.dimension_3() , unsigned(N3) );
+
+    ASSERT_EQ( hy.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( hy.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( hy.dimension_2() , unsigned(N2) );
+    ASSERT_EQ( hy.dimension_3() , unsigned(N3) );
+
+    // T v1 = hx() ;    // Generates compile error as intended
+    // T v2 = hx(0,0) ; // Generates compile error as intended
+    // hx(0,0) = v2 ;   // Generates compile error as intended
+
+/*
+#if ! KOKKOS_USING_EXP_VIEW
+    // Testing with asynchronous deep copy with respect to device
+    {
+      size_t count = 0 ;
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < hx.dimension_1() ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < hx.dimension_2() ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < hx.dimension_3() ; ++i3 ) {
+        hx(ip,i1,i2,i3) = ++count ;
+      }}}}
+
+
+      Kokkos::deep_copy(typename hView0::execution_space(), dx , hx );
+      Kokkos::deep_copy(typename hView0::execution_space(), dy , dx );
+      Kokkos::deep_copy(typename hView0::execution_space(), hy , dy );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , hy(ip,i1,i2,i3) ); }
+      }}}}
+
+      Kokkos::deep_copy(typename hView0::execution_space(), dx , T(0) );
+      Kokkos::deep_copy(typename hView0::execution_space(), hx , dx );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , T(0) ); }
+      }}}}
+    }
+
+    // Testing with asynchronous deep copy with respect to host
+    {
+      size_t count = 0 ;
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < hx.dimension_1() ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < hx.dimension_2() ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < hx.dimension_3() ; ++i3 ) {
+        hx(ip,i1,i2,i3) = ++count ;
+      }}}}
+
+      Kokkos::deep_copy(typename dView0::execution_space(), dx , hx );
+      Kokkos::deep_copy(typename dView0::execution_space(), dy , dx );
+      Kokkos::deep_copy(typename dView0::execution_space(), hy , dy );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , hy(ip,i1,i2,i3) ); }
+      }}}}
+
+      Kokkos::deep_copy(typename dView0::execution_space(), dx , T(0) );
+      Kokkos::deep_copy(typename dView0::execution_space(), hx , dx );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , T(0) ); }
+      }}}}
+    }
+#endif */ // #if ! KOKKOS_USING_EXP_VIEW
+
+    // Testing with synchronous deep copy
+    {
+      size_t count = 0 ;
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < hx.dimension_1() ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < hx.dimension_2() ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < hx.dimension_3() ; ++i3 ) {
+        hx(ip,i1,i2,i3) = ++count ;
+      }}}}
+
+      Kokkos::Experimental::deep_copy( dx , hx );
+      Kokkos::Experimental::deep_copy( dy , dx );
+      Kokkos::Experimental::deep_copy( hy , dy );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , hy(ip,i1,i2,i3) ); }
+      }}}}
+
+      Kokkos::Experimental::deep_copy( dx , T(0) );
+      Kokkos::Experimental::deep_copy( hx , dx );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , T(0) ); }
+      }}}}
+//    ASSERT_EQ( hx(0,0,0,0,0,0,0,0) , T(0) ); //Test rank8 op behaves properly - if implemented
+    }
+
+    dz = dx ; ASSERT_EQ( dx, dz); ASSERT_NE( dy, dz);
+    dz = dy ; ASSERT_EQ( dy, dz); ASSERT_NE( dx, dz);
+
+    dx = dView0();
+    ASSERT_TRUE( dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( dy.ptr_on_device() == 0 );
+    ASSERT_FALSE( dz.ptr_on_device() == 0 );
+    dy = dView0();
+    ASSERT_TRUE( dx.ptr_on_device() == 0 );
+    ASSERT_TRUE( dy.ptr_on_device() == 0 );
+    ASSERT_FALSE( dz.ptr_on_device() == 0 );
+    dz = dView0();
+    ASSERT_TRUE( dx.ptr_on_device() == 0 );
+    ASSERT_TRUE( dy.ptr_on_device() == 0 );
+    ASSERT_TRUE( dz.ptr_on_device() == 0 );
+
+  //View - DynRankView Interoperability tests
+    // deep_copy from view to dynrankview
+    const int testdim = 4;
+    dView0 dxx("dxx",testdim);
+    View1  vxx("vxx",testdim);
+    auto hvxx = Kokkos::create_mirror_view(vxx); 
+    for (int i = 0; i < testdim; ++i)
+      { hvxx(i) = i; }
+    Kokkos::deep_copy(vxx,hvxx);
+    Kokkos::deep_copy(dxx,vxx);
+    auto hdxx = Kokkos::create_mirror_view(dxx);
+    Kokkos::deep_copy(hdxx,dxx);
+    for (int i = 0; i < testdim; ++i)
+      { ASSERT_EQ( hvxx(i) , hdxx(i) ); }
+
+    ASSERT_EQ( rank(hdxx) , rank(hvxx) );
+    ASSERT_EQ( hdxx.dimension_0() , testdim );
+    ASSERT_EQ( hdxx.dimension_0() , hvxx.dimension_0() );
+
+    // deep_copy from dynrankview to view
+    View1 vdxx("vdxx",testdim);
+    auto hvdxx = Kokkos::create_mirror_view(vdxx);
+    Kokkos::deep_copy(hvdxx , hdxx);
+    ASSERT_EQ( rank(hdxx) , rank(hvdxx) );
+    ASSERT_EQ( hvdxx.dimension_0() , testdim );
+    ASSERT_EQ( hdxx.dimension_0() , hvdxx.dimension_0() );
+    for (int i = 0; i < testdim; ++i)
+      { ASSERT_EQ( hvxx(i) , hvdxx(i) ); }
+  }
+
+  typedef T DataType ;
+
+  static void
+  check_auto_conversion_to_const(
+     const Kokkos::Experimental::DynRankView< const DataType , device > & arg_const ,
+     const Kokkos::Experimental::DynRankView< DataType , device > & arg )
+  {
+    ASSERT_TRUE( arg_const == arg );
+  }
+
+  static void run_test_const()
+  {
+    typedef Kokkos::Experimental::DynRankView< DataType , device > typeX ;
+    typedef Kokkos::Experimental::DynRankView< const DataType , device > const_typeX ;
+    typedef Kokkos::Experimental::DynRankView< const DataType , device , Kokkos::MemoryRandomAccess > const_typeR ;
+    typeX x( "X", 2 );
+    const_typeX xc = x ;
+    const_typeR xr = x ;
+
+    ASSERT_TRUE( xc == x );
+    ASSERT_TRUE( x == xc );
+
+    // For CUDA the constant random access View does not return
+    // an lvalue reference due to retrieving through texture cache
+    // therefore not allowed to query the underlying pointer.
+#if defined(KOKKOS_HAVE_CUDA)
+    if ( ! std::is_same< typename device::execution_space , Kokkos::Cuda >::value )
+#endif
+    {
+      ASSERT_TRUE( x.ptr_on_device() == xr.ptr_on_device() );
+    }
+
+    // typeX xf = xc ; // setting non-const from const must not compile
+
+    check_auto_conversion_to_const( x , x );
+  }
+
+
+  static void run_test_subview()
+  {
+    typedef Kokkos::Experimental::DynRankView< const T , device > cdView ;
+    typedef Kokkos::Experimental::DynRankView< T , device > dView ;
+  // LayoutStride required for all returned DynRankView subdynrankview's
+    typedef Kokkos::Experimental::DynRankView< T , Kokkos::LayoutStride , device > sdView ; 
+
+    dView0 d0( "d0" );
+    cdView s0 = d0 ;
+
+  //  N0 = 1000,N1 = 3,N2 = 5,N3 = 7 
+    unsigned order[] = { 6,5,4,3,2,1,0 }, dimen[] = { N0, N1, N2, 2, 2, 2, 2 }; //LayoutRight equivalent
+    sdView d7( "d7" , Kokkos::LayoutStride::order_dimensions(7, order, dimen) );
+    ASSERT_EQ( d7.rank() , 7 );
+
+    sdView ds0 = Kokkos::subdynrankview( d7 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ); 
+    ASSERT_EQ( ds0.rank() , 0 );
+
+//Basic test - ALL
+    sdView dsALL = Kokkos::Experimental::subdynrankview( d7 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() ); 
+    ASSERT_EQ( dsALL.rank() , 7 );
+
+//  Send a value to final rank returning rank 6 subview
+    sdView dsm1 = Kokkos::Experimental::subdynrankview( d7 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , 1 );
+    ASSERT_EQ( dsm1.rank() , 6 );
+
+//  Send a std::pair as argument to a rank
+    sdView dssp = Kokkos::Experimental::subdynrankview( d7 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , std::pair<unsigned,unsigned>(1,2) );
+    ASSERT_EQ( dssp.rank() , 7 );
+
+//  Send a kokkos::pair as argument to a rank; take default layout as input
+    dView0 dd0("dd0" , N0 , N1 , N2 , 2 , 2 , 2 , 2 ); //default layout
+    ASSERT_EQ( dd0.rank() , 7 );
+    sdView dtkp = Kokkos::Experimental::subdynrankview( dd0 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::pair<unsigned,unsigned>(0,1) );
+    ASSERT_EQ( dtkp.rank() , 7 );
+
+// Return rank 7 subview, taking a pair as one argument, layout stride input
+    sdView ds7 = Kokkos::Experimental::subdynrankview( d7 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::pair<unsigned,unsigned>(0,1) );
+    ASSERT_EQ( ds7.rank() , 7 );
+
+// Default Layout DynRankView
+    dView dv6("dv6" , N0 , N1 , N2 , N3 , 2 , 2 );
+    ASSERT_EQ( dv6.rank() , 6 );
+
+// DynRankView with LayoutRight
+    typedef Kokkos::Experimental::DynRankView< T , Kokkos::LayoutRight , device > drView ;
+    drView dr5( "dr5" , N0 , N1 , N2 , 2 , 2 );
+    ASSERT_EQ( dr5.rank() , 5 );
+
+// LayoutStride but arranged as LayoutRight
+  // NOTE: unused arg_layout dimensions must be set to ~size_t(0) so that 
+  //  rank deduction can properly take place
+    unsigned order5[] = { 4,3,2,1,0 }, dimen5[] = { N0, N1, N2, 2, 2 };
+    Kokkos::LayoutStride ls = Kokkos::LayoutStride::order_dimensions(5, order5, dimen5);
+    ls.dimension[5] = ~size_t(0);
+    ls.dimension[6] = ~size_t(0);
+    ls.dimension[7] = ~size_t(0);
+    sdView d5("d5", ls);
+    ASSERT_EQ( d5.rank() , 5 );
+
+//  LayoutStride arranged as LayoutRight - commented out as example that fails unit test
+//    unsigned order5[] = { 4,3,2,1,0 }, dimen5[] = { N0, N1, N2, 2, 2 };
+//    sdView d5( "d5" , Kokkos::LayoutStride::order_dimensions(5, order5, dimen5) );
+//
+//  Fails the following unit test:
+//    ASSERT_EQ( d5.rank() , dr5.rank() );
+//
+//  Explanation: In construction of the Kokkos::LayoutStride below, since the 
+//   remaining dimensions are not specified, they will default to values of 0 
+//   rather than ~size_t(0). 
+//  When passed to the DynRankView constructor the default dimensions (of 0) 
+//   will be counted toward the dynamic rank and returning an incorrect value 
+//   (i.e. rank 7 rather than 5).
+
+// Check LayoutRight dr5 and LayoutStride d5 dimensions agree (as they should) 
+    ASSERT_EQ( d5.dimension_0() , dr5.dimension_0() );
+    ASSERT_EQ( d5.dimension_1() , dr5.dimension_1() );
+    ASSERT_EQ( d5.dimension_2() , dr5.dimension_2() );
+    ASSERT_EQ( d5.dimension_3() , dr5.dimension_3() );
+    ASSERT_EQ( d5.dimension_4() , dr5.dimension_4() );
+    ASSERT_EQ( d5.dimension_5() , dr5.dimension_5() );
+    ASSERT_EQ( d5.rank() , dr5.rank() );
+
+// Rank 5 subview of rank 5 dynamic rank view, layout stride input
+    sdView ds5 = Kokkos::Experimental::subdynrankview( d5 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::pair<unsigned,unsigned>(0,1) );
+    ASSERT_EQ( ds5.rank() , 5 );
+
+// Pass in extra ALL arguments beyond the rank of the DynRank View.
+// This behavior is allowed - ignore the extra ALL arguments when
+//  the src.rank() < number of arguments, but be careful!
+    sdView ds5plus = Kokkos::Experimental::subdynrankview( d5 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::pair<unsigned,unsigned>(0,1) , Kokkos::ALL() );
+
+    ASSERT_EQ( ds5.rank() , ds5plus.rank() );
+    ASSERT_EQ( ds5.dimension_0() , ds5plus.dimension_0() );
+    ASSERT_EQ( ds5.dimension_4() , ds5plus.dimension_4() );
+    ASSERT_EQ( ds5.dimension_5() , ds5plus.dimension_5() );
+
+#if ! defined( KOKKOS_HAVE_CUDA ) || defined ( KOKKOS_USE_CUDA_UVM )
+    ASSERT_EQ( & ds5(1,1,1,1,0) - & ds5plus(1,1,1,1,0) , 0 );
+    ASSERT_EQ( & ds5(1,1,1,1,0,0) - & ds5plus(1,1,1,1,0,0) , 0 );  // passing argument to rank beyond the view's rank is allowed iff it is a 0. 
+#endif
+
+// Similar test to rank 5 above, but create rank 4 subview
+// Check that the rank contracts (ds4 and ds4plus) and that subdynrankview can accept extra args (ds4plus)
+    sdView ds4 = Kokkos::Experimental::subdynrankview( d5 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , 0 );
+    sdView ds4plus = Kokkos::Experimental::subdynrankview( d5 , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , Kokkos::ALL() , 0 , Kokkos::ALL() );
+
+    ASSERT_EQ( ds4.rank() , ds4plus.rank() );
+    ASSERT_EQ( ds4.rank() , 4 );
+    ASSERT_EQ( ds4.dimension_0() , ds4plus.dimension_0() );
+    ASSERT_EQ( ds4.dimension_4() , ds4plus.dimension_4() );
+    ASSERT_EQ( ds4.dimension_5() , ds4plus.dimension_5() );
+  }
+
+  static void run_test_subview_strided()
+  {
+    typedef Kokkos::Experimental::DynRankView < int , Kokkos::LayoutLeft , host_drv_space > drview_left ;
+    typedef Kokkos::Experimental::DynRankView < int , Kokkos::LayoutRight , host_drv_space > drview_right ;
+    typedef Kokkos::Experimental::DynRankView < int , Kokkos::LayoutStride , host_drv_space > drview_stride ;
+
+    drview_left  xl2( "xl2", 100 , 200 );
+    drview_right xr2( "xr2", 100 , 200 );
+    drview_stride yl1 = Kokkos::Experimental::subdynrankview( xl2 , 0 , Kokkos::ALL() );
+    drview_stride yl2 = Kokkos::Experimental::subdynrankview( xl2 , 1 , Kokkos::ALL() );
+    drview_stride ys1 = Kokkos::Experimental::subdynrankview( xr2 , 0 , Kokkos::ALL() );
+    drview_stride ys2 = Kokkos::Experimental::subdynrankview( xr2 , 1 , Kokkos::ALL() );
+    drview_stride yr1 = Kokkos::Experimental::subdynrankview( xr2 , 0 , Kokkos::ALL() );
+    drview_stride yr2 = Kokkos::Experimental::subdynrankview( xr2 , 1 , Kokkos::ALL() );
+
+    ASSERT_EQ( yl1.dimension_0() , xl2.dimension_1() );
+    ASSERT_EQ( yl2.dimension_0() , xl2.dimension_1() );
+
+    ASSERT_EQ( yr1.dimension_0() , xr2.dimension_1() );
+    ASSERT_EQ( yr2.dimension_0() , xr2.dimension_1() );
+
+    ASSERT_EQ( & yl1(0) - & xl2(0,0) , 0 );
+    ASSERT_EQ( & yl2(0) - & xl2(1,0) , 0 );
+    ASSERT_EQ( & yr1(0) - & xr2(0,0) , 0 );
+    ASSERT_EQ( & yr2(0) - & xr2(1,0) , 0 );
+
+
+    drview_left  xl4( "xl4", 10 , 20 , 30 , 40 );
+    drview_right xr4( "xr4", 10 , 20 , 30 , 40 );
+
+    //Replace subdynrankview with subview - test
+    drview_stride yl4 = Kokkos::Experimental::subview( xl4 , 1 , Kokkos::ALL() , 2 , Kokkos::ALL() );
+    drview_stride yr4 = Kokkos::Experimental::subview( xr4 , 1 , Kokkos::ALL() , 2 , Kokkos::ALL() );
+
+    ASSERT_EQ( yl4.dimension_0() , xl4.dimension_1() );
+    ASSERT_EQ( yl4.dimension_1() , xl4.dimension_3() );
+    ASSERT_EQ( yr4.dimension_0() , xr4.dimension_1() );
+    ASSERT_EQ( yr4.dimension_1() , xr4.dimension_3() );
+    ASSERT_EQ( yl4.rank() , 2);
+    ASSERT_EQ( yr4.rank() , 2);
+
+    ASSERT_EQ( & yl4(4,4) - & xl4(1,4,2,4) , 0 );
+    ASSERT_EQ( & yr4(4,4) - & xr4(1,4,2,4) , 0 );
+  }
+
+  static void run_test_vector()
+  {
+    static const unsigned Length = 1000 , Count = 8 ;
+
+    typedef typename Kokkos::Experimental::DynRankView< T , Kokkos::LayoutLeft , host_drv_space > multivector_type ; 
+
+    typedef typename Kokkos::Experimental::DynRankView< T , Kokkos::LayoutRight , host_drv_space > multivector_right_type ;
+
+    multivector_type mv = multivector_type( "mv" , Length , Count );
+    multivector_right_type mv_right = multivector_right_type( "mv" , Length , Count );
+
+    typedef typename Kokkos::Experimental::DynRankView< T , Kokkos::LayoutStride , host_drv_space > svector_type ;
+    typedef typename Kokkos::Experimental::DynRankView< T , Kokkos::LayoutStride , host_drv_space > smultivector_type ;
+    typedef typename Kokkos::Experimental::DynRankView< const T , Kokkos::LayoutStride , host_drv_space > const_svector_right_type ; 
+    typedef typename Kokkos::Experimental::DynRankView< const T , Kokkos::LayoutStride , host_drv_space > const_svector_type ;
+    typedef typename Kokkos::Experimental::DynRankView< const T , Kokkos::LayoutStride , host_drv_space > const_smultivector_type ;
+
+    svector_type v1 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 0 );
+    svector_type v2 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 1 );
+    svector_type v3 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 2 );
+
+    svector_type rv1 = Kokkos::Experimental::subdynrankview( mv_right , 0 , Kokkos::ALL() );
+    svector_type rv2 = Kokkos::Experimental::subdynrankview( mv_right , 1 , Kokkos::ALL() );
+    svector_type rv3 = Kokkos::Experimental::subdynrankview( mv_right , 2 , Kokkos::ALL() );
+
+    smultivector_type mv1 = Kokkos::Experimental::subdynrankview( mv , std::make_pair( 1 , 998 ) ,
+                                                 std::make_pair( 2 , 5 ) );
+
+    smultivector_type mvr1 =
+      Kokkos::Experimental::subdynrankview( mv_right ,
+                       std::make_pair( 1 , 998 ) ,
+                       std::make_pair( 2 , 5 ) );
+
+    const_svector_type cv1 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL(), 0 );
+    const_svector_type cv2 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL(), 1 );
+    const_svector_type cv3 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL(), 2 );
+
+    svector_type vr1 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 0 );
+    svector_type vr2 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 1 );
+    svector_type vr3 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 2 );
+
+    const_svector_right_type cvr1 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 0 );
+    const_svector_right_type cvr2 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 1 );
+    const_svector_right_type cvr3 = Kokkos::Experimental::subdynrankview( mv , Kokkos::ALL() , 2 );
+
+
+    ASSERT_TRUE( & v1[0] == & v1(0) );
+    ASSERT_TRUE( & v1[0] == & mv(0,0) );
+    ASSERT_TRUE( & v2[0] == & mv(0,1) );
+    ASSERT_TRUE( & v3[0] == & mv(0,2) );
+
+    ASSERT_TRUE( & cv1[0] == & mv(0,0) );
+    ASSERT_TRUE( & cv2[0] == & mv(0,1) );
+    ASSERT_TRUE( & cv3[0] == & mv(0,2) );
+
+    ASSERT_TRUE( & vr1[0] == & mv(0,0) );
+    ASSERT_TRUE( & vr2[0] == & mv(0,1) );
+    ASSERT_TRUE( & vr3[0] == & mv(0,2) );
+
+    ASSERT_TRUE( & cvr1[0] == & mv(0,0) );
+    ASSERT_TRUE( & cvr2[0] == & mv(0,1) );
+    ASSERT_TRUE( & cvr3[0] == & mv(0,2) );
+
+
+    ASSERT_TRUE( & mv1(0,0) == & mv( 1 , 2 ) );
+    ASSERT_TRUE( & mv1(1,1) == & mv( 2 , 3 ) );
+    ASSERT_TRUE( & mv1(3,2) == & mv( 4 , 4 ) );
+    ASSERT_TRUE( & mvr1(0,0) == & mv_right( 1 , 2 ) );
+    ASSERT_TRUE( & mvr1(1,1) == & mv_right( 2 , 3 ) );
+    ASSERT_TRUE( & mvr1(3,2) == & mv_right( 4 , 4 ) );
+
+    const_svector_type c_cv1( v1 );
+    typename svector_type::const_type c_cv2( v2 );
+    typename const_svector_type::const_type c_ccv2( v2 );
+
+
+    const_smultivector_type cmv( mv );
+    typename smultivector_type::const_type cmvX( cmv );
+    typename const_smultivector_type::const_type ccmvX( cmv );
+  }
+};
+
+} // namespace Test
+
+/*--------------------------------------------------------------------------*/
+
diff --git a/lib/kokkos/containers/unit_tests/TestDynamicView.hpp b/lib/kokkos/containers/unit_tests/TestDynamicView.hpp
new file mode 100644
index 0000000000..7e3ca005f4
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestDynamicView.hpp
@@ -0,0 +1,168 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_TEST_DYNAMICVIEW_HPP
+#define KOKKOS_TEST_DYNAMICVIEW_HPP
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+#include <Kokkos_Core.hpp>
+
+#include <Kokkos_DynamicView.hpp>
+#include <impl/Kokkos_Timer.hpp>
+
+namespace Test {
+
+template< typename Scalar , class Space >
+struct TestDynamicView
+{
+  typedef typename Space::execution_space  execution_space ;
+  typedef typename Space::memory_space     memory_space ;
+
+  typedef Kokkos::Experimental::MemoryPool<typename Space::device_type> memory_pool_type;
+
+  typedef Kokkos::Experimental::DynamicView<Scalar*,Space> view_type;
+
+  typedef typename Kokkos::TeamPolicy<execution_space>::member_type member_type ;
+  typedef double value_type;
+
+  struct TEST {};
+  struct VERIFY {};
+
+  view_type a;
+  const unsigned total_size ;
+
+  TestDynamicView( const view_type & arg_a , const unsigned arg_total )
+    : a(arg_a), total_size( arg_total ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() ( const TEST , member_type team_member, double& value) const
+  {
+    const unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+    if ( team_member.team_rank() == 0 ) {
+      unsigned n = team_idx + team_member.team_size();
+
+      if ( total_size < n ) n = total_size ;
+
+      a.resize_parallel( n );
+
+      if ( a.extent(0) < n ) {
+        Kokkos::abort("GrowTest TEST failed resize_parallel");
+      }
+    }
+
+    // Make sure resize is done for all team members:
+    team_member.team_barrier();
+
+    const unsigned int val = team_idx + team_member.team_rank();
+
+    if ( val < total_size ) {
+      value += val ;
+
+      a( val ) = val ;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() ( const VERIFY , member_type team_member, double& value) const
+  {
+    const unsigned int val =
+      team_member.team_rank() + 
+      team_member.league_rank() * team_member.team_size();
+
+    if ( val < total_size ) {
+    
+      if ( val != a(val) ) {
+        Kokkos::abort("GrowTest VERIFY failed resize_parallel");
+      }
+
+      value += a(val);
+    }
+  }
+
+  static void run( unsigned arg_total_size )
+  {
+    typedef Kokkos::TeamPolicy<execution_space,TEST> TestPolicy ;
+    typedef Kokkos::TeamPolicy<execution_space,VERIFY> VerifyPolicy ;
+
+// printf("TestDynamicView::run(%d) construct memory pool\n",arg_total_size);
+
+    memory_pool_type pool( memory_space() , arg_total_size * sizeof(Scalar) * 1.2 );
+
+// printf("TestDynamicView::run(%d) construct dynamic view\n",arg_total_size);
+
+    view_type da("A",pool,arg_total_size);
+
+// printf("TestDynamicView::run(%d) construct test functor\n",arg_total_size);
+
+    TestDynamicView functor(da,arg_total_size);
+
+    const unsigned team_size = TestPolicy::team_size_recommended(functor);
+    const unsigned league_size = ( arg_total_size + team_size - 1 ) / team_size ;
+
+    double reference = 0;
+    double result = 0;
+
+// printf("TestDynamicView::run(%d) run functor test\n",arg_total_size);
+
+    Kokkos::parallel_reduce( TestPolicy(league_size,team_size) , functor , reference);
+    execution_space::fence();
+
+
+// printf("TestDynamicView::run(%d) run functor verify\n",arg_total_size);
+
+    Kokkos::parallel_reduce( VerifyPolicy(league_size,team_size) , functor , result );
+    execution_space::fence();
+
+// printf("TestDynamicView::run(%d) done\n",arg_total_size);
+
+  }
+};
+
+} // namespace Test
+
+#endif /* #ifndef KOKKOS_TEST_DYNAMICVIEW_HPP */
+
diff --git a/lib/kokkos/containers/unit_tests/TestOpenMP.cpp b/lib/kokkos/containers/unit_tests/TestOpenMP.cpp
new file mode 100644
index 0000000000..a4319f39ff
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestOpenMP.cpp
@@ -0,0 +1,182 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#include <Kokkos_Bitset.hpp>
+#include <Kokkos_UnorderedMap.hpp>
+#include <Kokkos_Vector.hpp>
+
+//----------------------------------------------------------------------------
+#include <TestBitset.hpp>
+#include <TestUnorderedMap.hpp>
+#include <TestStaticCrsGraph.hpp>
+#include <TestVector.hpp>
+#include <TestDualView.hpp>
+#include <TestDynamicView.hpp>
+#include <TestSegmentedView.hpp>
+#include <TestComplex.hpp>
+
+#include <Kokkos_DynRankView.hpp>
+#include <TestDynViewAPI.hpp>
+
+#include <iomanip>
+
+namespace Test {
+
+#ifdef KOKKOS_HAVE_OPENMP
+class openmp : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+
+    unsigned threads_count = 4 ;
+
+    if ( Kokkos::hwloc::available() ) {
+      threads_count = Kokkos::hwloc::get_available_numa_count() *
+                      Kokkos::hwloc::get_available_cores_per_numa();
+    }
+
+    Kokkos::OpenMP::initialize( threads_count );
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::OpenMP::finalize();
+  }
+};
+
+TEST_F( openmp, complex )
+{
+  testComplex<Kokkos::OpenMP> ();
+}
+
+TEST_F( openmp, dyn_view_api) {
+  TestDynViewAPI< double , Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, bitset )
+{
+  test_bitset<Kokkos::OpenMP>();
+}
+
+TEST_F( openmp , staticcrsgraph )
+{
+  TestStaticCrsGraph::run_test_graph< Kokkos::OpenMP >();
+  TestStaticCrsGraph::run_test_graph2< Kokkos::OpenMP >();
+}
+
+#define OPENMP_INSERT_TEST( name, num_nodes, num_inserts, num_duplicates, repeat, near )                                \
+  TEST_F( openmp, UnorderedMap_insert_##name##_##num_nodes##_##num_inserts##_##num_duplicates##_##repeat##x) {   \
+    for (int i=0; i<repeat; ++i)                                                                                \
+      test_insert<Kokkos::OpenMP>(num_nodes,num_inserts,num_duplicates, near);                                   \
+  }
+
+#define OPENMP_FAILED_INSERT_TEST( num_nodes, repeat )                         \
+  TEST_F( openmp, UnorderedMap_failed_insert_##num_nodes##_##repeat##x) {     \
+    for (int i=0; i<repeat; ++i)                                               \
+      test_failed_insert<Kokkos::OpenMP>(num_nodes);                             \
+  }
+
+#define OPENMP_ASSIGNEMENT_TEST( num_nodes, repeat )                             \
+  TEST_F( openmp, UnorderedMap_assignment_operators_##num_nodes##_##repeat##x) {       \
+    for (int i=0; i<repeat; ++i)                                               \
+      test_assignement_operators<Kokkos::OpenMP>(num_nodes);                     \
+  }
+
+#define OPENMP_DEEP_COPY( num_nodes, repeat )                             \
+  TEST_F( openmp, UnorderedMap_deep_copy##num_nodes##_##repeat##x) {       \
+    for (int i=0; i<repeat; ++i)                                               \
+      test_deep_copy<Kokkos::OpenMP>(num_nodes);                     \
+  }
+
+#define OPENMP_VECTOR_COMBINE_TEST( size )                             \
+  TEST_F( openmp, vector_combination##size##x) {       \
+      test_vector_combinations<int,Kokkos::OpenMP>(size);                     \
+  }
+
+#define OPENMP_DUALVIEW_COMBINE_TEST( size )                             \
+  TEST_F( openmp, dualview_combination##size##x) {       \
+      test_dualview_combinations<int,Kokkos::OpenMP>(size);                     \
+  }
+
+#define OPENMP_SEGMENTEDVIEW_TEST( size )                             \
+  TEST_F( openmp, segmentedview_##size##x) {       \
+      test_segmented_view<double,Kokkos::OpenMP>(size);                     \
+  }
+
+OPENMP_INSERT_TEST(close, 100000, 90000, 100, 500, true)
+OPENMP_INSERT_TEST(far, 100000, 90000, 100, 500, false)
+OPENMP_FAILED_INSERT_TEST( 10000, 1000 )
+OPENMP_DEEP_COPY( 10000, 1 )
+
+OPENMP_VECTOR_COMBINE_TEST( 10 )
+OPENMP_VECTOR_COMBINE_TEST( 3057 )
+OPENMP_DUALVIEW_COMBINE_TEST( 10 )
+OPENMP_SEGMENTEDVIEW_TEST( 10000 )
+
+#undef OPENMP_INSERT_TEST
+#undef OPENMP_FAILED_INSERT_TEST
+#undef OPENMP_ASSIGNEMENT_TEST
+#undef OPENMP_DEEP_COPY
+#undef OPENMP_VECTOR_COMBINE_TEST
+#undef OPENMP_DUALVIEW_COMBINE_TEST
+#undef OPENMP_SEGMENTEDVIEW_TEST
+#endif
+
+
+TEST_F( openmp , dynamic_view )
+{
+  typedef TestDynamicView< double , Kokkos::OpenMP >
+    TestDynView ;
+
+  for ( int i = 0 ; i < 10 ; ++i ) {
+    TestDynView::run( 100000 + 100 * i );
+  }
+}
+
+} // namespace test
+
diff --git a/lib/kokkos/containers/unit_tests/TestSegmentedView.hpp b/lib/kokkos/containers/unit_tests/TestSegmentedView.hpp
new file mode 100644
index 0000000000..bfd66d12a7
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestSegmentedView.hpp
@@ -0,0 +1,708 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_TEST_SEGMENTEDVIEW_HPP
+#define KOKKOS_TEST_SEGMENTEDVIEW_HPP
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+#include <Kokkos_Core.hpp>
+
+#if ! KOKKOS_USING_EXP_VIEW
+
+#include <Kokkos_SegmentedView.hpp>
+#include <impl/Kokkos_Timer.hpp>
+
+namespace Test {
+
+namespace Impl {
+
+  template<class ViewType , class ExecutionSpace, int Rank = ViewType::Rank>
+  struct GrowTest;
+
+  template<class ViewType , class ExecutionSpace>
+  struct GrowTest<ViewType , ExecutionSpace , 1> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    GrowTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      a.grow(team_member , team_idx+team_member.team_size());
+      value += team_idx + team_member.team_rank();
+
+      if((a.dimension_0()>team_idx+team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+team_member.team_rank()))
+        a(team_idx+team_member.team_rank()) = team_idx+team_member.team_rank();
+
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct GrowTest<ViewType , ExecutionSpace , 2> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    GrowTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      a.grow(team_member , team_idx+ team_member.team_size());
+
+      for( typename ExecutionSpace::size_type k=0;k<7;k++)
+        value += team_idx + team_member.team_rank() + 13*k;
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++) {
+          a(team_idx+ team_member.team_rank(),k) =
+              team_idx+ team_member.team_rank() + 13*k;
+        }
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct GrowTest<ViewType , ExecutionSpace , 3> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    GrowTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      a.grow(team_member , team_idx+ team_member.team_size());
+
+      for( typename ExecutionSpace::size_type k=0;k<7;k++)
+        for( typename ExecutionSpace::size_type l=0;l<3;l++)
+          value += team_idx + team_member.team_rank() + 13*k + 3*l;
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            a(team_idx+ team_member.team_rank(),k,l) =
+                team_idx+ team_member.team_rank() + 13*k + 3*l;
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct GrowTest<ViewType , ExecutionSpace , 4> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    GrowTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      a.grow(team_member , team_idx+ team_member.team_size());
+
+      for( typename ExecutionSpace::size_type k=0;k<7;k++)
+        for( typename ExecutionSpace::size_type l=0;l<3;l++)
+          for( typename ExecutionSpace::size_type m=0;m<2;m++)
+            value += team_idx + team_member.team_rank() + 13*k + 3*l + 7*m;
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              a(team_idx+ team_member.team_rank(),k,l,m) =
+                  team_idx+ team_member.team_rank() + 13*k + 3*l + 7*m;
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct GrowTest<ViewType , ExecutionSpace , 5> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    GrowTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      a.grow(team_member , team_idx+ team_member.team_size());
+
+      for( typename ExecutionSpace::size_type k=0;k<7;k++)
+        for( typename ExecutionSpace::size_type l=0;l<3;l++)
+          for( typename ExecutionSpace::size_type m=0;m<2;m++)
+            for( typename ExecutionSpace::size_type n=0;n<3;n++)
+              value +=
+                  team_idx + team_member.team_rank() + 13*k + 3*l + 7*m + 5*n;
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              for( typename ExecutionSpace::size_type n=0;n<a.dimension_4();n++)
+                a(team_idx+ team_member.team_rank(),k,l,m,n) =
+                  team_idx+ team_member.team_rank() + 13*k + 3*l + 7*m + 5*n;
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct GrowTest<ViewType , ExecutionSpace , 6> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    GrowTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      a.grow(team_member , team_idx+ team_member.team_size());
+
+      for( typename ExecutionSpace::size_type k=0;k<7;k++)
+        for( typename ExecutionSpace::size_type l=0;l<3;l++)
+          for( typename ExecutionSpace::size_type m=0;m<2;m++)
+            for( typename ExecutionSpace::size_type n=0;n<3;n++)
+              for( typename ExecutionSpace::size_type o=0;o<2;o++)
+              value +=
+                  team_idx + team_member.team_rank() + 13*k + 3*l + 7*m + 5*n + 2*o ;
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              for( typename ExecutionSpace::size_type n=0;n<a.dimension_4();n++)
+                for( typename ExecutionSpace::size_type o=0;o<a.dimension_5();o++)
+                a(team_idx+ team_member.team_rank(),k,l,m,n,o) =
+                    team_idx + team_member.team_rank() + 13*k + 3*l + 7*m + 5*n + 2*o ;
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct GrowTest<ViewType , ExecutionSpace , 7> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    GrowTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      a.grow(team_member , team_idx+ team_member.team_size());
+
+      for( typename ExecutionSpace::size_type k=0;k<7;k++)
+        for( typename ExecutionSpace::size_type l=0;l<3;l++)
+          for( typename ExecutionSpace::size_type m=0;m<2;m++)
+            for( typename ExecutionSpace::size_type n=0;n<3;n++)
+              for( typename ExecutionSpace::size_type o=0;o<2;o++)
+                for( typename ExecutionSpace::size_type p=0;p<4;p++)
+              value +=
+                  team_idx + team_member.team_rank() + 13*k + 3*l + 7*m + 5*n + 2*o + 15*p ;
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              for( typename ExecutionSpace::size_type n=0;n<a.dimension_4();n++)
+                for( typename ExecutionSpace::size_type o=0;o<a.dimension_5();o++)
+                  for( typename ExecutionSpace::size_type p=0;p<a.dimension_6();p++)
+                a(team_idx+ team_member.team_rank(),k,l,m,n,o,p) =
+                    team_idx + team_member.team_rank() + 13*k + 3*l + 7*m + 5*n + 2*o + 15*p ;
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct GrowTest<ViewType , ExecutionSpace , 8> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    GrowTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+      a.grow(team_member , team_idx + team_member.team_size());
+
+      for( typename ExecutionSpace::size_type k=0;k<7;k++)
+        for( typename ExecutionSpace::size_type l=0;l<3;l++)
+          for( typename ExecutionSpace::size_type m=0;m<2;m++)
+            for( typename ExecutionSpace::size_type n=0;n<3;n++)
+              for( typename ExecutionSpace::size_type o=0;o<2;o++)
+                for( typename ExecutionSpace::size_type p=0;p<4;p++)
+                  for( typename ExecutionSpace::size_type q=0;q<3;q++)
+              value +=
+                  team_idx + team_member.team_rank() + 13*k + 3*l + 7*m + 5*n + 2*o + 15*p + 17*q;
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              for( typename ExecutionSpace::size_type n=0;n<a.dimension_4();n++)
+                for( typename ExecutionSpace::size_type o=0;o<a.dimension_5();o++)
+                  for( typename ExecutionSpace::size_type p=0;p<a.dimension_6();p++)
+                    for( typename ExecutionSpace::size_type q=0;q<a.dimension_7();q++)
+                a(team_idx+ team_member.team_rank(),k,l,m,n,o,p,q) =
+                    team_idx + team_member.team_rank() + 13*k + 3*l + 7*m + 5*n + 2*o + 15*p + 17*q;
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace, int Rank = ViewType::Rank>
+  struct VerifyTest;
+
+  template<class ViewType , class ExecutionSpace>
+  struct VerifyTest<ViewType , ExecutionSpace , 1> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    VerifyTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        value += a(team_idx+ team_member.team_rank());
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct VerifyTest<ViewType , ExecutionSpace , 2> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    VerifyTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          value += a(team_idx+ team_member.team_rank(),k);
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct VerifyTest<ViewType , ExecutionSpace , 3> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    VerifyTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            value += a(team_idx+ team_member.team_rank(),k,l);
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct VerifyTest<ViewType , ExecutionSpace , 4> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    VerifyTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              value += a(team_idx+ team_member.team_rank(),k,l,m);
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct VerifyTest<ViewType , ExecutionSpace , 5> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    VerifyTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              for( typename ExecutionSpace::size_type n=0;n<a.dimension_4();n++)
+                value += a(team_idx+ team_member.team_rank(),k,l,m,n);
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct VerifyTest<ViewType , ExecutionSpace , 6> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    VerifyTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              for( typename ExecutionSpace::size_type n=0;n<a.dimension_4();n++)
+                for( typename ExecutionSpace::size_type o=0;o<a.dimension_5();o++)
+                  value += a(team_idx+ team_member.team_rank(),k,l,m,n,o);
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct VerifyTest<ViewType , ExecutionSpace , 7> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    VerifyTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              for( typename ExecutionSpace::size_type n=0;n<a.dimension_4();n++)
+                for( typename ExecutionSpace::size_type o=0;o<a.dimension_5();o++)
+                  for( typename ExecutionSpace::size_type p=0;p<a.dimension_6();p++)
+                    value += a(team_idx+ team_member.team_rank(),k,l,m,n,o,p);
+      }
+    }
+  };
+
+  template<class ViewType , class ExecutionSpace>
+  struct VerifyTest<ViewType , ExecutionSpace , 8> {
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+    typedef typename Policy::member_type team_type;
+    typedef double value_type;
+
+    ViewType a;
+
+    VerifyTest(ViewType in):a(in) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (team_type team_member, double& value) const {
+      unsigned int team_idx = team_member.league_rank() * team_member.team_size();
+
+      if((a.dimension_0()>team_idx+ team_member.team_rank()) &&
+         (a.dimension(0)>team_idx+ team_member.team_rank())) {
+        for( typename ExecutionSpace::size_type k=0;k<a.dimension_1();k++)
+          for( typename ExecutionSpace::size_type l=0;l<a.dimension_2();l++)
+            for( typename ExecutionSpace::size_type m=0;m<a.dimension_3();m++)
+              for( typename ExecutionSpace::size_type n=0;n<a.dimension_4();n++)
+                for( typename ExecutionSpace::size_type o=0;o<a.dimension_5();o++)
+                  for( typename ExecutionSpace::size_type p=0;p<a.dimension_6();p++)
+                    for( typename ExecutionSpace::size_type q=0;q<a.dimension_7();q++)
+                      value += a(team_idx+ team_member.team_rank(),k,l,m,n,o,p,q);
+      }
+    }
+  };
+
+  template <typename Scalar, class ExecutionSpace>
+  struct test_segmented_view
+  {
+    typedef test_segmented_view<Scalar,ExecutionSpace> self_type;
+
+    typedef Scalar scalar_type;
+    typedef ExecutionSpace execution_space;
+    typedef Kokkos::TeamPolicy<execution_space> Policy;
+
+    double result;
+    double reference;
+
+    template <class ViewType>
+    void run_me(ViewType a, int max_length){
+      const int team_size = Policy::team_size_max( GrowTest<ViewType,execution_space>(a) );
+      const int nteams = max_length/team_size;
+
+      reference = 0;
+      result = 0;
+
+      Kokkos::parallel_reduce(Policy(nteams,team_size),GrowTest<ViewType,execution_space>(a),reference);
+      Kokkos::fence();
+      Kokkos::parallel_reduce(Policy(nteams,team_size),VerifyTest<ViewType,execution_space>(a),result);
+      Kokkos::fence();
+    }
+
+
+    test_segmented_view(unsigned int size,int rank)
+    {
+      reference = 0;
+      result = 0;
+
+      const int dim_1 = 7;
+      const int dim_2 = 3;
+      const int dim_3 = 2;
+      const int dim_4 = 3;
+      const int dim_5 = 2;
+      const int dim_6 = 4;
+      //const int dim_7 = 3;
+
+      if(rank==1) {
+        typedef Kokkos::Experimental::SegmentedView<Scalar*,Kokkos::LayoutLeft,ExecutionSpace> rank1_view;
+        run_me< rank1_view >(rank1_view("Rank1",128,size), size);
+      }
+      if(rank==2) {
+        typedef Kokkos::Experimental::SegmentedView<Scalar**,Kokkos::LayoutLeft,ExecutionSpace> rank2_view;
+        run_me< rank2_view >(rank2_view("Rank2",128,size,dim_1), size);
+      }
+      if(rank==3) {
+        typedef Kokkos::Experimental::SegmentedView<Scalar*[7][3][2],Kokkos::LayoutRight,ExecutionSpace> rank3_view;
+        run_me< rank3_view >(rank3_view("Rank3",128,size), size);
+      }
+      if(rank==4) {
+        typedef Kokkos::Experimental::SegmentedView<Scalar****,Kokkos::LayoutRight,ExecutionSpace> rank4_view;
+        run_me< rank4_view >(rank4_view("Rank4",128,size,dim_1,dim_2,dim_3), size);
+      }
+      if(rank==5) {
+        typedef Kokkos::Experimental::SegmentedView<Scalar*[7][3][2][3],Kokkos::LayoutLeft,ExecutionSpace> rank5_view;
+        run_me< rank5_view >(rank5_view("Rank5",128,size), size);
+      }
+      if(rank==6) {
+        typedef Kokkos::Experimental::SegmentedView<Scalar*****[2],Kokkos::LayoutRight,ExecutionSpace> rank6_view;
+        run_me< rank6_view >(rank6_view("Rank6",128,size,dim_1,dim_2,dim_3,dim_4), size);
+      }
+      if(rank==7) {
+        typedef Kokkos::Experimental::SegmentedView<Scalar*******,Kokkos::LayoutLeft,ExecutionSpace> rank7_view;
+        run_me< rank7_view >(rank7_view("Rank7",128,size,dim_1,dim_2,dim_3,dim_4,dim_5,dim_6), size);
+      }
+      if(rank==8) {
+        typedef Kokkos::Experimental::SegmentedView<Scalar*****[2][4][3],Kokkos::LayoutLeft,ExecutionSpace> rank8_view;
+        run_me< rank8_view >(rank8_view("Rank8",128,size,dim_1,dim_2,dim_3,dim_4), size);
+      }
+    }
+
+   };
+
+} // namespace Impl
+
+
+
+
+template <typename Scalar, class ExecutionSpace>
+void test_segmented_view(unsigned int size)
+{
+  {
+    typedef Kokkos::Experimental::SegmentedView<Scalar*****[2][4][3],Kokkos::LayoutLeft,ExecutionSpace> view_type;
+    view_type a("A",128,size,7,3,2,3);
+    double reference;
+
+    Impl::GrowTest<view_type,ExecutionSpace> f(a);
+
+    const int team_size = Kokkos::TeamPolicy<ExecutionSpace>::team_size_max( f );
+    const int nteams = (size+team_size-1)/team_size;
+
+    Kokkos::parallel_reduce(Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size),f,reference);
+
+    size_t real_size = ((size+127)/128)*128;
+
+    ASSERT_EQ(real_size,a.dimension_0());
+    ASSERT_EQ(7,a.dimension_1());
+    ASSERT_EQ(3,a.dimension_2());
+    ASSERT_EQ(2,a.dimension_3());
+    ASSERT_EQ(3,a.dimension_4());
+    ASSERT_EQ(2,a.dimension_5());
+    ASSERT_EQ(4,a.dimension_6());
+    ASSERT_EQ(3,a.dimension_7());
+    ASSERT_EQ(real_size,a.dimension(0));
+    ASSERT_EQ(7,a.dimension(1));
+    ASSERT_EQ(3,a.dimension(2));
+    ASSERT_EQ(2,a.dimension(3));
+    ASSERT_EQ(3,a.dimension(4));
+    ASSERT_EQ(2,a.dimension(5));
+    ASSERT_EQ(4,a.dimension(6));
+    ASSERT_EQ(3,a.dimension(7));
+    ASSERT_EQ(8,a.Rank);
+  }
+  {
+    Impl::test_segmented_view<Scalar,ExecutionSpace> test(size,1);
+    ASSERT_EQ(test.reference,test.result);
+  }
+  {
+    Impl::test_segmented_view<Scalar,ExecutionSpace> test(size,2);
+    ASSERT_EQ(test.reference,test.result);
+  }
+  {
+    Impl::test_segmented_view<Scalar,ExecutionSpace> test(size,3);
+    ASSERT_EQ(test.reference,test.result);
+  }
+  {
+    Impl::test_segmented_view<Scalar,ExecutionSpace> test(size,4);
+    ASSERT_EQ(test.reference,test.result);
+  }
+  {
+    Impl::test_segmented_view<Scalar,ExecutionSpace> test(size,5);
+    ASSERT_EQ(test.reference,test.result);
+  }
+  {
+    Impl::test_segmented_view<Scalar,ExecutionSpace> test(size,6);
+    ASSERT_EQ(test.reference,test.result);
+  }
+  {
+    Impl::test_segmented_view<Scalar,ExecutionSpace> test(size,7);
+    ASSERT_EQ(test.reference,test.result);
+  }
+  {
+    Impl::test_segmented_view<Scalar,ExecutionSpace> test(size,8);
+    ASSERT_EQ(test.reference,test.result);
+  }
+
+}
+
+
+} // namespace Test
+
+#else
+
+template <typename Scalar, class ExecutionSpace>
+void test_segmented_view(unsigned int ) {}
+
+#endif
+
+#endif /* #ifndef KOKKOS_TEST_SEGMENTEDVIEW_HPP */
+
diff --git a/lib/kokkos/containers/unit_tests/TestSerial.cpp b/lib/kokkos/containers/unit_tests/TestSerial.cpp
new file mode 100644
index 0000000000..a7c42d2798
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestSerial.cpp
@@ -0,0 +1,175 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#if ! defined(KOKKOS_HAVE_SERIAL)
+#  error "It doesn't make sense to build this file unless the Kokkos::Serial device is enabled.  If you see this message, it probably means that there is an error in Kokkos' CMake build infrastructure."
+#else
+
+#include <Kokkos_Bitset.hpp>
+#include <Kokkos_UnorderedMap.hpp>
+#include <Kokkos_Vector.hpp>
+
+#include <TestBitset.hpp>
+#include <TestUnorderedMap.hpp>
+#include <TestStaticCrsGraph.hpp>
+#include <TestVector.hpp>
+#include <TestDualView.hpp>
+#include <TestSegmentedView.hpp>
+#include <TestDynamicView.hpp>
+#include <TestComplex.hpp>
+
+#include <iomanip>
+
+#include <Kokkos_DynRankView.hpp>
+#include <TestDynViewAPI.hpp>
+
+namespace Test {
+
+class serial : public ::testing::Test {
+protected:
+  static void SetUpTestCase () {
+    std::cout << std::setprecision(5) << std::scientific;
+    Kokkos::Serial::initialize ();
+  }
+
+  static void TearDownTestCase () {
+    Kokkos::Serial::finalize ();
+  }
+};
+
+TEST_F( serial, dyn_view_api) {
+  TestDynViewAPI< double , Kokkos::Serial >();
+}
+
+TEST_F( serial , staticcrsgraph )
+{
+  TestStaticCrsGraph::run_test_graph< Kokkos::Serial >();
+  TestStaticCrsGraph::run_test_graph2< Kokkos::Serial >();
+}
+
+TEST_F( serial, complex )
+{
+  testComplex<Kokkos::Serial> ();
+}
+
+TEST_F( serial, bitset )
+{
+  test_bitset<Kokkos::Serial> ();
+}
+
+#define SERIAL_INSERT_TEST( name, num_nodes, num_inserts, num_duplicates, repeat, near ) \
+  TEST_F( serial, UnorderedMap_insert_##name##_##num_nodes##_##num_inserts##_##num_duplicates##_##repeat##x) { \
+    for (int i=0; i<repeat; ++i)                                        \
+      test_insert<Kokkos::Serial> (num_nodes, num_inserts, num_duplicates, near); \
+  }
+
+#define SERIAL_FAILED_INSERT_TEST( num_nodes, repeat )                  \
+  TEST_F( serial, UnorderedMap_failed_insert_##num_nodes##_##repeat##x) { \
+    for (int i=0; i<repeat; ++i)                                        \
+      test_failed_insert<Kokkos::Serial> (num_nodes);                   \
+  }
+
+#define SERIAL_ASSIGNEMENT_TEST( num_nodes, repeat )                    \
+  TEST_F( serial, UnorderedMap_assignment_operators_##num_nodes##_##repeat##x) { \
+    for (int i=0; i<repeat; ++i)                                        \
+      test_assignement_operators<Kokkos::Serial> (num_nodes);           \
+  }
+
+#define SERIAL_DEEP_COPY( num_nodes, repeat )                           \
+  TEST_F( serial, UnorderedMap_deep_copy##num_nodes##_##repeat##x) {    \
+    for (int i=0; i<repeat; ++i)                                        \
+      test_deep_copy<Kokkos::Serial> (num_nodes);                       \
+  }
+
+#define SERIAL_VECTOR_COMBINE_TEST( size )             \
+  TEST_F( serial, vector_combination##size##x) {                        \
+    test_vector_combinations<int,Kokkos::Serial>(size);                 \
+  }
+
+#define SERIAL_DUALVIEW_COMBINE_TEST( size )             \
+  TEST_F( serial, dualview_combination##size##x) {                      \
+    test_dualview_combinations<int,Kokkos::Serial>(size);               \
+  }
+
+#define SERIAL_SEGMENTEDVIEW_TEST( size )                               \
+  TEST_F( serial, segmentedview_##size##x) {                            \
+    test_segmented_view<double,Kokkos::Serial>(size);                   \
+  }
+
+SERIAL_INSERT_TEST(close, 100000, 90000, 100, 500, true)
+SERIAL_INSERT_TEST(far, 100000, 90000, 100, 500, false)
+SERIAL_FAILED_INSERT_TEST( 10000, 1000 )
+SERIAL_DEEP_COPY( 10000, 1 )
+
+SERIAL_VECTOR_COMBINE_TEST( 10 )
+SERIAL_VECTOR_COMBINE_TEST( 3057 )
+SERIAL_DUALVIEW_COMBINE_TEST( 10 )
+SERIAL_SEGMENTEDVIEW_TEST( 10000 )
+
+#undef SERIAL_INSERT_TEST
+#undef SERIAL_FAILED_INSERT_TEST
+#undef SERIAL_ASSIGNEMENT_TEST
+#undef SERIAL_DEEP_COPY
+#undef SERIAL_VECTOR_COMBINE_TEST
+#undef SERIAL_DUALVIEW_COMBINE_TEST
+#undef SERIAL_SEGMENTEDVIEW_TEST
+
+TEST_F( serial , dynamic_view )
+{
+  typedef TestDynamicView< double , Kokkos::Serial >
+    TestDynView ;
+
+  for ( int i = 0 ; i < 10 ; ++i ) {
+    TestDynView::run( 100000 + 100 * i );
+  }
+}
+
+} // namespace Test
+
+#endif // KOKKOS_HAVE_SERIAL
+
+
diff --git a/lib/kokkos/containers/unit_tests/TestStaticCrsGraph.hpp b/lib/kokkos/containers/unit_tests/TestStaticCrsGraph.hpp
new file mode 100644
index 0000000000..52b45b7865
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestStaticCrsGraph.hpp
@@ -0,0 +1,149 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <vector>
+
+#include <Kokkos_StaticCrsGraph.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace TestStaticCrsGraph {
+
+template< class Space >
+void run_test_graph()
+{
+  typedef Kokkos::StaticCrsGraph< unsigned , Space > dView ;
+  typedef typename dView::HostMirror hView ;
+
+  const unsigned LENGTH = 1000 ;
+  dView dx ;
+  hView hx ;
+
+  std::vector< std::vector< int > > graph( LENGTH );
+
+  for ( size_t i = 0 ; i < LENGTH ; ++i ) {
+    graph[i].reserve(8);
+    for ( size_t j = 0 ; j < 8 ; ++j ) {
+      graph[i].push_back( i + j * 3 );
+    }
+  }
+
+  dx = Kokkos::create_staticcrsgraph<dView>( "dx" , graph );
+    hx = Kokkos::create_mirror( dx );
+
+  ASSERT_EQ( hx.row_map.dimension_0() - 1 , LENGTH );
+
+  for ( size_t i = 0 ; i < LENGTH ; ++i ) {
+    const size_t begin = hx.row_map[i];
+    const size_t n = hx.row_map[i+1] - begin ;
+    ASSERT_EQ( n , graph[i].size() );
+    for ( size_t j = 0 ; j < n ; ++j ) {
+      ASSERT_EQ( (int) hx.entries( j + begin ) , graph[i][j] );
+    }
+  }
+}
+
+template< class Space >
+void run_test_graph2()
+{
+  typedef Kokkos::StaticCrsGraph< unsigned[3] , Space > dView ;
+  typedef typename dView::HostMirror hView ;
+
+  const unsigned LENGTH = 10 ;
+
+  std::vector< size_t > sizes( LENGTH );
+
+  size_t total_length = 0 ;
+
+  for ( size_t i = 0 ; i < LENGTH ; ++i ) {
+    total_length += ( sizes[i] = 6 + i % 4 );
+  }
+
+  dView dx = Kokkos::create_staticcrsgraph<dView>( "test" , sizes );
+  hView hx = Kokkos::create_mirror( dx );
+  hView mx = Kokkos::create_mirror( dx );
+
+  ASSERT_EQ( (size_t) dx.row_map.dimension_0() , (size_t) LENGTH + 1 );
+  ASSERT_EQ( (size_t) hx.row_map.dimension_0() , (size_t) LENGTH + 1 );
+  ASSERT_EQ( (size_t) mx.row_map.dimension_0() , (size_t) LENGTH + 1 );
+
+  ASSERT_EQ( (size_t) dx.entries.dimension_0() , (size_t) total_length );
+  ASSERT_EQ( (size_t) hx.entries.dimension_0() , (size_t) total_length );
+  ASSERT_EQ( (size_t) mx.entries.dimension_0() , (size_t) total_length );
+
+  ASSERT_EQ( (size_t) dx.entries.dimension_1() , (size_t) 3 );
+  ASSERT_EQ( (size_t) hx.entries.dimension_1() , (size_t) 3 );
+  ASSERT_EQ( (size_t) mx.entries.dimension_1() , (size_t) 3 );
+
+  for ( size_t i = 0 ; i < LENGTH ; ++i ) {
+    const size_t entry_begin = hx.row_map[i];
+    const size_t entry_end   = hx.row_map[i+1];
+    for ( size_t j = entry_begin ; j < entry_end ; ++j ) {
+      hx.entries(j,0) = j + 1 ;
+      hx.entries(j,1) = j + 2 ;
+      hx.entries(j,2) = j + 3 ;
+    }
+  }
+
+  Kokkos::deep_copy( dx.entries , hx.entries );
+  Kokkos::deep_copy( mx.entries , dx.entries );
+
+  ASSERT_EQ( mx.row_map.dimension_0() , (size_t) LENGTH + 1 );
+
+  for ( size_t i = 0 ; i < LENGTH ; ++i ) {
+    const size_t entry_begin = mx.row_map[i];
+    const size_t entry_end   = mx.row_map[i+1];
+    ASSERT_EQ( ( entry_end - entry_begin ) , sizes[i] );
+    for ( size_t j = entry_begin ; j < entry_end ; ++j ) {
+      ASSERT_EQ( (size_t) mx.entries( j , 0 ) , ( j + 1 ) );
+      ASSERT_EQ( (size_t) mx.entries( j , 1 ) , ( j + 2 ) );
+      ASSERT_EQ( (size_t) mx.entries( j , 2 ) , ( j + 3 ) );
+    }
+  }
+}
+
+} /* namespace TestStaticCrsGraph */
+
+
diff --git a/lib/kokkos/containers/unit_tests/TestThreads.cpp b/lib/kokkos/containers/unit_tests/TestThreads.cpp
new file mode 100644
index 0000000000..58277528d3
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestThreads.cpp
@@ -0,0 +1,188 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+
+#include <Kokkos_Bitset.hpp>
+#include <Kokkos_UnorderedMap.hpp>
+
+#include <Kokkos_Vector.hpp>
+#include <iomanip>
+
+
+//----------------------------------------------------------------------------
+#include <TestBitset.hpp>
+#include <TestUnorderedMap.hpp>
+#include <TestStaticCrsGraph.hpp>
+
+#include <TestVector.hpp>
+#include <TestDualView.hpp>
+#include <TestDynamicView.hpp>
+#include <TestSegmentedView.hpp>
+
+#include <Kokkos_DynRankView.hpp>
+#include <TestDynViewAPI.hpp>
+
+namespace Test {
+
+class threads : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    std::cout << std::setprecision(5) << std::scientific;
+
+    unsigned num_threads = 4;
+
+    if (Kokkos::hwloc::available()) {
+      num_threads = Kokkos::hwloc::get_available_numa_count()
+                    * Kokkos::hwloc::get_available_cores_per_numa()
+                 // * Kokkos::hwloc::get_available_threads_per_core()
+                    ;
+
+    }
+
+    std::cout << "Threads: " << num_threads << std::endl;
+
+    Kokkos::Threads::initialize( num_threads );
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::Threads::finalize();
+  }
+};
+
+TEST_F( threads , dyn_view_api) {
+  TestDynViewAPI< double , Kokkos::Threads >();
+}
+
+TEST_F( threads , staticcrsgraph )
+{
+  TestStaticCrsGraph::run_test_graph< Kokkos::Threads >();
+  TestStaticCrsGraph::run_test_graph2< Kokkos::Threads >();
+}
+
+/*TEST_F( threads, bitset )
+{
+  test_bitset<Kokkos::Threads>();
+}*/
+
+#define THREADS_INSERT_TEST( name, num_nodes, num_inserts, num_duplicates, repeat, near )                                \
+  TEST_F( threads, UnorderedMap_insert_##name##_##num_nodes##_##num_inserts##_##num_duplicates##_##repeat##x) {   \
+    for (int i=0; i<repeat; ++i)                                                                                \
+      test_insert<Kokkos::Threads>(num_nodes,num_inserts,num_duplicates, near);                                   \
+  }
+
+#define THREADS_FAILED_INSERT_TEST( num_nodes, repeat )                            \
+  TEST_F( threads, UnorderedMap_failed_insert_##num_nodes##_##repeat##x) {       \
+    for (int i=0; i<repeat; ++i)                                               \
+      test_failed_insert<Kokkos::Threads>(num_nodes);                             \
+  }
+
+#define THREADS_ASSIGNEMENT_TEST( num_nodes, repeat )                             \
+  TEST_F( threads, UnorderedMap_assignment_operators_##num_nodes##_##repeat##x) {       \
+    for (int i=0; i<repeat; ++i)                                               \
+      test_assignement_operators<Kokkos::Threads>(num_nodes);                     \
+  }
+
+#define THREADS_DEEP_COPY( num_nodes, repeat )                             \
+  TEST_F( threads, UnorderedMap_deep_copy##num_nodes##_##repeat##x) {       \
+    for (int i=0; i<repeat; ++i)                                               \
+      test_deep_copy<Kokkos::Threads>(num_nodes);                     \
+  }
+
+#define THREADS_VECTOR_COMBINE_TEST( size )                             \
+  TEST_F( threads, vector_combination##size##x) {       \
+      test_vector_combinations<int,Kokkos::Threads>(size);                     \
+  }
+
+#define THREADS_DUALVIEW_COMBINE_TEST( size )                             \
+  TEST_F( threads, dualview_combination##size##x) {       \
+      test_dualview_combinations<int,Kokkos::Threads>(size);                     \
+  }
+
+#define THREADS_SEGMENTEDVIEW_TEST( size )                             \
+  TEST_F( threads, segmentedview_##size##x) {       \
+      test_segmented_view<double,Kokkos::Threads>(size);                     \
+  }
+
+
+THREADS_INSERT_TEST(far, 100000, 90000, 100, 500, false)
+THREADS_FAILED_INSERT_TEST( 10000, 1000 )
+THREADS_DEEP_COPY( 10000, 1 )
+
+THREADS_VECTOR_COMBINE_TEST( 10 )
+THREADS_VECTOR_COMBINE_TEST( 3057 )
+THREADS_DUALVIEW_COMBINE_TEST( 10 )
+THREADS_SEGMENTEDVIEW_TEST( 10000 )
+
+
+#undef THREADS_INSERT_TEST
+#undef THREADS_FAILED_INSERT_TEST
+#undef THREADS_ASSIGNEMENT_TEST
+#undef THREADS_DEEP_COPY
+#undef THREADS_VECTOR_COMBINE_TEST
+#undef THREADS_DUALVIEW_COMBINE_TEST
+#undef THREADS_SEGMENTEDVIEW_TEST
+
+
+
+TEST_F( threads , dynamic_view )
+{
+  typedef TestDynamicView< double , Kokkos::Threads >
+    TestDynView ;
+
+  for ( int i = 0 ; i < 10 ; ++i ) {
+    TestDynView::run( 100000 + 100 * i );
+  }
+}
+
+} // namespace Test
+
+
+#endif /* #if defined( KOKKOS_HAVE_PTHREAD ) */
+
diff --git a/lib/kokkos/containers/unit_tests/TestUnorderedMap.hpp b/lib/kokkos/containers/unit_tests/TestUnorderedMap.hpp
new file mode 100644
index 0000000000..ff0328548d
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestUnorderedMap.hpp
@@ -0,0 +1,313 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_TEST_UNORDERED_MAP_HPP
+#define KOKKOS_TEST_UNORDERED_MAP_HPP
+
+#include <gtest/gtest.h>
+#include <iostream>
+
+
+namespace Test {
+
+namespace Impl {
+
+template <typename MapType, bool Near = false>
+struct TestInsert
+{
+  typedef MapType map_type;
+  typedef typename map_type::execution_space execution_space;
+  typedef uint32_t value_type;
+
+  map_type map;
+  uint32_t inserts;
+  uint32_t collisions;
+
+  TestInsert( map_type arg_map, uint32_t arg_inserts, uint32_t arg_collisions)
+    : map(arg_map)
+    , inserts(arg_inserts)
+    , collisions(arg_collisions)
+  {}
+
+  void testit( bool rehash_on_fail = true )
+  {
+    execution_space::fence();
+
+    uint32_t failed_count = 0;
+    do {
+      failed_count = 0;
+      Kokkos::parallel_reduce(inserts, *this, failed_count);
+
+      if (rehash_on_fail && failed_count > 0u) {
+        const uint32_t new_capacity = map.capacity() + ((map.capacity()*3ull)/20u) + failed_count/collisions ;
+        map.rehash( new_capacity );
+      }
+    } while (rehash_on_fail && failed_count > 0u);
+
+    execution_space::fence();
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & failed_count ) const { failed_count = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & failed_count, const volatile value_type & count ) const
+  { failed_count += count; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(uint32_t i, value_type & failed_count) const
+  {
+    const uint32_t key = Near ? i/collisions : i%(inserts/collisions);
+    if (map.insert(key,i).failed()) ++failed_count;
+  }
+
+};
+
+  template <typename MapType, bool Near>
+  struct TestErase
+  {
+    typedef TestErase<MapType, Near> self_type;
+
+    typedef MapType map_type;
+    typedef typename MapType::execution_space execution_space;
+
+    map_type m_map;
+    uint32_t m_num_erase;
+    uint32_t m_num_duplicates;
+
+    TestErase(map_type map, uint32_t num_erases, uint32_t num_duplicates)
+      : m_map(map)
+      , m_num_erase(num_erases)
+      , m_num_duplicates(num_duplicates)
+    {}
+
+    void testit()
+    {
+      execution_space::fence();
+      Kokkos::parallel_for(m_num_erase, *this);
+      execution_space::fence();
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()(typename execution_space::size_type i) const
+    {
+      if (Near) {
+        m_map.erase(i/m_num_duplicates);
+      }
+      else {
+        m_map.erase(i%(m_num_erase/m_num_duplicates));
+      }
+
+    }
+  };
+
+  template <typename MapType>
+  struct TestFind
+  {
+    typedef MapType map_type;
+    typedef typename MapType::execution_space::execution_space execution_space;
+    typedef uint32_t value_type;
+
+    map_type m_map;
+    uint32_t m_num_insert;
+    uint32_t m_num_duplicates;
+    uint32_t m_max_key;
+
+    TestFind(map_type map, uint32_t num_inserts, uint32_t num_duplicates)
+      : m_map(map)
+      , m_num_insert(num_inserts)
+      , m_num_duplicates(num_duplicates)
+      , m_max_key( ((num_inserts + num_duplicates) - 1)/num_duplicates )
+    {}
+
+    void testit(value_type &errors)
+    {
+      execution_space::execution_space::fence();
+      Kokkos::parallel_reduce(m_map.capacity(), *this, errors);
+      execution_space::execution_space::fence();
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    static void init( value_type & dst)
+    {
+      dst = 0;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    static void join( volatile value_type & dst, const volatile value_type & src)
+    { dst += src; }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()(typename execution_space::size_type i, value_type & errors) const
+    {
+      const bool expect_to_find_i = (i < m_max_key);
+
+      const bool exists = m_map.exists(i);
+
+      if (expect_to_find_i && !exists)  ++errors;
+      if (!expect_to_find_i && exists)  ++errors;
+    }
+  };
+
+} // namespace Impl
+
+
+
+template <typename Device>
+void test_insert( uint32_t num_nodes , uint32_t num_inserts , uint32_t num_duplicates , bool near )
+{
+  typedef Kokkos::UnorderedMap<uint32_t,uint32_t, Device> map_type;
+  typedef Kokkos::UnorderedMap<const uint32_t,const uint32_t, Device> const_map_type;
+
+  const uint32_t expected_inserts = (num_inserts + num_duplicates -1u) / num_duplicates;
+
+  map_type map;
+  map.rehash(num_nodes,false);
+
+  if (near) {
+    Impl::TestInsert<map_type,true> test_insert(map, num_inserts, num_duplicates);
+    test_insert.testit();
+  } else
+  {
+    Impl::TestInsert<map_type,false> test_insert(map, num_inserts, num_duplicates);
+    test_insert.testit();
+  }
+
+  const bool print_list = false;
+  if (print_list) {
+    Kokkos::Impl::UnorderedMapPrint<map_type> f(map);
+    f.apply();
+  }
+
+  const uint32_t map_size = map.size();
+
+  ASSERT_FALSE( map.failed_insert());
+  {
+    EXPECT_EQ(expected_inserts, map_size);
+
+    {
+      uint32_t find_errors = 0;
+      Impl::TestFind<const_map_type> test_find(map, num_inserts, num_duplicates);
+      test_find.testit(find_errors);
+      EXPECT_EQ( 0u, find_errors);
+    }
+
+    map.begin_erase();
+    Impl::TestErase<map_type,false> test_erase(map, num_inserts, num_duplicates);
+    test_erase.testit();
+    map.end_erase();
+    EXPECT_EQ(0u, map.size());
+  }
+}
+
+template <typename Device>
+void test_failed_insert( uint32_t num_nodes)
+{
+  typedef Kokkos::UnorderedMap<uint32_t,uint32_t, Device> map_type;
+
+  map_type map(num_nodes);
+  Impl::TestInsert<map_type> test_insert(map, 2u*num_nodes, 1u);
+  test_insert.testit(false /*don't rehash on fail*/);
+  Device::execution_space::fence();
+
+  EXPECT_TRUE( map.failed_insert() );
+}
+
+
+
+template <typename Device>
+void test_deep_copy( uint32_t num_nodes )
+{
+  typedef Kokkos::UnorderedMap<uint32_t,uint32_t, Device> map_type;
+  typedef Kokkos::UnorderedMap<const uint32_t, const uint32_t, Device> const_map_type;
+
+  typedef typename map_type::HostMirror host_map_type ;
+  // typedef Kokkos::UnorderedMap<uint32_t, uint32_t, typename Device::host_mirror_execution_space > host_map_type;
+
+  map_type map;
+  map.rehash(num_nodes,false);
+
+  {
+    Impl::TestInsert<map_type> test_insert(map, num_nodes, 1);
+    test_insert.testit();
+    ASSERT_EQ( map.size(), num_nodes);
+    ASSERT_FALSE( map.failed_insert() );
+    {
+      uint32_t find_errors = 0;
+      Impl::TestFind<map_type> test_find(map, num_nodes, 1);
+      test_find.testit(find_errors);
+      EXPECT_EQ( find_errors, 0u);
+    }
+
+  }
+
+  host_map_type hmap;
+  Kokkos::deep_copy(hmap, map);
+
+  ASSERT_EQ( map.size(), hmap.size());
+  ASSERT_EQ( map.capacity(), hmap.capacity());
+  {
+    uint32_t find_errors = 0;
+    Impl::TestFind<host_map_type> test_find(hmap, num_nodes, 1);
+    test_find.testit(find_errors);
+    EXPECT_EQ( find_errors, 0u);
+  }
+
+  map_type mmap;
+  Kokkos::deep_copy(mmap, hmap);
+
+  const_map_type cmap = mmap;
+
+  EXPECT_EQ( cmap.size(), num_nodes);
+
+  {
+    uint32_t find_errors = 0;
+    Impl::TestFind<const_map_type> test_find(cmap, num_nodes, 1);
+    test_find.testit(find_errors);
+    EXPECT_EQ( find_errors, 0u);
+  }
+
+}
+
+} // namespace Test
+
+#endif //KOKKOS_TEST_UNORDERED_MAP_HPP
diff --git a/lib/kokkos/containers/unit_tests/TestVector.hpp b/lib/kokkos/containers/unit_tests/TestVector.hpp
new file mode 100644
index 0000000000..f9f4564898
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/TestVector.hpp
@@ -0,0 +1,131 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_TEST_VECTOR_HPP
+#define KOKKOS_TEST_VECTOR_HPP
+
+#include <gtest/gtest.h>
+#include <iostream>
+#include <cstdlib>
+#include <cstdio>
+#include <impl/Kokkos_Timer.hpp>
+
+namespace Test {
+
+namespace Impl {
+
+  template <typename Scalar, class Device>
+  struct test_vector_combinations
+  {
+    typedef test_vector_combinations<Scalar,Device> self_type;
+
+    typedef Scalar scalar_type;
+    typedef Device execution_space;
+
+    Scalar reference;
+    Scalar result;
+
+    template <typename Vector>
+    Scalar run_me(unsigned int n){
+      Vector a(n,1);
+
+
+      a.push_back(2);
+      a.resize(n+4);
+      a[n+1] = 3;
+      a[n+2] = 4;
+      a[n+3] = 5;
+
+
+      Scalar temp1 = a[2];
+      Scalar temp2 = a[n];
+      Scalar temp3 = a[n+1];
+
+      a.assign(n+2,-1);
+
+      a[2] = temp1;
+      a[n] = temp2;
+      a[n+1] = temp3;
+
+      Scalar test1 = 0;
+      for(unsigned int i=0; i<a.size(); i++)
+        test1+=a[i];
+
+      a.assign(n+1,-2);
+      Scalar test2 = 0;
+      for(unsigned int i=0; i<a.size(); i++)
+        test2+=a[i];
+
+      a.reserve(n+10);
+
+      Scalar test3 = 0;
+      for(unsigned int i=0; i<a.size(); i++)
+        test3+=a[i];
+
+
+      return (test1*test2+test3)*test2+test1*test3;
+    }
+
+
+    test_vector_combinations(unsigned int size)
+    {
+      reference = run_me<std::vector<Scalar> >(size);
+      result = run_me<Kokkos::vector<Scalar,Device> >(size);
+    }
+
+   };
+
+} // namespace Impl
+
+
+
+
+template <typename Scalar, typename Device>
+void test_vector_combinations(unsigned int size)
+{
+  Impl::test_vector_combinations<Scalar,Device> test(size);
+  ASSERT_EQ( test.reference, test.result);
+}
+
+
+} // namespace Test
+
+#endif //KOKKOS_TEST_UNORDERED_MAP_HPP
diff --git a/lib/kokkos/containers/unit_tests/UnitTestMain.cpp b/lib/kokkos/containers/unit_tests/UnitTestMain.cpp
new file mode 100644
index 0000000000..f952ab3db5
--- /dev/null
+++ b/lib/kokkos/containers/unit_tests/UnitTestMain.cpp
@@ -0,0 +1,50 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+int main(int argc, char *argv[]) {
+  ::testing::InitGoogleTest(&argc,argv);
+  return RUN_ALL_TESTS();
+}
+
diff --git a/lib/kokkos/core/CMakeLists.txt b/lib/kokkos/core/CMakeLists.txt
new file mode 100644
index 0000000000..42fce6b2f2
--- /dev/null
+++ b/lib/kokkos/core/CMakeLists.txt
@@ -0,0 +1,11 @@
+
+
+TRIBITS_SUBPACKAGE(Core)
+
+ADD_SUBDIRECTORY(src)
+
+TRIBITS_ADD_TEST_DIRECTORIES(unit_test)
+TRIBITS_ADD_TEST_DIRECTORIES(perf_test)
+
+TRIBITS_SUBPACKAGE_POSTPROCESS()
+
diff --git a/lib/kokkos/core/cmake/Dependencies.cmake b/lib/kokkos/core/cmake/Dependencies.cmake
new file mode 100644
index 0000000000..34ff0be5d3
--- /dev/null
+++ b/lib/kokkos/core/cmake/Dependencies.cmake
@@ -0,0 +1,4 @@
+TRIBITS_PACKAGE_DEFINE_DEPENDENCIES(
+  LIB_OPTIONAL_TPLS Pthread CUDA HWLOC QTHREAD DLlib
+  TEST_OPTIONAL_TPLS CUSPARSE
+  )
diff --git a/lib/kokkos/core/cmake/KokkosCore_config.h.in b/lib/kokkos/core/cmake/KokkosCore_config.h.in
new file mode 100644
index 0000000000..27e3ba1c31
--- /dev/null
+++ b/lib/kokkos/core/cmake/KokkosCore_config.h.in
@@ -0,0 +1,57 @@
+#ifndef KOKKOS_CORE_CONFIG_H
+#define KOKKOS_CORE_CONFIG_H
+
+/* The trivial 'src/build_common.sh' creates a config
+ * that must stay in sync with this file.
+ */
+#cmakedefine KOKKOS_FOR_SIERRA
+
+#if !defined( KOKKOS_FOR_SIERRA )
+
+#cmakedefine KOKKOS_HAVE_MPI
+#cmakedefine KOKKOS_HAVE_CUDA
+
+// mfh 16 Sep 2014: If passed in on the command line, that overrides
+// any value of KOKKOS_USE_CUDA_UVM here.  Doing this should prevent build
+// warnings like this one:
+//
+// packages/kokkos/core/src/KokkosCore_config.h:13:1: warning: "KOKKOS_USE_CUDA_UVM" redefined
+//
+// At some point, we should edit the test-build scripts in
+// Trilinos/cmake/ctest/drivers/perseus/, and take
+// -DKOKKOS_USE_CUDA_UVM from the command-line arguments there.  I
+// hesitate to do that now, because I'm not sure if all the files are
+// including KokkosCore_config.h (or a header file that includes it) like
+// they should.
+
+#if ! defined(KOKKOS_USE_CUDA_UVM)
+#cmakedefine KOKKOS_USE_CUDA_UVM
+#endif // ! defined(KOKKOS_USE_CUDA_UVM)
+
+#cmakedefine KOKKOS_HAVE_PTHREAD
+#cmakedefine KOKKOS_HAVE_SERIAL
+#cmakedefine KOKKOS_HAVE_QTHREAD
+#cmakedefine KOKKOS_HAVE_Winthread
+#cmakedefine KOKKOS_HAVE_OPENMP
+#cmakedefine KOKKOS_HAVE_HWLOC
+#cmakedefine KOKKOS_HAVE_DEBUG
+#cmakedefine KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
+#cmakedefine KOKKOS_HAVE_CXX11
+#cmakedefine KOKKOS_HAVE_CUSPARSE
+#cmakedefine KOKKOS_ENABLE_PROFILING_INTERNAL
+#ifdef KOKKOS_ENABLE_PROFILING_INTERNAL
+#define KOKKOS_ENABLE_PROFILING 1
+#else
+#define KOKKOS_ENABLE_PROFILING 0
+#endif
+
+// Don't forbid users from defining this macro on the command line,
+// but still make sure that CMake logic can control its definition.
+#if ! defined(KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+#cmakedefine KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA 1
+#endif // KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA
+
+#cmakedefine KOKKOS_USING_DEPRECATED_VIEW
+
+#endif // KOKKOS_FOR_SIERRA
+#endif // KOKKOS_CORE_CONFIG_H
diff --git a/lib/kokkos/core/perf_test/CMakeLists.txt b/lib/kokkos/core/perf_test/CMakeLists.txt
new file mode 100644
index 0000000000..d93ca14d96
--- /dev/null
+++ b/lib/kokkos/core/perf_test/CMakeLists.txt
@@ -0,0 +1,29 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINRARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(SOURCES
+  PerfTestMain.cpp
+  PerfTestHost.cpp
+  PerfTestCuda.cpp
+  )
+
+# Per #374, we always want to build this test, but we only want to run
+# it as a PERFORMANCE test.  That's why we separate building the test
+# from running the test.
+
+TRIBITS_ADD_EXECUTABLE(
+  PerfTestExec
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  TESTONLYLIBS kokkos_gtest
+  )
+
+TRIBITS_ADD_EXECUTABLE_AND_TEST(
+  PerfTest
+  NAME PerfTestExec
+  COMM serial mpi
+  NUM_MPI_PROCS 1
+  CATEGORIES PERFORMANCE
+  FAIL_REGULAR_EXPRESSION "  FAILED  "
+  )
diff --git a/lib/kokkos/core/perf_test/Makefile b/lib/kokkos/core/perf_test/Makefile
new file mode 100644
index 0000000000..8fa1fbfc3c
--- /dev/null
+++ b/lib/kokkos/core/perf_test/Makefile
@@ -0,0 +1,66 @@
+KOKKOS_PATH = ../..
+
+GTEST_PATH = ../../tpls/gtest
+
+vpath %.cpp ${KOKKOS_PATH}/core/perf_test
+
+default: build_all
+	echo "End Build"
+
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?=  -lpthread
+endif
+
+KOKKOS_CXXFLAGS += -I$(GTEST_PATH) -I${KOKKOS_PATH}/core/perf_test
+
+TEST_TARGETS = 
+TARGETS = 
+
+OBJ_PERF = PerfTestHost.o PerfTestCuda.o PerfTestMain.o gtest-all.o
+TARGETS += KokkosCore_PerformanceTest
+TEST_TARGETS += test-performance
+
+OBJ_ATOMICS = test_atomic.o 
+TARGETS += KokkosCore_PerformanceTest_Atomics
+TEST_TARGETS += test-atomic
+
+
+KokkosCore_PerformanceTest: $(OBJ_PERF) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_PERF) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_PerformanceTest
+
+KokkosCore_PerformanceTest_Atomics: $(OBJ_ATOMICS) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_ATOMICS) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_PerformanceTest_Atomics
+
+test-performance: KokkosCore_PerformanceTest
+	./KokkosCore_PerformanceTest
+
+test-atomic: KokkosCore_PerformanceTest_Atomics
+	./KokkosCore_PerformanceTest_Atomics
+
+
+build_all: $(TARGETS)
+
+test: $(TEST_TARGETS)
+
+clean: kokkos-clean 
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
+gtest-all.o:$(GTEST_PATH)/gtest/gtest-all.cc 
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $(GTEST_PATH)/gtest/gtest-all.cc
+
diff --git a/lib/kokkos/core/perf_test/PerfTestBlasKernels.hpp b/lib/kokkos/core/perf_test/PerfTestBlasKernels.hpp
new file mode 100644
index 0000000000..aa4046cbf0
--- /dev/null
+++ b/lib/kokkos/core/perf_test/PerfTestBlasKernels.hpp
@@ -0,0 +1,309 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_BLAS_KERNELS_HPP
+#define KOKKOS_BLAS_KERNELS_HPP
+
+namespace Kokkos {
+
+template< class ConstVectorType ,
+          class Device = typename ConstVectorType::execution_space >
+struct Dot ;
+
+template< class ConstVectorType ,
+          class Device = typename ConstVectorType::execution_space >
+struct DotSingle ;
+
+template< class ConstScalarType ,
+          class VectorType ,
+          class Device = typename VectorType::execution_space >
+struct Scale ;
+
+template< class ConstScalarType ,
+          class ConstVectorType ,
+          class VectorType ,
+          class Device = typename VectorType::execution_space >
+struct AXPBY ;
+
+/** \brief  Y = alpha * X + beta * Y */
+template< class ConstScalarType ,
+          class ConstVectorType ,
+          class      VectorType >
+void axpby( const ConstScalarType & alpha ,
+            const ConstVectorType & X ,
+            const ConstScalarType & beta ,
+            const      VectorType & Y )
+{
+  typedef AXPBY< ConstScalarType , ConstVectorType , VectorType > functor ;
+
+  parallel_for( Y.dimension_0() , functor( alpha , X , beta , Y ) );
+}
+
+/** \brief  Y *= alpha */
+template< class ConstScalarType ,
+          class      VectorType >
+void scale( const ConstScalarType & alpha , const VectorType & Y )
+{
+  typedef Scale< ConstScalarType , VectorType > functor ;
+
+  parallel_for( Y.dimension_0() , functor( alpha , Y ) );
+}
+
+template< class ConstVectorType ,
+          class Finalize >
+void dot( const ConstVectorType & X ,
+          const ConstVectorType & Y ,
+          const Finalize & finalize )
+{
+  typedef Dot< ConstVectorType >  functor ;
+
+  parallel_reduce( X.dimension_0() , functor( X , Y ) , finalize );
+}
+
+template< class ConstVectorType ,
+          class Finalize >
+void dot( const ConstVectorType & X ,
+          const Finalize & finalize )
+{
+  typedef DotSingle< ConstVectorType >  functor ;
+
+  parallel_reduce( X.dimension_0() , functor( X ) , finalize );
+}
+
+} /* namespace Kokkos */
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template< class Type , class Device >
+struct Dot
+{
+  typedef typename Device::execution_space execution_space ;
+
+  typedef typename
+    Impl::StaticAssertSame< Impl::unsigned_< 1 > ,
+                            Impl::unsigned_< Type::Rank > >::type ok_rank ;
+
+
+/*  typedef typename
+    Impl::StaticAssertSame< execution_space ,
+                            typename Type::execution_space >::type ok_device ;*/
+
+  typedef double value_type ;
+
+#if 1
+  typename Type::const_type X ;
+  typename Type::const_type Y ;
+#else
+  Type X ;
+  Type Y ;
+#endif
+
+  Dot( const Type & arg_x , const Type & arg_y )
+    : X(arg_x) , Y(arg_y) { }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int i , value_type & update ) const
+    { update += X[i] * Y[i]; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & source )
+    { update += source; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+};
+
+template< class Type , class Device >
+struct DotSingle
+{
+  typedef typename Device::execution_space execution_space ;
+
+  typedef typename
+    Impl::StaticAssertSame< Impl::unsigned_< 1 > ,
+                            Impl::unsigned_< Type::Rank > >::type ok_rank ;
+
+/*  typedef typename
+    Impl::StaticAssertSame< execution_space ,
+                            typename Type::execution_space >::type ok_device ;*/
+
+  typedef double value_type ;
+
+#if 1
+  typename Type::const_type X ;
+#else
+  Type X ;
+#endif
+
+  DotSingle( const Type & arg_x ) : X(arg_x) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int i , value_type & update ) const
+    {
+      const typename Type::value_type & x = X[i]; update += x * x ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & source )
+    { update += source; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+};
+
+
+template< class ScalarType , class VectorType , class Device>
+struct Scale
+{
+  typedef typename Device::execution_space execution_space ;
+
+/*  typedef typename
+    Impl::StaticAssertSame< execution_space ,
+                            typename ScalarType::execution_space >::type
+      ok_scalar_device ;
+
+  typedef typename
+    Impl::StaticAssertSame< execution_space ,
+                            typename VectorType::execution_space >::type
+      ok_vector_device ;*/
+
+  typedef typename
+    Impl::StaticAssertSame< Impl::unsigned_< 0 > ,
+                            Impl::unsigned_< ScalarType::Rank > >::type
+      ok_scalar_rank ;
+
+  typedef typename
+    Impl::StaticAssertSame< Impl::unsigned_< 1 > ,
+                            Impl::unsigned_< VectorType::Rank > >::type
+      ok_vector_rank ;
+
+#if 1
+  typename ScalarType::const_type alpha ;
+#else
+  ScalarType alpha ;
+#endif
+
+  VectorType Y ;
+
+  Scale( const ScalarType & arg_alpha , const VectorType & arg_Y )
+    : alpha( arg_alpha ), Y( arg_Y ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int i ) const
+    {
+      Y[i] *= alpha() ;
+    }
+};
+
+
+template< class ScalarType ,
+          class ConstVectorType ,
+          class VectorType,
+          class Device>
+struct AXPBY
+{
+  typedef typename Device::execution_space execution_space ;
+
+/*  typedef typename
+    Impl::StaticAssertSame< execution_space ,
+                            typename ScalarType::execution_space >::type
+      ok_scalar_device ;
+
+  typedef typename
+    Impl::StaticAssertSame< execution_space ,
+                            typename ConstVectorType::execution_space >::type
+      ok_const_vector_device ;
+
+  typedef typename
+    Impl::StaticAssertSame< execution_space ,
+                            typename VectorType::execution_space >::type
+      ok_vector_device ;*/
+
+  typedef typename
+    Impl::StaticAssertSame< Impl::unsigned_< 0 > ,
+                            Impl::unsigned_< ScalarType::Rank > >::type
+      ok_scalar_rank ;
+
+  typedef typename
+    Impl::StaticAssertSame< Impl::unsigned_< 1 > ,
+                            Impl::unsigned_< ConstVectorType::Rank > >::type
+      ok_const_vector_rank ;
+
+  typedef typename
+    Impl::StaticAssertSame< Impl::unsigned_< 1 > ,
+                            Impl::unsigned_< VectorType::Rank > >::type
+      ok_vector_rank ;
+
+#if 1
+  typename ScalarType::const_type alpha , beta ;
+  typename ConstVectorType::const_type X ;
+#else
+  ScalarType alpha , beta ;
+  ConstVectorType X ;
+#endif
+
+  VectorType Y ;
+
+  AXPBY( const ScalarType      & arg_alpha ,
+         const ConstVectorType & arg_X ,
+         const ScalarType      & arg_beta ,
+         const VectorType      & arg_Y )
+    : alpha( arg_alpha ), beta( arg_beta ), X( arg_X ), Y( arg_Y ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int i ) const
+    {
+      Y[i] = alpha() * X[i] + beta() * Y[i] ;
+    }
+};
+
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_BLAS_KERNELS_HPP */
diff --git a/lib/kokkos/core/perf_test/PerfTestCuda.cpp b/lib/kokkos/core/perf_test/PerfTestCuda.cpp
new file mode 100644
index 0000000000..524beb8b90
--- /dev/null
+++ b/lib/kokkos/core/perf_test/PerfTestCuda.cpp
@@ -0,0 +1,189 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <iostream>
+#include <iomanip>
+#include <algorithm>
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+#include <impl/Kokkos_Timer.hpp>
+
+#include <PerfTestHexGrad.hpp>
+#include <PerfTestBlasKernels.hpp>
+#include <PerfTestGramSchmidt.hpp>
+#include <PerfTestDriver.hpp>
+
+
+namespace Test {
+
+class cuda : public ::testing::Test {
+  protected:
+    static void SetUpTestCase() {
+      Kokkos::HostSpace::execution_space::initialize();
+      Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice(0) );
+    }
+    static void TearDownTestCase() {
+      Kokkos::Cuda::finalize();
+      Kokkos::HostSpace::execution_space::finalize();
+    }
+};
+
+TEST_F( cuda, hexgrad )
+{
+  EXPECT_NO_THROW( run_test_hexgrad< Kokkos::Cuda >( 10 , 20, "Kokkos::Cuda" ) );
+}
+
+TEST_F( cuda, gramschmidt )
+{
+  EXPECT_NO_THROW( run_test_gramschmidt< Kokkos::Cuda >( 10 , 20, "Kokkos::Cuda" ) );
+}
+
+namespace {
+
+template <typename T>
+struct TextureFetch
+{
+  typedef Kokkos::View< T *, Kokkos::CudaSpace> array_type;
+  typedef Kokkos::View< const T *, Kokkos::CudaSpace, Kokkos::MemoryRandomAccess> const_array_type;
+  typedef Kokkos::View< int *, Kokkos::CudaSpace> index_array_type;
+  typedef Kokkos::View< const int *, Kokkos::CudaSpace> const_index_array_type;
+
+  struct FillArray
+  {
+    array_type m_array;
+    FillArray( const array_type & array )
+      : m_array(array)
+    {}
+
+    void apply() const
+    {
+      Kokkos::parallel_for( Kokkos::RangePolicy<Kokkos::Cuda,int>(0,m_array.dimension_0()), *this);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()(int i) const { m_array(i) = i; }
+  };
+
+  struct RandomIndexes
+  {
+    index_array_type m_indexes;
+    typename index_array_type::HostMirror m_host_indexes;
+    RandomIndexes( const index_array_type & indexes)
+      : m_indexes(indexes)
+      , m_host_indexes(Kokkos::create_mirror(m_indexes))
+    {}
+
+    void apply() const
+    {
+      Kokkos::parallel_for( Kokkos::RangePolicy<Kokkos::HostSpace::execution_space,int>(0,m_host_indexes.dimension_0()), *this);
+      //random shuffle
+      Kokkos::HostSpace::execution_space::fence();
+      std::random_shuffle(m_host_indexes.ptr_on_device(), m_host_indexes.ptr_on_device() + m_host_indexes.dimension_0());
+      Kokkos::deep_copy(m_indexes,m_host_indexes);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()(int i) const { m_host_indexes(i) = i; }
+  };
+
+  struct RandomReduce
+  {
+    const_array_type       m_array;
+    const_index_array_type m_indexes;
+    RandomReduce( const const_array_type & array, const const_index_array_type & indexes)
+      : m_array(array)
+      , m_indexes(indexes)
+    {}
+
+    void apply(T & reduce) const
+    {
+      Kokkos::parallel_reduce( Kokkos::RangePolicy<Kokkos::Cuda,int>(0,m_array.dimension_0()), *this, reduce);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()(int i, T & reduce) const
+    { reduce += m_array(m_indexes(i)); }
+  };
+
+  static void run(int size, double & reduce_time, T &reduce)
+  {
+    array_type array("array",size);
+    index_array_type indexes("indexes",size);
+
+    { FillArray f(array); f.apply(); }
+    { RandomIndexes f(indexes); f.apply(); }
+
+    Kokkos::Cuda::fence();
+
+    Kokkos::Timer timer;
+    for (int j=0; j<10; ++j) {
+      RandomReduce f(array,indexes);
+      f.apply(reduce);
+    }
+    Kokkos::Cuda::fence();
+    reduce_time = timer.seconds();
+  }
+};
+
+} // unnamed namespace
+
+TEST_F( cuda, texture_double )
+{
+  printf("Random reduce of double through texture fetch\n");
+  for (int i=1; i<=26; ++i) {
+    int size = 1<<i;
+    double time = 0;
+    double reduce = 0;
+    TextureFetch<double>::run(size,time,reduce);
+    printf("   time = %1.3e   size = 2^%d\n", time, i);
+  }
+}
+
+} // namespace Test
+
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) */
+
diff --git a/lib/kokkos/core/perf_test/PerfTestDriver.hpp b/lib/kokkos/core/perf_test/PerfTestDriver.hpp
new file mode 100644
index 0000000000..e3dd3b4123
--- /dev/null
+++ b/lib/kokkos/core/perf_test/PerfTestDriver.hpp
@@ -0,0 +1,152 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <iostream>
+#include <string>
+
+// mfh 06 Jun 2013: This macro doesn't work like one might thing it
+// should.  It doesn't take the template parameter DeviceType and
+// print its actual type name; it just literally prints out
+// "DeviceType".  I've worked around this below without using the
+// macro, so I'm commenting out the macro to avoid compiler complaints
+// about an unused macro.
+
+// #define KOKKOS_MACRO_IMPL_TO_STRING( X ) #X
+// #define KOKKOS_MACRO_TO_STRING( X )  KOKKOS_MACRO_IMPL_TO_STRING( X )
+
+//------------------------------------------------------------------------
+
+namespace Test {
+
+enum { NUMBER_OF_TRIALS = 5 };
+
+
+
+template< class DeviceType >
+void run_test_hexgrad( int exp_beg , int exp_end, const char deviceTypeName[] )
+{
+  std::string label_hexgrad ;
+  label_hexgrad.append( "\"HexGrad< double , " );
+  // mfh 06 Jun 2013: This only appends "DeviceType" (literally) to
+  // the string, not the actual name of the device type.  Thus, I've
+  // modified the function to take the name of the device type.
+  //
+  //label_hexgrad.append( KOKKOS_MACRO_TO_STRING( DeviceType ) );
+  label_hexgrad.append( deviceTypeName );
+  label_hexgrad.append( " >\"" );
+
+  for (int i = exp_beg ; i < exp_end ; ++i) {
+    double min_seconds = 0.0 ;
+    double max_seconds = 0.0 ;
+    double avg_seconds = 0.0 ;
+
+    const int parallel_work_length = 1<<i;
+
+    for ( int j = 0 ; j < NUMBER_OF_TRIALS ; ++j ) {
+      const double seconds = HexGrad< DeviceType >::test(parallel_work_length) ;
+
+      if ( 0 == j ) {
+        min_seconds = seconds ;
+        max_seconds = seconds ;
+      }
+      else {
+        if ( seconds < min_seconds ) min_seconds = seconds ;
+        if ( seconds > max_seconds ) max_seconds = seconds ;
+      }
+      avg_seconds += seconds ;
+    }
+    avg_seconds /= NUMBER_OF_TRIALS ;
+
+    std::cout << label_hexgrad
+      << " , " << parallel_work_length
+      << " , " << min_seconds
+      << " , " << ( min_seconds / parallel_work_length )
+      << std::endl ;
+  }
+}
+
+template< class DeviceType >
+void run_test_gramschmidt( int exp_beg , int exp_end, const char deviceTypeName[] )
+{
+  std::string label_gramschmidt ;
+  label_gramschmidt.append( "\"GramSchmidt< double , " );
+  // mfh 06 Jun 2013: This only appends "DeviceType" (literally) to
+  // the string, not the actual name of the device type.  Thus, I've
+  // modified the function to take the name of the device type.
+  //
+  //label_gramschmidt.append( KOKKOS_MACRO_TO_STRING( DeviceType ) );
+  label_gramschmidt.append( deviceTypeName );
+  label_gramschmidt.append( " >\"" );
+
+  for (int i = exp_beg ; i < exp_end ; ++i) {
+    double min_seconds = 0.0 ;
+    double max_seconds = 0.0 ;
+    double avg_seconds = 0.0 ;
+
+    const int parallel_work_length = 1<<i;
+
+    for ( int j = 0 ; j < NUMBER_OF_TRIALS ; ++j ) {
+      const double seconds = ModifiedGramSchmidt< double , DeviceType >::test(parallel_work_length, 32 ) ;
+
+      if ( 0 == j ) {
+        min_seconds = seconds ;
+        max_seconds = seconds ;
+      }
+      else {
+        if ( seconds < min_seconds ) min_seconds = seconds ;
+        if ( seconds > max_seconds ) max_seconds = seconds ;
+      }
+      avg_seconds += seconds ;
+    }
+    avg_seconds /= NUMBER_OF_TRIALS ;
+
+    std::cout << label_gramschmidt
+      << " , " << parallel_work_length
+      << " , " << min_seconds
+      << " , " << ( min_seconds / parallel_work_length )
+      << std::endl ;
+  }
+}
+
+}
+
diff --git a/lib/kokkos/core/perf_test/PerfTestGramSchmidt.hpp b/lib/kokkos/core/perf_test/PerfTestGramSchmidt.hpp
new file mode 100644
index 0000000000..516696b141
--- /dev/null
+++ b/lib/kokkos/core/perf_test/PerfTestGramSchmidt.hpp
@@ -0,0 +1,226 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <cmath>
+#include <PerfTestBlasKernels.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Test {
+
+// Reduction   : result = dot( Q(:,j) , Q(:,j) );
+// PostProcess : R(j,j) = result ; inv = 1 / result ;
+template< class VectorView , class ValueView  >
+struct InvNorm2 : public Kokkos::DotSingle< VectorView > {
+
+  typedef typename Kokkos::DotSingle< VectorView >::value_type value_type ;
+
+  ValueView  Rjj ;
+  ValueView  inv ;
+
+  InvNorm2( const VectorView & argX ,
+            const ValueView  & argR ,
+            const ValueView  & argInv )
+    : Kokkos::DotSingle< VectorView >( argX )
+    , Rjj( argR )
+    , inv( argInv )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void final( value_type & result ) const
+  {
+    result = sqrt( result );
+    Rjj() = result ;
+    inv() = ( 0 < result ) ? 1.0 / result : 0 ;
+  }
+};
+
+template< class VectorView , class ValueView >
+inline
+void invnorm2( const VectorView & x ,
+               const ValueView  & r ,
+               const ValueView  & r_inv )
+{
+  Kokkos::parallel_reduce( x.dimension_0() , InvNorm2< VectorView , ValueView >( x , r , r_inv ) );
+}
+
+// PostProcess : tmp = - ( R(j,k) = result );
+template< class VectorView , class ValueView  >
+struct DotM : public Kokkos::Dot< VectorView > {
+
+  typedef typename Kokkos::Dot< VectorView >::value_type value_type ;
+
+  ValueView  Rjk ;
+  ValueView  tmp ;
+
+  DotM( const VectorView & argX ,
+        const VectorView & argY ,
+        const ValueView & argR ,
+        const ValueView & argTmp )
+    : Kokkos::Dot< VectorView >( argX , argY )
+    , Rjk( argR )
+    , tmp( argTmp )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void final( value_type & result ) const
+  {
+     Rjk()  = result ;
+     tmp()  = - result ;
+  }
+};
+
+template< class VectorView , class ValueView >
+inline
+void dot_neg( const VectorView & x ,
+              const VectorView & y ,
+              const ValueView  & r ,
+              const ValueView  & r_neg )
+{
+  Kokkos::parallel_reduce( x.dimension_0() , DotM< VectorView , ValueView >( x , y , r , r_neg ) );
+}
+
+
+template< typename Scalar , class DeviceType >
+struct ModifiedGramSchmidt
+{
+  typedef DeviceType  execution_space ;
+  typedef typename execution_space::size_type  size_type ;
+
+  typedef Kokkos::View< Scalar** ,
+                        Kokkos::LayoutLeft ,
+                        execution_space > multivector_type ;
+
+  typedef Kokkos::View< Scalar* ,
+                        Kokkos::LayoutLeft ,
+                        execution_space > vector_type ;
+
+  typedef Kokkos::View< Scalar ,
+                        Kokkos::LayoutLeft ,
+                        execution_space > value_view ;
+
+
+  multivector_type Q ;
+  multivector_type R ;
+
+  static double factorization( const multivector_type Q_ ,
+                               const multivector_type R_ )
+  {
+    const size_type count  = Q_.dimension_1();
+    value_view tmp("tmp");
+    value_view one("one");
+
+    Kokkos::deep_copy( one , (Scalar) 1 );
+
+    Kokkos::Timer timer ;
+
+    for ( size_type j = 0 ; j < count ; ++j ) {
+      // Reduction   : tmp = dot( Q(:,j) , Q(:,j) );
+      // PostProcess : tmp = sqrt( tmp ); R(j,j) = tmp ; tmp = 1 / tmp ;
+      const vector_type Qj  = Kokkos::subview( Q_ , Kokkos::ALL() , j );
+      const value_view  Rjj = Kokkos::subview( R_ , j , j );
+
+      invnorm2( Qj , Rjj , tmp );
+
+      // Q(:,j) *= ( 1 / R(j,j) ); => Q(:,j) *= tmp ;
+      Kokkos::scale( tmp , Qj );
+
+      for ( size_t k = j + 1 ; k < count ; ++k ) {
+        const vector_type Qk = Kokkos::subview( Q_ , Kokkos::ALL() , k );
+        const value_view  Rjk = Kokkos::subview( R_ , j , k );
+
+        // Reduction   : R(j,k) = dot( Q(:,j) , Q(:,k) );
+        // PostProcess : tmp = - R(j,k);
+        dot_neg( Qj , Qk , Rjk , tmp );
+
+        // Q(:,k) -= R(j,k) * Q(:,j); => Q(:,k) += tmp * Q(:,j)
+        Kokkos::axpby( tmp , Qj , one , Qk );
+      }
+    }
+
+    execution_space::fence();
+
+    return timer.seconds();
+  }
+
+  //--------------------------------------------------------------------------
+
+  static double test( const size_t length ,
+                      const size_t count ,
+                      const size_t iter = 1 )
+  {
+    multivector_type Q_( "Q" , length , count );
+    multivector_type R_( "R" , count , count );
+
+    typename multivector_type::HostMirror A =
+      Kokkos::create_mirror( Q_ );
+
+    // Create and fill A on the host
+
+    for ( size_type j = 0 ; j < count ; ++j ) {
+      for ( size_type i = 0 ; i < length ; ++i ) {
+        A(i,j) = ( i + 1 ) * ( j + 1 );
+      }
+    }
+
+    double dt_min = 0 ;
+
+    for ( size_t i = 0 ; i < iter ; ++i ) {
+
+      Kokkos::deep_copy( Q_ , A );
+
+      // A = Q * R
+
+      const double dt = factorization( Q_ , R_ );
+
+      if ( 0 == i ) dt_min = dt ;
+      else dt_min = dt < dt_min ? dt : dt_min ;
+    }
+
+    return dt_min ;
+  }
+};
+
+}
+
diff --git a/lib/kokkos/core/perf_test/PerfTestHexGrad.hpp b/lib/kokkos/core/perf_test/PerfTestHexGrad.hpp
new file mode 100644
index 0000000000..ed5371f29c
--- /dev/null
+++ b/lib/kokkos/core/perf_test/PerfTestHexGrad.hpp
@@ -0,0 +1,268 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+namespace Test {
+
+template< class DeviceType ,
+          typename CoordScalarType = double ,
+          typename GradScalarType  = float >
+struct HexGrad
+{
+  typedef DeviceType execution_space ;
+  typedef typename execution_space::size_type  size_type ;
+
+  typedef HexGrad<DeviceType,CoordScalarType,GradScalarType> self_type;
+
+  // 3D array : ( ParallelWork , Space , Node )
+
+  enum { NSpace = 3 , NNode = 8 };
+
+  typedef Kokkos::View< CoordScalarType*[NSpace][NNode] , execution_space >
+    elem_coord_type ;
+
+  typedef Kokkos::View< GradScalarType*[NSpace][NNode] , execution_space >
+    elem_grad_type ;
+
+  elem_coord_type  coords ;
+  elem_grad_type   grad_op ;
+
+  enum { FLOPS  = 318 }; // = 3 * ( 18 + 8 * 11 ) };
+  enum { READS  = 18 };
+  enum { WRITES = 18 };
+
+  HexGrad( const elem_coord_type  & arg_coords ,
+           const elem_grad_type   & arg_grad_op )
+    : coords( arg_coords )
+    , grad_op( arg_grad_op )
+    {}
+
+  KOKKOS_INLINE_FUNCTION static
+  void grad( const CoordScalarType x[] ,
+             const CoordScalarType z[] ,
+                   GradScalarType grad_y[] )
+  {
+    const GradScalarType R42=(x[3] - x[1]);
+    const GradScalarType R52=(x[4] - x[1]);
+    const GradScalarType R54=(x[4] - x[3]);
+
+    const GradScalarType R63=(x[5] - x[2]);
+    const GradScalarType R83=(x[7] - x[2]);
+    const GradScalarType R86=(x[7] - x[5]);
+
+    const GradScalarType R31=(x[2] - x[0]);
+    const GradScalarType R61=(x[5] - x[0]);
+    const GradScalarType R74=(x[6] - x[3]);
+
+    const GradScalarType R72=(x[6] - x[1]);
+    const GradScalarType R75=(x[6] - x[4]);
+    const GradScalarType R81=(x[7] - x[0]);
+
+    const GradScalarType t1=(R63 + R54);
+    const GradScalarType t2=(R61 + R74);
+    const GradScalarType t3=(R72 + R81);
+
+    const GradScalarType t4 =(R86 + R42);
+    const GradScalarType t5 =(R83 + R52);
+    const GradScalarType t6 =(R75 + R31);
+
+    //  Calculate Y gradient from X and Z data
+
+    grad_y[0] = (z[1] *  t1) - (z[2] * R42) - (z[3] *  t5)  + (z[4] *  t4) + (z[5] * R52) - (z[7] * R54);
+    grad_y[1] = (z[2] *  t2) + (z[3] * R31) - (z[0] *  t1)  - (z[5] *  t6) + (z[6] * R63) - (z[4] * R61);
+    grad_y[2] = (z[3] *  t3) + (z[0] * R42) - (z[1] *  t2)  - (z[6] *  t4) + (z[7] * R74) - (z[5] * R72);
+    grad_y[3] = (z[0] *  t5) - (z[1] * R31) - (z[2] *  t3)  + (z[7] *  t6) + (z[4] * R81) - (z[6] * R83);
+    grad_y[4] = (z[5] *  t3) + (z[6] * R86) - (z[7] *  t2)  - (z[0] *  t4) - (z[3] * R81) + (z[1] * R61);
+    grad_y[5] = (z[6] *  t5) - (z[4] *  t3)  - (z[7] * R75) + (z[1] *  t6) - (z[0] * R52) + (z[2] * R72);
+    grad_y[6] = (z[7] *  t1) - (z[5] *  t5)  - (z[4] * R86) + (z[2] *  t4) - (z[1] * R63) + (z[3] * R83);
+    grad_y[7] = (z[4] *  t2) - (z[6] *  t1)  + (z[5] * R75) - (z[3] *  t6) - (z[2] * R74) + (z[0] * R54);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type ielem ) const
+  {
+    GradScalarType g[NNode] ;
+
+    const CoordScalarType x[NNode] = {
+      coords(ielem,0,0),
+      coords(ielem,0,1),
+      coords(ielem,0,2),
+      coords(ielem,0,3),
+      coords(ielem,0,4),
+      coords(ielem,0,5),
+      coords(ielem,0,6),
+      coords(ielem,0,7)
+    };
+
+    const CoordScalarType y[NNode] = {
+      coords(ielem,1,0),
+      coords(ielem,1,1),
+      coords(ielem,1,2),
+      coords(ielem,1,3),
+      coords(ielem,1,4),
+      coords(ielem,1,5),
+      coords(ielem,1,6),
+      coords(ielem,1,7)
+    };
+
+    const CoordScalarType z[NNode] = {
+      coords(ielem,2,0),
+      coords(ielem,2,1),
+      coords(ielem,2,2),
+      coords(ielem,2,3),
+      coords(ielem,2,4),
+      coords(ielem,2,5),
+      coords(ielem,2,6),
+      coords(ielem,2,7)
+    };
+
+    grad( z , y , g );
+
+    grad_op(ielem,0,0) = g[0];
+    grad_op(ielem,0,1) = g[1];
+    grad_op(ielem,0,2) = g[2];
+    grad_op(ielem,0,3) = g[3];
+    grad_op(ielem,0,4) = g[4];
+    grad_op(ielem,0,5) = g[5];
+    grad_op(ielem,0,6) = g[6];
+    grad_op(ielem,0,7) = g[7];
+
+    grad( x , z , g );
+
+    grad_op(ielem,1,0) = g[0];
+    grad_op(ielem,1,1) = g[1];
+    grad_op(ielem,1,2) = g[2];
+    grad_op(ielem,1,3) = g[3];
+    grad_op(ielem,1,4) = g[4];
+    grad_op(ielem,1,5) = g[5];
+    grad_op(ielem,1,6) = g[6];
+    grad_op(ielem,1,7) = g[7];
+
+    grad( y , x , g );
+
+    grad_op(ielem,2,0) = g[0];
+    grad_op(ielem,2,1) = g[1];
+    grad_op(ielem,2,2) = g[2];
+    grad_op(ielem,2,3) = g[3];
+    grad_op(ielem,2,4) = g[4];
+    grad_op(ielem,2,5) = g[5];
+    grad_op(ielem,2,6) = g[6];
+    grad_op(ielem,2,7) = g[7];
+  }
+
+  //--------------------------------------------------------------------------
+
+  struct Init {
+    typedef typename self_type::execution_space execution_space ;
+
+    elem_coord_type coords ;
+
+    Init( const elem_coord_type & arg_coords )
+      : coords( arg_coords ) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()( size_type ielem ) const
+    {
+      coords(ielem,0,0) = 0.;
+      coords(ielem,1,0) = 0.;
+      coords(ielem,2,0) = 0.;
+
+      coords(ielem,0,1) = 1.;
+      coords(ielem,1,1) = 0.;
+      coords(ielem,2,1) = 0.;
+
+      coords(ielem,0,2) = 1.;
+      coords(ielem,1,2) = 1.;
+      coords(ielem,2,2) = 0.;
+
+      coords(ielem,0,3) = 0.;
+      coords(ielem,1,3) = 1.;
+      coords(ielem,2,3) = 0.;
+
+
+      coords(ielem,0,4) = 0.;
+      coords(ielem,1,4) = 0.;
+      coords(ielem,2,4) = 1.;
+
+      coords(ielem,0,5) = 1.;
+      coords(ielem,1,5) = 0.;
+      coords(ielem,2,5) = 1.;
+
+      coords(ielem,0,6) = 1.;
+      coords(ielem,1,6) = 1.;
+      coords(ielem,2,6) = 1.;
+
+      coords(ielem,0,7) = 0.;
+      coords(ielem,1,7) = 1.;
+      coords(ielem,2,7) = 1.;
+    }
+  };
+
+  //--------------------------------------------------------------------------
+
+  static double test( const int count , const int iter = 1 )
+  {
+    elem_coord_type coord( "coord" , count );
+    elem_grad_type  grad ( "grad" , count );
+
+    // Execute the parallel kernels on the arrays:
+
+    double dt_min = 0 ;
+
+    Kokkos::parallel_for( count , Init( coord ) );
+    execution_space::fence();
+
+    for ( int i = 0 ; i < iter ; ++i ) {
+      Kokkos::Timer timer ;
+      Kokkos::parallel_for( count , HexGrad<execution_space>( coord , grad ) );
+      execution_space::fence();
+      const double dt = timer.seconds();
+      if ( 0 == i ) dt_min = dt ;
+      else dt_min = dt < dt_min ? dt : dt_min ;
+    }
+
+    return dt_min ;
+  }
+};
+
+}
+
diff --git a/lib/kokkos/core/perf_test/PerfTestHost.cpp b/lib/kokkos/core/perf_test/PerfTestHost.cpp
new file mode 100644
index 0000000000..6a0f2efada
--- /dev/null
+++ b/lib/kokkos/core/perf_test/PerfTestHost.cpp
@@ -0,0 +1,104 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_OPENMP )
+
+typedef Kokkos::OpenMP TestHostDevice ;
+const char TestHostDeviceName[] = "Kokkos::OpenMP" ;
+
+#elif defined( KOKKOS_HAVE_PTHREAD )
+
+typedef Kokkos::Threads TestHostDevice ;
+const char TestHostDeviceName[] = "Kokkos::Threads" ;
+
+#elif defined( KOKKOS_HAVE_SERIAL )
+
+typedef Kokkos::Serial TestHostDevice ;
+const char TestHostDeviceName[] = "Kokkos::Serial" ;
+
+#else
+#  error "You must enable at least one of the following execution spaces in order to build this test: Kokkos::Threads, Kokkos::OpenMP, or Kokkos::Serial."
+#endif
+
+#include <impl/Kokkos_Timer.hpp>
+
+#include <PerfTestHexGrad.hpp>
+#include <PerfTestBlasKernels.hpp>
+#include <PerfTestGramSchmidt.hpp>
+#include <PerfTestDriver.hpp>
+
+//------------------------------------------------------------------------
+
+namespace Test {
+
+class host : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    const unsigned team_count = Kokkos::hwloc::get_available_numa_count();
+    const unsigned threads_per_team = 4 ;
+
+    TestHostDevice::initialize( team_count * threads_per_team );
+  }
+
+  static void TearDownTestCase()
+  {
+    TestHostDevice::finalize();
+  }
+};
+
+TEST_F( host, hexgrad ) {
+  EXPECT_NO_THROW(run_test_hexgrad< TestHostDevice>( 10, 20, TestHostDeviceName ));
+}
+
+TEST_F( host, gramschmidt ) {
+  EXPECT_NO_THROW(run_test_gramschmidt< TestHostDevice>( 10, 20, TestHostDeviceName ));
+}
+
+} // namespace Test
+
+
diff --git a/lib/kokkos/core/perf_test/PerfTestMain.cpp b/lib/kokkos/core/perf_test/PerfTestMain.cpp
new file mode 100644
index 0000000000..ac91630829
--- /dev/null
+++ b/lib/kokkos/core/perf_test/PerfTestMain.cpp
@@ -0,0 +1,49 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+int main(int argc, char *argv[]) {
+  ::testing::InitGoogleTest(&argc,argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/lib/kokkos/core/perf_test/test_atomic.cpp b/lib/kokkos/core/perf_test/test_atomic.cpp
new file mode 100644
index 0000000000..ab73f2505e
--- /dev/null
+++ b/lib/kokkos/core/perf_test/test_atomic.cpp
@@ -0,0 +1,507 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Timer.hpp>
+
+typedef Kokkos::DefaultExecutionSpace exec_space;
+
+#define RESET		0
+#define BRIGHT 		1
+#define DIM		2
+#define UNDERLINE 	3
+#define BLINK		4
+#define REVERSE		7
+#define HIDDEN		8
+
+#define BLACK 		0
+#define RED		1
+#define GREEN		2
+#define YELLOW		3
+#define BLUE		4
+#define MAGENTA		5
+#define CYAN		6
+#define GREY		7
+#define	WHITE		8
+
+void textcolor(int attr, int fg, int bg)
+{	char command[13];
+
+	/* Command is the control command to the terminal */
+	sprintf(command, "%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40);
+	printf("%s", command);
+}
+void textcolor_standard() {textcolor(RESET, BLACK, WHITE);}
+
+
+template<class T,class DEVICE_TYPE>
+struct ZeroFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef typename Kokkos::View<T,execution_space> type;
+  typedef typename Kokkos::View<T,execution_space>::HostMirror h_type;
+  type data;
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+    data() = 0;
+  }
+};
+
+//---------------------------------------------------
+//--------------atomic_fetch_add---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct AddFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+    Kokkos::atomic_fetch_add(&data(),(T)1);
+  }
+};
+
+template<class T>
+T AddLoop(int loop) {
+  struct ZeroFunctor<T,exec_space> f_zero;
+  typename ZeroFunctor<T,exec_space>::type data("Data");
+  typename ZeroFunctor<T,exec_space>::h_type h_data("HData");
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  exec_space::fence();
+
+  struct AddFunctor<T,exec_space> f_add;
+  f_add.data = data;
+  Kokkos::parallel_for(loop,f_add);
+  exec_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T,class DEVICE_TYPE>
+struct AddNonAtomicFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+    data()+=(T)1;
+  }
+};
+
+template<class T>
+T AddLoopNonAtomic(int loop) {
+  struct ZeroFunctor<T,exec_space> f_zero;
+  typename ZeroFunctor<T,exec_space>::type data("Data");
+  typename ZeroFunctor<T,exec_space>::h_type h_data("HData");
+
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  exec_space::fence();
+
+  struct AddNonAtomicFunctor<T,exec_space> f_add;
+  f_add.data = data;
+  Kokkos::parallel_for(loop,f_add);
+  exec_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+
+  return val;
+}
+
+template<class T>
+T AddLoopSerial(int loop) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  for(int i=0;i<loop;i++)
+  *data+=(T)1;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DEVICE_TYPE>
+struct CASFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+	  T old = data();
+	  T newval, assumed;
+	  do {
+	    assumed = old;
+	    newval = assumed + (T)1;
+	    old = Kokkos::atomic_compare_exchange(&data(), assumed, newval);
+	  }
+	  while( old != assumed );
+  }
+};
+
+template<class T>
+T CASLoop(int loop) {
+  struct ZeroFunctor<T,exec_space> f_zero;
+  typename ZeroFunctor<T,exec_space>::type data("Data");
+  typename ZeroFunctor<T,exec_space>::h_type h_data("HData");
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  exec_space::fence();
+
+  struct CASFunctor<T,exec_space> f_cas;
+  f_cas.data = data;
+  Kokkos::parallel_for(loop,f_cas);
+  exec_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+
+  return val;
+}
+
+template<class T,class DEVICE_TYPE>
+struct CASNonAtomicFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+	  volatile T assumed;
+	  volatile T newval;
+	  bool fail=1;
+	  do {
+	    assumed = data();
+	    newval = assumed + (T)1;
+	    if(data()==assumed) {
+	    	data() = newval;
+	    	fail = 0;
+	    }
+	  }
+	  while(fail);
+  }
+};
+
+template<class T>
+T CASLoopNonAtomic(int loop) {
+  struct ZeroFunctor<T,exec_space> f_zero;
+  typename ZeroFunctor<T,exec_space>::type data("Data");
+  typename ZeroFunctor<T,exec_space>::h_type h_data("HData");
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  exec_space::fence();
+
+  struct CASNonAtomicFunctor<T,exec_space> f_cas;
+  f_cas.data = data;
+  Kokkos::parallel_for(loop,f_cas);
+  exec_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+
+  return val;
+}
+
+template<class T>
+T CASLoopSerial(int loop) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  for(int i=0;i<loop;i++) {
+	  T assumed;
+	  T newval;
+	  T old;
+	  do {
+	    assumed = *data;
+	    newval = assumed + (T)1;
+	    old = *data;
+	    *data = newval;
+	  }
+	  while(!(assumed==old));
+  }
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DEVICE_TYPE>
+struct ExchFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data, data2;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+	T old = Kokkos::atomic_exchange(&data(),(T)i);
+    Kokkos::atomic_fetch_add(&data2(),old);
+  }
+};
+
+template<class T>
+T ExchLoop(int loop) {
+  struct ZeroFunctor<T,exec_space> f_zero;
+  typename ZeroFunctor<T,exec_space>::type data("Data");
+  typename ZeroFunctor<T,exec_space>::h_type h_data("HData");
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  exec_space::fence();
+
+  typename ZeroFunctor<T,exec_space>::type data2("Data");
+  typename ZeroFunctor<T,exec_space>::h_type h_data2("HData");
+  f_zero.data = data2;
+  Kokkos::parallel_for(1,f_zero);
+  exec_space::fence();
+
+  struct ExchFunctor<T,exec_space> f_exch;
+  f_exch.data = data;
+  f_exch.data2 = data2;
+  Kokkos::parallel_for(loop,f_exch);
+  exec_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  Kokkos::deep_copy(h_data2,data2);
+  T val = h_data() + h_data2();
+
+  return val;
+}
+
+template<class T,class DEVICE_TYPE>
+struct ExchNonAtomicFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data, data2;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+		T old = data();
+		data()=(T) i;
+		data2()+=old;
+  }
+};
+
+
+template<class T>
+T ExchLoopNonAtomic(int loop) {
+  struct ZeroFunctor<T,exec_space> f_zero;
+  typename ZeroFunctor<T,exec_space>::type data("Data");
+  typename ZeroFunctor<T,exec_space>::h_type h_data("HData");
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  exec_space::fence();
+
+  typename ZeroFunctor<T,exec_space>::type data2("Data");
+  typename ZeroFunctor<T,exec_space>::h_type h_data2("HData");
+  f_zero.data = data2;
+  Kokkos::parallel_for(1,f_zero);
+  exec_space::fence();
+
+  struct ExchNonAtomicFunctor<T,exec_space> f_exch;
+  f_exch.data = data;
+  f_exch.data2 = data2;
+  Kokkos::parallel_for(loop,f_exch);
+  exec_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  Kokkos::deep_copy(h_data2,data2);
+  T val = h_data() + h_data2();
+
+  return val;
+}
+
+template<class T>
+T ExchLoopSerial(int loop) {
+  T* data = new T[1];
+  T* data2 = new T[1];
+  data[0] = 0;
+  data2[0] = 0;
+  for(int i=0;i<loop;i++) {
+	T old = *data;
+	*data=(T) i;
+	*data2+=old;
+  }
+
+  T val = *data2 + *data;
+  delete [] data;
+  delete [] data2;
+  return val;
+}
+
+template<class T>
+T LoopVariant(int loop, int test) {
+  switch (test) {
+    case 1: return AddLoop<T>(loop);
+    case 2: return CASLoop<T>(loop);
+    case 3: return ExchLoop<T>(loop);
+  }
+  return 0;
+}
+
+template<class T>
+T LoopVariantSerial(int loop, int test) {
+  switch (test) {
+    case 1: return AddLoopSerial<T>(loop);
+    case 2: return CASLoopSerial<T>(loop);
+    case 3: return ExchLoopSerial<T>(loop);
+  }
+  return 0;
+}
+
+template<class T>
+T LoopVariantNonAtomic(int loop, int test) {
+  switch (test) {
+    case 1: return AddLoopNonAtomic<T>(loop);
+    case 2: return CASLoopNonAtomic<T>(loop);
+    case 3: return ExchLoopNonAtomic<T>(loop);
+  }
+  return 0;
+}
+
+template<class T>
+void Loop(int loop, int test, const char* type_name) {
+  LoopVariant<T>(loop,test);
+
+  Kokkos::Impl::Timer timer;
+  T res = LoopVariant<T>(loop,test);
+  double time = timer.seconds();
+
+  timer.reset();
+  T resNonAtomic = LoopVariantNonAtomic<T>(loop,test);
+  double timeNonAtomic = timer.seconds();
+
+  timer.reset();
+  T resSerial = LoopVariantSerial<T>(loop,test);
+  double timeSerial = timer.seconds();
+
+  time         *=1e6/loop;
+  timeNonAtomic*=1e6/loop;
+  timeSerial   *=1e6/loop;
+  //textcolor_standard();
+  bool passed = true;
+  if(resSerial!=res) passed = false;
+  //if(!passed) textcolor(RESET,BLACK,YELLOW);
+  printf("%s Test %i %s  --- Loop: %i Value (S,A,NA): %e %e %e Time: %7.4e %7.4e %7.4e Size of Type %i)",
+         type_name,test,passed?"PASSED":"FAILED",loop,
+         1.0*resSerial,1.0*res,1.0*resNonAtomic,
+         timeSerial,time,timeNonAtomic,(int)sizeof(T));
+  //if(!passed) textcolor_standard();
+  printf("\n");
+}
+
+
+template<class T>
+void Test(int loop, int test, const char* type_name) {
+  if(test==-1) {
+    Loop<T>(loop,1,type_name);
+    Loop<T>(loop,2,type_name);
+    Loop<T>(loop,3,type_name);
+
+  }
+  else
+    Loop<T>(loop,test,type_name);
+}
+
+int main(int argc, char* argv[])
+{
+  int type = -1;
+  int loop = 100000;
+  int test = -1;
+
+  for(int i=0;i<argc;i++)
+  {
+     if((strcmp(argv[i],"--test")==0)) {test=atoi(argv[++i]); continue;}
+     if((strcmp(argv[i],"--type")==0)) {type=atoi(argv[++i]); continue;}
+     if((strcmp(argv[i],"-l")==0)||(strcmp(argv[i],"--loop")==0)) {loop=atoi(argv[++i]); continue;}
+  }
+
+
+  Kokkos::initialize(argc,argv);
+
+
+  printf("Using %s\n",Kokkos::atomic_query_version());
+  bool all_tests = false;
+  if(type==-1) all_tests = true;
+  while(type<100) {
+    if(type==1) {
+     Test<int>(loop,test,"int                    ");
+    }
+    if(type==2) {
+     Test<long int>(loop,test,"long int               ");
+    }
+    if(type==3) {
+     Test<long long int>(loop,test,"long long int          ");
+    }
+    if(type==4) {
+     Test<unsigned int>(loop,test,"unsigned int           ");
+    }
+    if(type==5) {
+     Test<unsigned long int>(loop,test,"unsigned long int      ");
+    }
+    if(type==6) {
+     Test<unsigned long long int>(loop,test,"unsigned long long int ");
+    }
+    if(type==10) {
+     //Test<float>(loop,test,"float                  ");
+    }
+    if(type==11) {
+     Test<double>(loop,test,"double                 ");
+    }
+    if(!all_tests) type=100;
+    else type++;
+  }
+
+  Kokkos::finalize();
+
+}
+
diff --git a/lib/kokkos/core/src/CMakeLists.txt b/lib/kokkos/core/src/CMakeLists.txt
new file mode 100644
index 0000000000..807a01ed01
--- /dev/null
+++ b/lib/kokkos/core/src/CMakeLists.txt
@@ -0,0 +1,113 @@
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_Serial
+  KOKKOS_HAVE_SERIAL
+  "Whether to enable the Kokkos::Serial device.  This device executes \"parallel\" kernels sequentially on a single CPU thread.  It is enabled by default.  If you disable this device, please enable at least one other CPU device, such as Kokkos::OpenMP or Kokkos::Threads."
+  ON
+  )
+
+ASSERT_DEFINED(${PROJECT_NAME}_ENABLE_CXX11)
+ASSERT_DEFINED(${PACKAGE_NAME}_ENABLE_CUDA)
+
+# Kokkos_ENABLE_CXX11_DISPATCH_LAMBDA governs whether Kokkos allows
+# use of lambdas at the outer level of parallel dispatch (that is, as
+# the argument to an outer parallel_for, parallel_reduce, or
+# parallel_scan).  This works with non-CUDA execution spaces if C++11
+# is enabled.  It does not currently work with public releases of
+# CUDA.  If that changes, please change the default here to ON if CUDA
+# and C++11 are ON.
+IF (${PROJECT_NAME}_ENABLE_CXX11)
+  IF (${PACKAGE_NAME}_ENABLE_CUDA)
+    SET(Kokkos_ENABLE_CXX11_DISPATCH_LAMBDA_DEFAULT OFF)
+  ELSE ()
+    SET(Kokkos_ENABLE_CXX11_DISPATCH_LAMBDA_DEFAULT ON)
+  ENDIF ()
+ELSE ()
+  SET(Kokkos_ENABLE_CXX11_DISPATCH_LAMBDA_DEFAULT OFF)
+ENDIF ()
+
+TRIBITS_ADD_OPTION_AND_DEFINE(
+  Kokkos_ENABLE_CXX11_DISPATCH_LAMBDA
+  KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA
+  "Whether Kokkos allows use of lambdas at the outer level of parallel dispatch (that is, as the argument to an outer parallel_for, parallel_reduce, or parallel_scan).  This requires C++11.  It also does not currently work with public releases of CUDA.  As a result, even if C++11 is enabled, this will be OFF by default if CUDA is enabled.  If this option is ON, the macro KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA will be defined.  For compatibility with Kokkos' Makefile build system, it is also possible to define that macro on the command line."
+  ${Kokkos_ENABLE_CXX11_DISPATCH_LAMBDA_DEFAULT}
+  )
+
+TRIBITS_CONFIGURE_FILE(${PACKAGE_NAME}_config.h)
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+#-----------------------------------------------------------------------------
+
+SET(TRILINOS_INCDIR ${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR})
+
+#-----------------------------------------------------------------------------
+
+SET(HEADERS_PUBLIC "")
+SET(HEADERS_PRIVATE "")
+SET(SOURCES "")
+
+FILE(GLOB HEADERS_PUBLIC Kokkos*.hpp)
+LIST( APPEND HEADERS_PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/${PACKAGE_NAME}_config.h )
+
+#-----------------------------------------------------------------------------
+
+FILE(GLOB HEADERS_IMPL impl/*.hpp)
+FILE(GLOB SOURCES_IMPL impl/*.cpp)
+
+LIST(APPEND HEADERS_PRIVATE ${HEADERS_IMPL} )
+LIST(APPEND SOURCES         ${SOURCES_IMPL} )
+
+INSTALL(FILES ${HEADERS_IMPL} DESTINATION ${TRILINOS_INCDIR}/impl/)
+
+#-----------------------------------------------------------------------------
+
+FILE(GLOB HEADERS_THREADS Threads/*.hpp)
+FILE(GLOB SOURCES_THREADS Threads/*.cpp)
+
+LIST(APPEND HEADERS_PRIVATE ${HEADERS_THREADS} )
+LIST(APPEND SOURCES         ${SOURCES_THREADS} )
+
+INSTALL(FILES ${HEADERS_THREADS} DESTINATION ${TRILINOS_INCDIR}/Threads/)
+
+#-----------------------------------------------------------------------------
+
+FILE(GLOB HEADERS_OPENMP OpenMP/*.hpp)
+FILE(GLOB SOURCES_OPENMP OpenMP/*.cpp)
+
+LIST(APPEND HEADERS_PRIVATE ${HEADERS_OPENMP} )
+LIST(APPEND SOURCES         ${SOURCES_OPENMP} )
+
+INSTALL(FILES ${HEADERS_OPENMP} DESTINATION ${TRILINOS_INCDIR}/OpenMP/)
+
+#-----------------------------------------------------------------------------
+
+FILE(GLOB HEADERS_CUDA Cuda/*.hpp)
+FILE(GLOB SOURCES_CUDA Cuda/*.cpp)
+
+LIST(APPEND HEADERS_PRIVATE ${HEADERS_CUDA} )
+LIST(APPEND SOURCES         ${SOURCES_CUDA} )
+
+INSTALL(FILES ${HEADERS_CUDA} DESTINATION ${TRILINOS_INCDIR}/Cuda/)
+
+#-----------------------------------------------------------------------------
+FILE(GLOB HEADERS_QTHREAD Qthread/*.hpp)
+FILE(GLOB SOURCES_QTHREAD Qthread/*.cpp)
+
+LIST(APPEND HEADERS_PRIVATE ${HEADERS_QTHREAD} )
+LIST(APPEND SOURCES         ${SOURCES_QTHREAD} )
+
+INSTALL(FILES ${HEADERS_QTHREAD} DESTINATION ${TRILINOS_INCDIR}/Qthread/)
+
+#-----------------------------------------------------------------------------
+
+TRIBITS_ADD_LIBRARY(
+    kokkoscore
+    HEADERS ${HEADERS_PUBLIC}
+    NOINSTALLHEADERS ${HEADERS_PRIVATE}
+    SOURCES ${SOURCES}
+    DEPLIBS
+    )
+
+
diff --git a/lib/kokkos/core/src/Cuda/KokkosExp_Cuda_View.hpp b/lib/kokkos/core/src/Cuda/KokkosExp_Cuda_View.hpp
new file mode 100644
index 0000000000..4ed7d8e2a8
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/KokkosExp_Cuda_View.hpp
@@ -0,0 +1,334 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXPERIMENTAL_CUDA_VIEW_HPP
+#define KOKKOS_EXPERIMENTAL_CUDA_VIEW_HPP
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#if defined( KOKKOS_HAVE_CUDA )
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template<>
+struct ViewOperatorBoundsErrorAbort< Kokkos::CudaSpace > {
+  KOKKOS_INLINE_FUNCTION
+  static void apply( const size_t rank
+                   , const size_t n0 , const size_t n1
+                   , const size_t n2 , const size_t n3
+                   , const size_t n4 , const size_t n5
+                   , const size_t n6 , const size_t n7
+                   , const size_t i0 , const size_t i1
+                   , const size_t i2 , const size_t i3
+                   , const size_t i4 , const size_t i5
+                   , const size_t i6 , const size_t i7 )
+    {
+      const int r =
+        ( n0 <= i0 ? 0 :
+        ( n1 <= i1 ? 1 :
+        ( n2 <= i2 ? 2 :
+        ( n3 <= i3 ? 3 :
+        ( n4 <= i4 ? 4 :
+        ( n5 <= i5 ? 5 :
+        ( n6 <= i6 ? 6 : 7 )))))));
+      const size_t n =
+        ( n0 <= i0 ? n0 :
+        ( n1 <= i1 ? n1 :
+        ( n2 <= i2 ? n2 :
+        ( n3 <= i3 ? n3 :
+        ( n4 <= i4 ? n4 :
+        ( n5 <= i5 ? n5 :
+        ( n6 <= i6 ? n6 : n7 )))))));
+      const size_t i =
+        ( n0 <= i0 ? i0 :
+        ( n1 <= i1 ? i1 :
+        ( n2 <= i2 ? i2 :
+        ( n3 <= i3 ? i3 :
+        ( n4 <= i4 ? i4 :
+        ( n5 <= i5 ? i5 :
+        ( n6 <= i6 ? i6 : i7 )))))));
+      printf("Cuda view array bounds error index %d : FAILED %lu < %lu\n" , r , i , n );
+      Kokkos::Impl::cuda_abort("Cuda view array bounds error");
+    }
+};
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+// Cuda Texture fetches can be performed for 4, 8 and 16 byte objects (int,int2,int4)
+// Via reinterpret_case this can be used to support all scalar types of those sizes.
+// Any other scalar type falls back to either normal reads out of global memory,
+// or using the __ldg intrinsic on Kepler GPUs or newer (Compute Capability >= 3.0)
+
+template< typename ValueType , typename AliasType >
+struct CudaTextureFetch {
+
+  ::cudaTextureObject_t   m_obj ;
+  const ValueType       * m_ptr ;
+  int                     m_offset ;
+
+  // Deference operator pulls through texture object and returns by value
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  ValueType operator[]( const iType & i ) const
+    {
+#if defined( __CUDA_ARCH__ ) && ( 300 <= __CUDA_ARCH__ )
+      AliasType v = tex1Dfetch<AliasType>( m_obj , i + m_offset );
+      return  *(reinterpret_cast<ValueType*> (&v));
+#else
+      return m_ptr[ i ];
+#endif
+    }
+
+  // Pointer to referenced memory
+  KOKKOS_INLINE_FUNCTION
+  operator const ValueType * () const { return m_ptr ; }
+
+
+  KOKKOS_INLINE_FUNCTION
+  CudaTextureFetch() : m_obj() , m_ptr() , m_offset() {}
+
+  KOKKOS_INLINE_FUNCTION
+  ~CudaTextureFetch() {}
+
+  KOKKOS_INLINE_FUNCTION
+  CudaTextureFetch( const CudaTextureFetch & rhs )
+    : m_obj(     rhs.m_obj )
+    , m_ptr(     rhs.m_ptr )
+    , m_offset(  rhs.m_offset )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  CudaTextureFetch( CudaTextureFetch && rhs )
+    : m_obj(     rhs.m_obj )
+    , m_ptr(     rhs.m_ptr )
+    , m_offset(  rhs.m_offset )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  CudaTextureFetch & operator = ( const CudaTextureFetch & rhs )
+    {
+      m_obj     = rhs.m_obj ;
+      m_ptr     = rhs.m_ptr ;
+      m_offset  = rhs.m_offset ;
+      return *this ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  CudaTextureFetch & operator = ( CudaTextureFetch && rhs )
+    {
+      m_obj     = rhs.m_obj ;
+      m_ptr     = rhs.m_ptr ;
+      m_offset  = rhs.m_offset ;
+      return *this ;
+    }
+
+  // Texture object spans the entire allocation.
+  // This handle may view a subset of the allocation, so an offset is required.
+  template< class CudaMemorySpace >
+  inline explicit
+  CudaTextureFetch( const ValueType * const arg_ptr
+                  , Kokkos::Experimental::Impl::SharedAllocationRecord< CudaMemorySpace , void > & record
+                  )
+    : m_obj( record.template attach_texture_object< AliasType >() )
+    , m_ptr( arg_ptr )
+    , m_offset( record.attach_texture_object_offset( reinterpret_cast<const AliasType*>( arg_ptr ) ) )
+    {}
+};
+
+#if defined( KOKKOS_CUDA_USE_LDG_INTRINSIC )
+
+template< typename ValueType , typename AliasType >
+struct CudaLDGFetch {
+
+  const ValueType * m_ptr ;
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  ValueType operator[]( const iType & i ) const
+    {
+      AliasType v = __ldg(reinterpret_cast<AliasType*>(&m_ptr[i]));
+      return  *(reinterpret_cast<ValueType*> (&v));
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  operator const ValueType * () const { return m_ptr ; }
+
+  KOKKOS_INLINE_FUNCTION
+  CudaLDGFetch() : m_ptr() {}
+
+  KOKKOS_INLINE_FUNCTION
+  ~CudaLDGFetch() {}
+
+  KOKKOS_INLINE_FUNCTION
+  CudaLDGFetch( const CudaLDGFetch & rhs )
+    : m_ptr( rhs.m_ptr )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  CudaLDGFetch( CudaLDGFetch && rhs )
+    : m_ptr( rhs.m_ptr )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  CudaLDGFetch & operator = ( const CudaLDGFetch & rhs )
+    {
+      m_ptr = rhs.m_ptr ;
+      return *this ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  CudaLDGFetch & operator = ( CudaLDGFetch && rhs )
+    {
+      m_ptr = rhs.m_ptr ;
+      return *this ;
+    }
+
+  template< class CudaMemorySpace >
+  inline explicit
+  CudaTextureFetch( const ValueType * const arg_ptr
+                  , Kokkos::Experimental::Impl::SharedAllocationRecord< CudaMemorySpace , void > const &
+                  )
+    : m_ptr( arg_data_ptr )
+    {}
+};
+
+#endif
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+/** \brief  Replace Default ViewDataHandle with Cuda texture fetch specialization
+ *          if 'const' value type, CudaSpace and random access.
+ */
+template< class Traits >
+class ViewDataHandle< Traits ,
+  typename std::enable_if<(
+    // Is Cuda memory space
+    ( std::is_same< typename Traits::memory_space,Kokkos::CudaSpace>::value ||
+      std::is_same< typename Traits::memory_space,Kokkos::CudaUVMSpace>::value )
+    &&
+    // Is a trivial const value of 4, 8, or 16 bytes
+    std::is_trivial<typename Traits::const_value_type>::value
+    &&
+    std::is_same<typename Traits::const_value_type,typename Traits::value_type>::value
+    &&
+    ( sizeof(typename Traits::const_value_type) ==  4 ||
+      sizeof(typename Traits::const_value_type) ==  8 ||
+      sizeof(typename Traits::const_value_type) == 16 )
+    &&
+    // Random access trait
+    ( Traits::memory_traits::RandomAccess != 0 )
+  )>::type >
+{
+public:
+
+  using track_type  = Kokkos::Experimental::Impl::SharedAllocationTracker ;
+
+  using value_type  = typename Traits::const_value_type ;
+  using return_type = typename Traits::const_value_type ; // NOT a reference
+
+  using alias_type = typename std::conditional< ( sizeof(value_type) ==  4 ) , int ,
+                     typename std::conditional< ( sizeof(value_type) ==  8 ) , ::int2 ,
+                     typename std::conditional< ( sizeof(value_type) == 16 ) , ::int4 , void
+                     >::type
+                     >::type
+                     >::type ;
+
+#if defined( KOKKOS_CUDA_USE_LDG_INTRINSIC )
+  using handle_type = Kokkos::Experimental::Impl::CudaLDGFetch< value_type , alias_type > ;
+#else
+  using handle_type = Kokkos::Experimental::Impl::CudaTextureFetch< value_type , alias_type > ;
+#endif
+
+  KOKKOS_INLINE_FUNCTION
+  static handle_type const & assign( handle_type const & arg_handle , track_type const & /* arg_tracker */ )
+    {
+      return arg_handle ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  static handle_type assign( value_type * arg_data_ptr, track_type const & arg_tracker )
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      // Assignment of texture = non-texture requires creation of a texture object
+      // which can only occur on the host.  In addition, 'get_record' is only valid
+      // if called in a host execution space
+      return handle_type( arg_data_ptr , arg_tracker.template get_record< typename Traits::memory_space >() );
+#else
+      Kokkos::Impl::cuda_abort("Cannot create Cuda texture object from within a Cuda kernel");
+      return handle_type();
+#endif
+    }
+};
+
+}
+}
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) */
+#endif /* #ifndef KOKKOS_CUDA_VIEW_HPP */
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_CudaExec.hpp b/lib/kokkos/core/src/Cuda/Kokkos_CudaExec.hpp
new file mode 100644
index 0000000000..d1a560ee04
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_CudaExec.hpp
@@ -0,0 +1,318 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDAEXEC_HPP
+#define KOKKOS_CUDAEXEC_HPP
+
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#ifdef KOKKOS_HAVE_CUDA
+
+#include <string>
+#include <Kokkos_Parallel.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <Cuda/Kokkos_Cuda_abort.hpp>
+#include <Cuda/Kokkos_Cuda_Error.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+struct CudaTraits {
+  enum { WarpSize       = 32      /* 0x0020 */ };
+  enum { WarpIndexMask  = 0x001f  /* Mask for warpindex */ };
+  enum { WarpIndexShift = 5       /* WarpSize == 1 << WarpShift */ };
+
+  enum { SharedMemoryBanks    = 32      /* Compute device 2.0 */ };
+  enum { SharedMemoryCapacity = 0x0C000 /* 48k shared / 16k L1 Cache */ };
+  enum { SharedMemoryUsage    = 0x04000 /* 16k shared / 48k L1 Cache */ };
+
+  enum { UpperBoundGridCount    = 65535 /* Hard upper bound */ };
+  enum { ConstantMemoryCapacity = 0x010000 /* 64k bytes */ };
+  enum { ConstantMemoryUsage    = 0x008000 /* 32k bytes */ };
+  enum { ConstantMemoryCache    = 0x002000 /*  8k bytes */ };
+
+  typedef unsigned long
+    ConstantGlobalBufferType[ ConstantMemoryUsage / sizeof(unsigned long) ];
+
+  enum { ConstantMemoryUseThreshold = 0x000200 /* 512 bytes */ };
+
+  KOKKOS_INLINE_FUNCTION static
+  CudaSpace::size_type warp_count( CudaSpace::size_type i )
+    { return ( i + WarpIndexMask ) >> WarpIndexShift ; }
+
+  KOKKOS_INLINE_FUNCTION static
+  CudaSpace::size_type warp_align( CudaSpace::size_type i )
+    {
+      enum { Mask = ~CudaSpace::size_type( WarpIndexMask ) };
+      return ( i + WarpIndexMask ) & Mask ;
+    }
+};
+
+//----------------------------------------------------------------------------
+
+CudaSpace::size_type cuda_internal_multiprocessor_count();
+CudaSpace::size_type cuda_internal_maximum_warp_count();
+CudaSpace::size_type cuda_internal_maximum_grid_count();
+CudaSpace::size_type cuda_internal_maximum_shared_words();
+
+CudaSpace::size_type * cuda_internal_scratch_flags( const CudaSpace::size_type size );
+CudaSpace::size_type * cuda_internal_scratch_space( const CudaSpace::size_type size );
+CudaSpace::size_type * cuda_internal_scratch_unified( const CudaSpace::size_type size );
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if defined( __CUDACC__ )
+
+/** \brief  Access to constant memory on the device */
+#ifdef KOKKOS_CUDA_USE_RELOCATABLE_DEVICE_CODE
+
+__device__ __constant__
+extern unsigned long kokkos_impl_cuda_constant_memory_buffer[] ;
+
+#else
+
+__device__ __constant__
+unsigned long kokkos_impl_cuda_constant_memory_buffer[ Kokkos::Impl::CudaTraits::ConstantMemoryUsage / sizeof(unsigned long) ] ;
+
+#endif
+
+
+namespace Kokkos {
+namespace Impl {
+  struct CudaLockArraysStruct {
+    int* atomic;
+    int* scratch;
+    int* threadid;
+  };
+}
+}
+__device__ __constant__
+#ifdef KOKKOS_CUDA_USE_RELOCATABLE_DEVICE_CODE
+extern
+#endif
+Kokkos::Impl::CudaLockArraysStruct kokkos_impl_cuda_lock_arrays ;
+
+#define CUDA_SPACE_ATOMIC_MASK 0x1FFFF
+#define CUDA_SPACE_ATOMIC_XOR_MASK 0x15A39
+
+namespace Kokkos {
+namespace Impl {
+  void* cuda_resize_scratch_space(size_t bytes, bool force_shrink = false);
+}
+}
+
+namespace Kokkos {
+namespace Impl {
+__device__ inline
+bool lock_address_cuda_space(void* ptr) {
+  size_t offset = size_t(ptr);
+  offset = offset >> 2;
+  offset = offset & CUDA_SPACE_ATOMIC_MASK;
+  return (0 == atomicCAS(&kokkos_impl_cuda_lock_arrays.atomic[offset],0,1));
+}
+
+__device__ inline
+void unlock_address_cuda_space(void* ptr) {
+  size_t offset = size_t(ptr);
+  offset = offset >> 2;
+  offset = offset & CUDA_SPACE_ATOMIC_MASK;
+  atomicExch( &kokkos_impl_cuda_lock_arrays.atomic[ offset ], 0);
+}
+
+}
+}
+
+template< typename T >
+inline
+__device__
+T * kokkos_impl_cuda_shared_memory()
+{ extern __shared__ Kokkos::CudaSpace::size_type sh[]; return (T*) sh ; }
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+// See section B.17 of Cuda C Programming Guide Version 3.2
+// for discussion of
+//   __launch_bounds__(maxThreadsPerBlock,minBlocksPerMultiprocessor)
+// function qualifier which could be used to improve performance.
+//----------------------------------------------------------------------------
+// Maximize L1 cache and minimize shared memory:
+//   cudaFuncSetCacheConfig(MyKernel, cudaFuncCachePreferL1 );
+// For 2.0 capability: 48 KB L1 and 16 KB shared
+//----------------------------------------------------------------------------
+
+template< class DriverType >
+__global__
+static void cuda_parallel_launch_constant_memory()
+{
+  const DriverType & driver =
+    *((const DriverType *) kokkos_impl_cuda_constant_memory_buffer );
+
+  driver();
+}
+
+template< class DriverType >
+__global__
+static void cuda_parallel_launch_local_memory( const DriverType driver )
+{
+  driver();
+}
+
+template < class DriverType ,
+           bool Large = ( CudaTraits::ConstantMemoryUseThreshold < sizeof(DriverType) ) >
+struct CudaParallelLaunch ;
+
+template < class DriverType >
+struct CudaParallelLaunch< DriverType , true > {
+
+  inline
+  CudaParallelLaunch( const DriverType & driver
+                    , const dim3       & grid
+                    , const dim3       & block
+                    , const int          shmem
+                    , const cudaStream_t stream = 0 )
+  {
+    if ( grid.x && ( block.x * block.y * block.z ) ) {
+
+      if ( sizeof( Kokkos::Impl::CudaTraits::ConstantGlobalBufferType ) <
+           sizeof( DriverType ) ) {
+        Kokkos::Impl::throw_runtime_exception( std::string("CudaParallelLaunch FAILED: Functor is too large") );
+      }
+
+      // Fence before changing settings and copying closure
+      Kokkos::Cuda::fence();
+
+      if ( CudaTraits::SharedMemoryCapacity < shmem ) {
+        Kokkos::Impl::throw_runtime_exception( std::string("CudaParallelLaunch FAILED: shared memory request is too large") );
+      }
+      #ifndef KOKKOS_ARCH_KEPLER //On Kepler the L1 has no benefit since it doesn't cache reads
+      else if ( shmem ) {
+        CUDA_SAFE_CALL( cudaFuncSetCacheConfig( cuda_parallel_launch_constant_memory< DriverType > , cudaFuncCachePreferShared ) );
+      } else {
+        CUDA_SAFE_CALL( cudaFuncSetCacheConfig( cuda_parallel_launch_constant_memory< DriverType > , cudaFuncCachePreferL1 ) );
+      }
+      #endif
+
+      // Copy functor to constant memory on the device
+      cudaMemcpyToSymbol( kokkos_impl_cuda_constant_memory_buffer , & driver , sizeof(DriverType) );
+
+      #ifndef KOKKOS_CUDA_USE_RELOCATABLE_DEVICE_CODE
+      Kokkos::Impl::CudaLockArraysStruct locks;
+      locks.atomic = atomic_lock_array_cuda_space_ptr(false);
+      locks.scratch = scratch_lock_array_cuda_space_ptr(false);
+      locks.threadid = threadid_lock_array_cuda_space_ptr(false);
+      cudaMemcpyToSymbol( kokkos_impl_cuda_lock_arrays , & locks , sizeof(CudaLockArraysStruct) );
+      #endif
+
+      // Invoke the driver function on the device
+      cuda_parallel_launch_constant_memory< DriverType ><<< grid , block , shmem , stream >>>();
+
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+      CUDA_SAFE_CALL( cudaGetLastError() );
+      Kokkos::Cuda::fence();
+#endif
+    }
+  }
+};
+
+template < class DriverType >
+struct CudaParallelLaunch< DriverType , false > {
+
+  inline
+  CudaParallelLaunch( const DriverType & driver
+                    , const dim3       & grid
+                    , const dim3       & block
+                    , const int          shmem
+                    , const cudaStream_t stream = 0 )
+  {
+    if ( grid.x && ( block.x * block.y * block.z ) ) {
+
+      if ( CudaTraits::SharedMemoryCapacity < shmem ) {
+        Kokkos::Impl::throw_runtime_exception( std::string("CudaParallelLaunch FAILED: shared memory request is too large") );
+      }
+      #ifndef KOKKOS_ARCH_KEPLER //On Kepler the L1 has no benefit since it doesn't cache reads
+      else if ( shmem ) {
+        CUDA_SAFE_CALL( cudaFuncSetCacheConfig( cuda_parallel_launch_local_memory< DriverType > , cudaFuncCachePreferShared ) );
+      } else {
+        CUDA_SAFE_CALL( cudaFuncSetCacheConfig( cuda_parallel_launch_local_memory< DriverType > , cudaFuncCachePreferL1 ) );
+      }
+      #endif
+
+      #ifndef KOKKOS_CUDA_USE_RELOCATABLE_DEVICE_CODE
+      Kokkos::Impl::CudaLockArraysStruct locks;
+      locks.atomic = atomic_lock_array_cuda_space_ptr(false);
+      locks.scratch = scratch_lock_array_cuda_space_ptr(false);
+      locks.threadid = threadid_lock_array_cuda_space_ptr(false);
+      cudaMemcpyToSymbol( kokkos_impl_cuda_lock_arrays , & locks , sizeof(CudaLockArraysStruct) );
+      #endif
+
+      cuda_parallel_launch_local_memory< DriverType ><<< grid , block , shmem , stream >>>( driver );
+
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+      CUDA_SAFE_CALL( cudaGetLastError() );
+      Kokkos::Cuda::fence();
+#endif
+    }
+  }
+};
+
+//----------------------------------------------------------------------------
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* defined( __CUDACC__ ) */
+#endif /* defined( KOKKOS_HAVE_CUDA ) */
+#endif /* #ifndef KOKKOS_CUDAEXEC_HPP */
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_CudaSpace.cpp b/lib/kokkos/core/src/Cuda/Kokkos_CudaSpace.cpp
new file mode 100644
index 0000000000..a4f372d65d
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_CudaSpace.cpp
@@ -0,0 +1,829 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdlib.h>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <algorithm>
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#ifdef KOKKOS_HAVE_CUDA
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Cuda.hpp>
+#include <Kokkos_CudaSpace.hpp>
+
+#include <Cuda/Kokkos_Cuda_Internal.hpp>
+#include <impl/Kokkos_Error.hpp>
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+namespace {
+   cudaStream_t get_deep_copy_stream() {
+     static cudaStream_t s = 0;
+     if( s == 0) {
+       cudaStreamCreate ( &s );
+     }
+     return s;
+   }
+}
+
+DeepCopy<CudaSpace,CudaSpace,Cuda>::DeepCopy( void * dst , const void * src , size_t n )
+{ CUDA_SAFE_CALL( cudaMemcpy( dst , src , n , cudaMemcpyDefault ) ); }
+
+DeepCopy<HostSpace,CudaSpace,Cuda>::DeepCopy( void * dst , const void * src , size_t n )
+{ CUDA_SAFE_CALL( cudaMemcpy( dst , src , n , cudaMemcpyDefault ) ); }
+
+DeepCopy<CudaSpace,HostSpace,Cuda>::DeepCopy( void * dst , const void * src , size_t n )
+{ CUDA_SAFE_CALL( cudaMemcpy( dst , src , n , cudaMemcpyDefault ) ); }
+
+DeepCopy<CudaSpace,CudaSpace,Cuda>::DeepCopy( const Cuda & instance , void * dst , const void * src , size_t n )
+{ CUDA_SAFE_CALL( cudaMemcpyAsync( dst , src , n , cudaMemcpyDefault , instance.cuda_stream() ) ); }
+
+DeepCopy<HostSpace,CudaSpace,Cuda>::DeepCopy( const Cuda & instance , void * dst , const void * src , size_t n )
+{ CUDA_SAFE_CALL( cudaMemcpyAsync( dst , src , n , cudaMemcpyDefault , instance.cuda_stream() ) ); }
+
+DeepCopy<CudaSpace,HostSpace,Cuda>::DeepCopy( const Cuda & instance , void * dst , const void * src , size_t n )
+{ CUDA_SAFE_CALL( cudaMemcpyAsync( dst , src , n , cudaMemcpyDefault , instance.cuda_stream() ) ); }
+
+void DeepCopyAsyncCuda( void * dst , const void * src , size_t n) {
+  cudaStream_t s = get_deep_copy_stream();
+  CUDA_SAFE_CALL( cudaMemcpyAsync( dst , src , n , cudaMemcpyDefault , s ) );
+  cudaStreamSynchronize(s);
+}
+
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+
+namespace Kokkos {
+
+void CudaSpace::access_error()
+{
+  const std::string msg("Kokkos::CudaSpace::access_error attempt to execute Cuda function from non-Cuda space" );
+  Kokkos::Impl::throw_runtime_exception( msg );
+}
+
+void CudaSpace::access_error( const void * const )
+{
+  const std::string msg("Kokkos::CudaSpace::access_error attempt to execute Cuda function from non-Cuda space" );
+  Kokkos::Impl::throw_runtime_exception( msg );
+}
+
+/*--------------------------------------------------------------------------*/
+
+bool CudaUVMSpace::available()
+{
+#if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && !defined(__APPLE__)
+  enum { UVM_available = true };
+#else
+  enum { UVM_available = false };
+#endif
+  return UVM_available;
+}
+
+/*--------------------------------------------------------------------------*/
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+CudaSpace::CudaSpace()
+  : m_device( Kokkos::Cuda().cuda_device() )
+{
+}
+
+CudaUVMSpace::CudaUVMSpace()
+  : m_device( Kokkos::Cuda().cuda_device() )
+{
+}
+
+CudaHostPinnedSpace::CudaHostPinnedSpace()
+{
+}
+
+void * CudaSpace::allocate( const size_t arg_alloc_size ) const
+{
+  void * ptr = NULL;
+
+  CUDA_SAFE_CALL( cudaMalloc( &ptr, arg_alloc_size ) );
+
+  return ptr ;
+}
+
+void * CudaUVMSpace::allocate( const size_t arg_alloc_size ) const
+{
+  void * ptr = NULL;
+
+  CUDA_SAFE_CALL( cudaMallocManaged( &ptr, arg_alloc_size , cudaMemAttachGlobal ) );
+
+  return ptr ;
+}
+
+void * CudaHostPinnedSpace::allocate( const size_t arg_alloc_size ) const
+{
+  void * ptr = NULL;
+
+  CUDA_SAFE_CALL( cudaHostAlloc( &ptr, arg_alloc_size , cudaHostAllocDefault ) );
+
+  return ptr ;
+}
+
+void CudaSpace::deallocate( void * const arg_alloc_ptr , const size_t /* arg_alloc_size */ ) const
+{
+  try {
+    CUDA_SAFE_CALL( cudaFree( arg_alloc_ptr ) );
+  } catch(...) {}
+}
+
+void CudaUVMSpace::deallocate( void * const arg_alloc_ptr , const size_t /* arg_alloc_size */ ) const
+{
+  try {
+    CUDA_SAFE_CALL( cudaFree( arg_alloc_ptr ) );
+  } catch(...) {}
+}
+
+void CudaHostPinnedSpace::deallocate( void * const arg_alloc_ptr , const size_t /* arg_alloc_size */ ) const
+{
+  try {
+    CUDA_SAFE_CALL( cudaFreeHost( arg_alloc_ptr ) );
+  } catch(...) {}
+}
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+SharedAllocationRecord< void , void >
+SharedAllocationRecord< Kokkos::CudaSpace , void >::s_root_record ;
+
+SharedAllocationRecord< void , void >
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::s_root_record ;
+
+SharedAllocationRecord< void , void >
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::s_root_record ;
+
+::cudaTextureObject_t
+SharedAllocationRecord< Kokkos::CudaSpace , void >::
+attach_texture_object( const unsigned sizeof_alias
+                     , void *   const alloc_ptr
+                     , size_t   const alloc_size )
+{
+  enum { TEXTURE_BOUND_1D = 1u << 27 };
+
+  if ( ( alloc_ptr == 0 ) || ( sizeof_alias * TEXTURE_BOUND_1D <= alloc_size ) ) {
+    std::ostringstream msg ;
+    msg << "Kokkos::CudaSpace ERROR: Cannot attach texture object to"
+        << " alloc_ptr(" << alloc_ptr << ")"
+        << " alloc_size(" << alloc_size << ")"
+        << " max_size(" << ( sizeof_alias * TEXTURE_BOUND_1D ) << ")" ;
+    std::cerr << msg.str() << std::endl ;
+    std::cerr.flush();
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  ::cudaTextureObject_t tex_obj ;
+
+  struct cudaResourceDesc resDesc ;
+  struct cudaTextureDesc  texDesc ;
+
+  memset( & resDesc , 0 , sizeof(resDesc) );
+  memset( & texDesc , 0 , sizeof(texDesc) );
+
+  resDesc.resType                = cudaResourceTypeLinear ;
+  resDesc.res.linear.desc        = ( sizeof_alias ==  4 ?  cudaCreateChannelDesc< int >() :
+                                   ( sizeof_alias ==  8 ?  cudaCreateChannelDesc< ::int2 >() :
+                                  /* sizeof_alias == 16 */ cudaCreateChannelDesc< ::int4 >() ) );
+  resDesc.res.linear.sizeInBytes = alloc_size ;
+  resDesc.res.linear.devPtr      = alloc_ptr ;
+
+  CUDA_SAFE_CALL( cudaCreateTextureObject( & tex_obj , & resDesc, & texDesc, NULL ) );
+
+  return tex_obj ;
+}
+
+std::string
+SharedAllocationRecord< Kokkos::CudaSpace , void >::get_label() const
+{
+  SharedAllocationHeader header ;
+
+  Kokkos::Impl::DeepCopy< Kokkos::HostSpace , Kokkos::CudaSpace >( & header , RecordBase::head() , sizeof(SharedAllocationHeader) );
+
+  return std::string( header.m_label );
+}
+
+std::string
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::get_label() const
+{
+  return std::string( RecordBase::head()->m_label );
+}
+
+std::string
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::get_label() const
+{
+  return std::string( RecordBase::head()->m_label );
+}
+
+SharedAllocationRecord< Kokkos::CudaSpace , void > *
+SharedAllocationRecord< Kokkos::CudaSpace , void >::
+allocate( const Kokkos::CudaSpace &  arg_space
+        , const std::string       &  arg_label
+        , const size_t               arg_alloc_size
+        )
+{
+  return new SharedAllocationRecord( arg_space , arg_label , arg_alloc_size );
+}
+
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void > *
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::
+allocate( const Kokkos::CudaUVMSpace &  arg_space
+        , const std::string          &  arg_label
+        , const size_t                  arg_alloc_size
+        )
+{
+  return new SharedAllocationRecord( arg_space , arg_label , arg_alloc_size );
+}
+
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void > *
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::
+allocate( const Kokkos::CudaHostPinnedSpace &  arg_space
+        , const std::string                 &  arg_label
+        , const size_t                         arg_alloc_size
+        )
+{
+  return new SharedAllocationRecord( arg_space , arg_label , arg_alloc_size );
+}
+
+void
+SharedAllocationRecord< Kokkos::CudaSpace , void >::
+deallocate( SharedAllocationRecord< void , void > * arg_rec )
+{
+  delete static_cast<SharedAllocationRecord*>(arg_rec);
+}
+
+void
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::
+deallocate( SharedAllocationRecord< void , void > * arg_rec )
+{
+  delete static_cast<SharedAllocationRecord*>(arg_rec);
+}
+
+void
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::
+deallocate( SharedAllocationRecord< void , void > * arg_rec )
+{
+  delete static_cast<SharedAllocationRecord*>(arg_rec);
+}
+
+SharedAllocationRecord< Kokkos::CudaSpace , void >::
+~SharedAllocationRecord()
+{
+  m_space.deallocate( SharedAllocationRecord< void , void >::m_alloc_ptr
+                    , SharedAllocationRecord< void , void >::m_alloc_size
+                    );
+}
+
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::
+~SharedAllocationRecord()
+{
+  m_space.deallocate( SharedAllocationRecord< void , void >::m_alloc_ptr
+                    , SharedAllocationRecord< void , void >::m_alloc_size
+                    );
+}
+
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::
+~SharedAllocationRecord()
+{
+  m_space.deallocate( SharedAllocationRecord< void , void >::m_alloc_ptr
+                    , SharedAllocationRecord< void , void >::m_alloc_size
+                    );
+}
+
+SharedAllocationRecord< Kokkos::CudaSpace , void >::
+SharedAllocationRecord( const Kokkos::CudaSpace & arg_space
+                      , const std::string       & arg_label
+                      , const size_t              arg_alloc_size
+                      , const SharedAllocationRecord< void , void >::function_type arg_dealloc
+                      )
+  // Pass through allocated [ SharedAllocationHeader , user_memory ]
+  // Pass through deallocation function
+  : SharedAllocationRecord< void , void >
+      ( & SharedAllocationRecord< Kokkos::CudaSpace , void >::s_root_record
+      , reinterpret_cast<SharedAllocationHeader*>( arg_space.allocate( sizeof(SharedAllocationHeader) + arg_alloc_size ) )
+      , sizeof(SharedAllocationHeader) + arg_alloc_size
+      , arg_dealloc
+      )
+  , m_tex_obj( 0 )
+  , m_space( arg_space )
+{
+  SharedAllocationHeader header ;
+
+  // Fill in the Header information
+  header.m_record = static_cast< SharedAllocationRecord< void , void > * >( this );
+
+  strncpy( header.m_label
+          , arg_label.c_str()
+          , SharedAllocationHeader::maximum_label_length
+          );
+
+  // Copy to device memory
+  Kokkos::Impl::DeepCopy<CudaSpace,HostSpace>::DeepCopy( RecordBase::m_alloc_ptr , & header , sizeof(SharedAllocationHeader) );
+}
+
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::
+SharedAllocationRecord( const Kokkos::CudaUVMSpace & arg_space
+                      , const std::string          & arg_label
+                      , const size_t                 arg_alloc_size
+                      , const SharedAllocationRecord< void , void >::function_type arg_dealloc
+                      )
+  // Pass through allocated [ SharedAllocationHeader , user_memory ]
+  // Pass through deallocation function
+  : SharedAllocationRecord< void , void >
+      ( & SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::s_root_record
+      , reinterpret_cast<SharedAllocationHeader*>( arg_space.allocate( sizeof(SharedAllocationHeader) + arg_alloc_size ) )
+      , sizeof(SharedAllocationHeader) + arg_alloc_size
+      , arg_dealloc
+      )
+  , m_tex_obj( 0 )
+  , m_space( arg_space )
+{
+  // Fill in the Header information, directly accessible via UVM
+
+  RecordBase::m_alloc_ptr->m_record = this ;
+
+  strncpy( RecordBase::m_alloc_ptr->m_label
+          , arg_label.c_str()
+          , SharedAllocationHeader::maximum_label_length
+          );
+}
+
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::
+SharedAllocationRecord( const Kokkos::CudaHostPinnedSpace & arg_space
+                      , const std::string                 & arg_label
+                      , const size_t                        arg_alloc_size
+                      , const SharedAllocationRecord< void , void >::function_type arg_dealloc
+                      )
+  // Pass through allocated [ SharedAllocationHeader , user_memory ]
+  // Pass through deallocation function
+  : SharedAllocationRecord< void , void >
+      ( & SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::s_root_record
+      , reinterpret_cast<SharedAllocationHeader*>( arg_space.allocate( sizeof(SharedAllocationHeader) + arg_alloc_size ) )
+      , sizeof(SharedAllocationHeader) + arg_alloc_size
+      , arg_dealloc
+      )
+  , m_space( arg_space )
+{
+  // Fill in the Header information, directly accessible via UVM
+
+  RecordBase::m_alloc_ptr->m_record = this ;
+
+  strncpy( RecordBase::m_alloc_ptr->m_label
+          , arg_label.c_str()
+          , SharedAllocationHeader::maximum_label_length
+          );
+}
+
+//----------------------------------------------------------------------------
+
+void * SharedAllocationRecord< Kokkos::CudaSpace , void >::
+allocate_tracked( const Kokkos::CudaSpace & arg_space
+                , const std::string & arg_alloc_label
+                , const size_t arg_alloc_size )
+{
+  if ( ! arg_alloc_size ) return (void *) 0 ;
+
+  SharedAllocationRecord * const r =
+    allocate( arg_space , arg_alloc_label , arg_alloc_size );
+
+  RecordBase::increment( r );
+
+  return r->data();
+}
+
+void SharedAllocationRecord< Kokkos::CudaSpace , void >::
+deallocate_tracked( void * const arg_alloc_ptr )
+{
+  if ( arg_alloc_ptr != 0 ) {
+    SharedAllocationRecord * const r = get_record( arg_alloc_ptr );
+
+    RecordBase::decrement( r );
+  }
+}
+
+void * SharedAllocationRecord< Kokkos::CudaSpace , void >::
+reallocate_tracked( void * const arg_alloc_ptr
+                  , const size_t arg_alloc_size )
+{
+  SharedAllocationRecord * const r_old = get_record( arg_alloc_ptr );
+  SharedAllocationRecord * const r_new = allocate( r_old->m_space , r_old->get_label() , arg_alloc_size );
+
+  Kokkos::Impl::DeepCopy<CudaSpace,CudaSpace>( r_new->data() , r_old->data()
+                                             , std::min( r_old->size() , r_new->size() ) );
+
+  RecordBase::increment( r_new );
+  RecordBase::decrement( r_old );
+
+  return r_new->data();
+}
+
+void * SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::
+allocate_tracked( const Kokkos::CudaUVMSpace & arg_space
+                , const std::string & arg_alloc_label
+                , const size_t arg_alloc_size )
+{
+  if ( ! arg_alloc_size ) return (void *) 0 ;
+
+  SharedAllocationRecord * const r =
+    allocate( arg_space , arg_alloc_label , arg_alloc_size );
+
+  RecordBase::increment( r );
+
+  return r->data();
+}
+
+void SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::
+deallocate_tracked( void * const arg_alloc_ptr )
+{
+  if ( arg_alloc_ptr != 0 ) {
+    SharedAllocationRecord * const r = get_record( arg_alloc_ptr );
+
+    RecordBase::decrement( r );
+  }
+}
+
+void * SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::
+reallocate_tracked( void * const arg_alloc_ptr
+                  , const size_t arg_alloc_size )
+{
+  SharedAllocationRecord * const r_old = get_record( arg_alloc_ptr );
+  SharedAllocationRecord * const r_new = allocate( r_old->m_space , r_old->get_label() , arg_alloc_size );
+
+  Kokkos::Impl::DeepCopy<CudaUVMSpace,CudaUVMSpace>( r_new->data() , r_old->data()
+                                             , std::min( r_old->size() , r_new->size() ) );
+
+  RecordBase::increment( r_new );
+  RecordBase::decrement( r_old );
+
+  return r_new->data();
+}
+
+void * SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::
+allocate_tracked( const Kokkos::CudaHostPinnedSpace & arg_space
+                , const std::string & arg_alloc_label
+                , const size_t arg_alloc_size )
+{
+  if ( ! arg_alloc_size ) return (void *) 0 ;
+
+  SharedAllocationRecord * const r =
+    allocate( arg_space , arg_alloc_label , arg_alloc_size );
+
+  RecordBase::increment( r );
+
+  return r->data();
+}
+
+void SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::
+deallocate_tracked( void * const arg_alloc_ptr )
+{
+  if ( arg_alloc_ptr != 0 ) {
+    SharedAllocationRecord * const r = get_record( arg_alloc_ptr );
+
+    RecordBase::decrement( r );
+  }
+}
+
+void * SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::
+reallocate_tracked( void * const arg_alloc_ptr
+                  , const size_t arg_alloc_size )
+{
+  SharedAllocationRecord * const r_old = get_record( arg_alloc_ptr );
+  SharedAllocationRecord * const r_new = allocate( r_old->m_space , r_old->get_label() , arg_alloc_size );
+
+  Kokkos::Impl::DeepCopy<CudaHostPinnedSpace,CudaHostPinnedSpace>( r_new->data() , r_old->data()
+                                             , std::min( r_old->size() , r_new->size() ) );
+
+  RecordBase::increment( r_new );
+  RecordBase::decrement( r_old );
+
+  return r_new->data();
+}
+
+//----------------------------------------------------------------------------
+
+SharedAllocationRecord< Kokkos::CudaSpace , void > *
+SharedAllocationRecord< Kokkos::CudaSpace , void >::get_record( void * alloc_ptr )
+{
+  using Header     = SharedAllocationHeader ;
+  using RecordBase = SharedAllocationRecord< void , void > ;
+  using RecordCuda = SharedAllocationRecord< Kokkos::CudaSpace , void > ;
+
+#if 0
+  // Copy the header from the allocation
+  Header head ;
+
+  Header const * const head_cuda = alloc_ptr ? Header::get_header( alloc_ptr ) : (Header*) 0 ;
+
+  if ( alloc_ptr ) {
+    Kokkos::Impl::DeepCopy<HostSpace,CudaSpace>::DeepCopy( & head , head_cuda , sizeof(SharedAllocationHeader) );
+  }
+
+  RecordCuda * const record = alloc_ptr ? static_cast< RecordCuda * >( head.m_record ) : (RecordCuda *) 0 ;
+
+  if ( ! alloc_ptr || record->m_alloc_ptr != head_cuda ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::CudaSpace , void >::get_record ERROR" ) );
+  }
+
+#else
+
+  // Iterate the list to search for the record among all allocations
+  // requires obtaining the root of the list and then locking the list.
+
+  RecordCuda * const record = static_cast< RecordCuda * >( RecordBase::find( & s_root_record , alloc_ptr ) );
+
+  if ( record == 0 ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::CudaSpace , void >::get_record ERROR" ) );
+  }
+
+#endif
+
+  return record ;
+}
+
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void > *
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::get_record( void * alloc_ptr )
+{
+  using Header     = SharedAllocationHeader ;
+  using RecordCuda = SharedAllocationRecord< Kokkos::CudaUVMSpace , void > ;
+
+  Header * const h = alloc_ptr ? reinterpret_cast< Header * >( alloc_ptr ) - 1 : (Header *) 0 ;
+
+  if ( ! alloc_ptr || h->m_record->m_alloc_ptr != h ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::get_record ERROR" ) );
+  }
+
+  return static_cast< RecordCuda * >( h->m_record );
+}
+
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void > *
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::get_record( void * alloc_ptr )
+{
+  using Header     = SharedAllocationHeader ;
+  using RecordCuda = SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void > ;
+
+  Header * const h = alloc_ptr ? reinterpret_cast< Header * >( alloc_ptr ) - 1 : (Header *) 0 ;
+
+  if ( ! alloc_ptr || h->m_record->m_alloc_ptr != h ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::get_record ERROR" ) );
+  }
+
+  return static_cast< RecordCuda * >( h->m_record );
+}
+
+// Iterate records to print orphaned memory ...
+void
+SharedAllocationRecord< Kokkos::CudaSpace , void >::
+print_records( std::ostream & s , const Kokkos::CudaSpace & space , bool detail )
+{
+  SharedAllocationRecord< void , void > * r = & s_root_record ;
+
+  char buffer[256] ;
+
+  SharedAllocationHeader head ;
+
+  if ( detail ) {
+    do {
+      if ( r->m_alloc_ptr ) {
+        Kokkos::Impl::DeepCopy<HostSpace,CudaSpace>::DeepCopy( & head , r->m_alloc_ptr , sizeof(SharedAllocationHeader) );
+      }
+      else {
+        head.m_label[0] = 0 ;
+      }
+
+      //Formatting dependent on sizeof(uintptr_t)
+      const char * format_string;
+
+      if (sizeof(uintptr_t) == sizeof(unsigned long)) { 
+        format_string = "Cuda addr( 0x%.12lx ) list( 0x%.12lx 0x%.12lx ) extent[ 0x%.12lx + %.8ld ] count(%d) dealloc(0x%.12lx) %s\n";
+      }
+      else if (sizeof(uintptr_t) == sizeof(unsigned long long)) { 
+        format_string = "Cuda addr( 0x%.12llx ) list( 0x%.12llx 0x%.12llx ) extent[ 0x%.12llx + %.8ld ] count(%d) dealloc(0x%.12llx) %s\n";
+      }
+
+      snprintf( buffer , 256 
+              , format_string
+              , reinterpret_cast<uintptr_t>( r )
+              , reinterpret_cast<uintptr_t>( r->m_prev )
+              , reinterpret_cast<uintptr_t>( r->m_next )
+              , reinterpret_cast<uintptr_t>( r->m_alloc_ptr )
+              , r->m_alloc_size
+              , r->m_count
+              , reinterpret_cast<uintptr_t>( r->m_dealloc )
+              , head.m_label
+              );
+      std::cout << buffer ;
+      r = r->m_next ;
+    } while ( r != & s_root_record );
+  }
+  else {
+    do {
+      if ( r->m_alloc_ptr ) {
+
+        Kokkos::Impl::DeepCopy<HostSpace,CudaSpace>::DeepCopy( & head , r->m_alloc_ptr , sizeof(SharedAllocationHeader) );
+
+        //Formatting dependent on sizeof(uintptr_t)
+        const char * format_string;
+
+        if (sizeof(uintptr_t) == sizeof(unsigned long)) { 
+          format_string = "Cuda [ 0x%.12lx + %ld ] %s\n";
+        }
+        else if (sizeof(uintptr_t) == sizeof(unsigned long long)) { 
+          format_string = "Cuda [ 0x%.12llx + %ld ] %s\n";
+        }
+
+        snprintf( buffer , 256 
+                , format_string
+                , reinterpret_cast< uintptr_t >( r->data() )
+                , r->size()
+                , head.m_label
+                );
+      }
+      else {
+        snprintf( buffer , 256 , "Cuda [ 0 + 0 ]\n" );
+      }
+      std::cout << buffer ;
+      r = r->m_next ;
+    } while ( r != & s_root_record );
+  }
+}
+
+void
+SharedAllocationRecord< Kokkos::CudaUVMSpace , void >::
+print_records( std::ostream & s , const Kokkos::CudaUVMSpace & space , bool detail )
+{
+  SharedAllocationRecord< void , void >::print_host_accessible_records( s , "CudaUVM" , & s_root_record , detail );
+}
+
+void
+SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >::
+print_records( std::ostream & s , const Kokkos::CudaHostPinnedSpace & space , bool detail )
+{
+  SharedAllocationRecord< void , void >::print_host_accessible_records( s , "CudaHostPinned" , & s_root_record , detail );
+}
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace {
+  __global__ void init_lock_array_kernel_atomic() {
+    unsigned i = blockIdx.x*blockDim.x + threadIdx.x;
+
+    if(i<CUDA_SPACE_ATOMIC_MASK+1)
+      kokkos_impl_cuda_lock_arrays.atomic[i] = 0;
+  }
+
+  __global__ void init_lock_array_kernel_scratch_threadid(int N) {
+    unsigned i = blockIdx.x*blockDim.x + threadIdx.x;
+
+    if(i<N) {
+      kokkos_impl_cuda_lock_arrays.scratch[i] = 0;
+      kokkos_impl_cuda_lock_arrays.threadid[i] = 0;
+    }
+  }
+}
+
+
+namespace Impl {
+int* atomic_lock_array_cuda_space_ptr(bool deallocate) {
+  static int* ptr = NULL;
+  if(deallocate) {
+    cudaFree(ptr);
+    ptr = NULL;
+  }
+
+  if(ptr==NULL && !deallocate)
+    cudaMalloc(&ptr,sizeof(int)*(CUDA_SPACE_ATOMIC_MASK+1));
+  return ptr;
+}
+
+int* scratch_lock_array_cuda_space_ptr(bool deallocate) {
+  static int* ptr = NULL;
+  if(deallocate) {
+    cudaFree(ptr);
+    ptr = NULL;
+  }
+
+  if(ptr==NULL && !deallocate)
+    cudaMalloc(&ptr,sizeof(int)*(Cuda::concurrency()));
+  return ptr;
+}
+
+int* threadid_lock_array_cuda_space_ptr(bool deallocate) {
+  static int* ptr = NULL;
+  if(deallocate) {
+    cudaFree(ptr);
+    ptr = NULL;
+  }
+
+  if(ptr==NULL && !deallocate)
+    cudaMalloc(&ptr,sizeof(int)*(Cuda::concurrency()));
+  return ptr;
+}
+
+void init_lock_arrays_cuda_space() {
+  static int is_initialized = 0;
+  if(! is_initialized) {
+    Kokkos::Impl::CudaLockArraysStruct locks;
+    locks.atomic = atomic_lock_array_cuda_space_ptr(false);
+    locks.scratch = scratch_lock_array_cuda_space_ptr(false);
+    locks.threadid = threadid_lock_array_cuda_space_ptr(false);
+    cudaMemcpyToSymbol( kokkos_impl_cuda_lock_arrays , & locks , sizeof(CudaLockArraysStruct) );
+    init_lock_array_kernel_atomic<<<(CUDA_SPACE_ATOMIC_MASK+255)/256,256>>>();
+    init_lock_array_kernel_scratch_threadid<<<(Kokkos::Cuda::concurrency()+255)/256,256>>>(Kokkos::Cuda::concurrency());
+  }
+}
+
+void* cuda_resize_scratch_space(size_t bytes, bool force_shrink) {
+  static void* ptr = NULL;
+  static size_t current_size = 0;
+  if(current_size == 0) {
+    current_size = bytes;
+    ptr = Kokkos::kokkos_malloc<Kokkos::CudaSpace>("CudaSpace::ScratchMemory",current_size);
+  }
+  if(bytes > current_size) {
+    current_size = bytes;
+    ptr = Kokkos::kokkos_realloc<Kokkos::CudaSpace>(ptr,current_size);
+  }
+  if((bytes < current_size) && (force_shrink)) {
+    current_size = bytes;
+    Kokkos::kokkos_free<Kokkos::CudaSpace>(ptr);
+    ptr = Kokkos::kokkos_malloc<Kokkos::CudaSpace>("CudaSpace::ScratchMemory",current_size);
+  }
+  return ptr;
+}
+
+}
+}
+#endif // KOKKOS_HAVE_CUDA
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Alloc.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Alloc.hpp
new file mode 100644
index 0000000000..10999ee57b
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Alloc.hpp
@@ -0,0 +1,182 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDA_ALLOCATION_TRACKING_HPP
+#define KOKKOS_CUDA_ALLOCATION_TRACKING_HPP
+
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#ifdef KOKKOS_HAVE_CUDA
+
+#include <impl/Kokkos_Traits.hpp>
+
+namespace Kokkos {
+namespace Impl {
+
+template< class DestructFunctor >
+SharedAllocationRecord *
+shared_allocation_record( Kokkos::CudaSpace const & arg_space
+                        , void *            const   arg_alloc_ptr
+                        , DestructFunctor   const & arg_destruct )
+{
+  SharedAllocationRecord * const record = SharedAllocationRecord::get_record( arg_alloc_ptr );
+
+  // assert: record != 0
+
+  // assert: sizeof(DestructFunctor) <= record->m_destruct_size
+
+  // assert: record->m_destruct_function == 0
+
+  DestructFunctor * const functor =
+    reinterpret_cast< DestructFunctor * >(
+    reinterpret_cast< uintptr_t >( record ) + sizeof(SharedAllocationRecord) );
+
+  new( functor ) DestructFunctor( arg_destruct );
+
+  record->m_destruct_functor = & shared_allocation_destroy< DestructFunctor > ;
+  
+  return record ;
+}
+
+
+/// class CudaUnmanagedAllocator
+/// does nothing when deallocate(ptr,size) is called
+struct CudaUnmanagedAllocator
+{
+  static const char * name()
+  {
+    return "Cuda Unmanaged Allocator";
+  }
+
+  static void deallocate(void * /*ptr*/, size_t /*size*/) {}
+
+  static bool support_texture_binding() { return true; }
+};
+
+/// class CudaUnmanagedAllocator
+/// does nothing when deallocate(ptr,size) is called
+struct CudaUnmanagedUVMAllocator
+{
+  static const char * name()
+  {
+    return "Cuda Unmanaged UVM Allocator";
+  }
+
+  static void deallocate(void * /*ptr*/, size_t /*size*/) {}
+
+  static bool support_texture_binding() { return true; }
+};
+
+/// class CudaUnmanagedHostAllocator
+/// does nothing when deallocate(ptr,size) is called
+class CudaUnmanagedHostAllocator
+{
+public:
+  static const char * name()
+  {
+    return "Cuda Unmanaged Host Allocator";
+  }
+  // Unmanaged deallocate does nothing
+  static void deallocate(void * /*ptr*/, size_t /*size*/) {}
+};
+
+/// class CudaMallocAllocator
+class CudaMallocAllocator
+{
+public:
+  static const char * name()
+  {
+    return "Cuda Malloc Allocator";
+  }
+
+  static void* allocate(size_t size);
+
+  static void deallocate(void * ptr, size_t);
+
+  static void * reallocate(void * old_ptr, size_t old_size, size_t new_size);
+
+  static bool support_texture_binding() { return true; }
+};
+
+/// class CudaUVMAllocator
+class CudaUVMAllocator
+{
+public:
+  static const char * name()
+  {
+    return "Cuda UVM Allocator";
+  }
+
+  static void* allocate(size_t size);
+
+  static void deallocate(void * ptr, size_t);
+
+  static void * reallocate(void * old_ptr, size_t old_size, size_t new_size);
+
+  static bool support_texture_binding() { return true; }
+};
+
+/// class CudaHostAllocator
+class CudaHostAllocator
+{
+public:
+  static const char * name()
+  {
+    return "Cuda Host Allocator";
+  }
+
+  static void* allocate(size_t size);
+
+  static void deallocate(void * ptr, size_t);
+
+  static void * reallocate(void * old_ptr, size_t old_size, size_t new_size);
+};
+
+
+}} // namespace Kokkos::Impl
+
+#endif //KOKKOS_HAVE_CUDA
+
+#endif // #ifndef KOKKOS_CUDA_ALLOCATION_TRACKING_HPP
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Error.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Error.hpp
new file mode 100644
index 0000000000..a0b29ddc2b
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Error.hpp
@@ -0,0 +1,69 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDA_ERROR_HPP
+#define KOKKOS_CUDA_ERROR_HPP
+
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#ifdef KOKKOS_HAVE_CUDA
+
+namespace Kokkos { namespace Impl {
+
+void cuda_device_synchronize();
+
+void cuda_internal_error_throw( cudaError e , const char * name, const char * file = NULL, const int line = 0 );
+
+inline void cuda_internal_safe_call( cudaError e , const char * name, const char * file = NULL, const int line = 0)
+{
+  if ( cudaSuccess != e ) { cuda_internal_error_throw( e , name, file, line ); }
+}
+
+#define CUDA_SAFE_CALL( call )  \
+	Kokkos::Impl::cuda_internal_safe_call( call , #call, __FILE__, __LINE__ )
+
+}} // namespace Kokkos::Impl
+
+#endif //KOKKOS_HAVE_CUDA
+#endif //KOKKOS_CUDA_ERROR_HPP
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Impl.cpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Impl.cpp
new file mode 100644
index 0000000000..2d8d07d077
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Impl.cpp
@@ -0,0 +1,778 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/*--------------------------------------------------------------------------*/
+/* Kokkos interfaces */
+
+#include <Kokkos_Core.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#ifdef KOKKOS_HAVE_CUDA
+
+#include <Cuda/Kokkos_Cuda_Error.hpp>
+#include <Cuda/Kokkos_Cuda_Internal.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <impl/Kokkos_Profiling_Interface.hpp>
+
+/*--------------------------------------------------------------------------*/
+/* Standard 'C' libraries */
+#include <stdlib.h>
+
+/* Standard 'C++' libraries */
+#include <vector>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#ifdef KOKKOS_CUDA_USE_RELOCATABLE_DEVICE_CODE
+
+__device__ __constant__
+unsigned long kokkos_impl_cuda_constant_memory_buffer[ Kokkos::Impl::CudaTraits::ConstantMemoryUsage / sizeof(unsigned long) ] ;
+
+__device__ __constant__
+Kokkos::Impl::CudaLockArraysStruct kokkos_impl_cuda_lock_arrays ;
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+namespace {
+
+__global__
+void query_cuda_kernel_arch( int * d_arch )
+{
+#if defined( __CUDA_ARCH__ )
+  *d_arch = __CUDA_ARCH__ ;
+#else
+  *d_arch = 0 ;
+#endif
+}
+
+/** Query what compute capability is actually launched to the device: */
+int cuda_kernel_arch()
+{
+  int * d_arch = 0 ;
+  cudaMalloc( (void **) & d_arch , sizeof(int) );
+  query_cuda_kernel_arch<<<1,1>>>( d_arch );
+  int arch = 0 ;
+  cudaMemcpy( & arch , d_arch , sizeof(int) , cudaMemcpyDefault );
+  cudaFree( d_arch );
+  return arch ;
+}
+
+bool cuda_launch_blocking()
+{
+  const char * env = getenv("CUDA_LAUNCH_BLOCKING");
+
+  if (env == 0) return false;
+
+  return atoi(env);
+}
+
+}
+
+void cuda_device_synchronize()
+{
+//  static const bool launch_blocking = cuda_launch_blocking();
+
+//  if (!launch_blocking) {
+    CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+//  }
+}
+
+void cuda_internal_error_throw( cudaError e , const char * name, const char * file, const int line )
+{
+  std::ostringstream out ;
+  out << name << " error( " << cudaGetErrorName(e) << "): " << cudaGetErrorString(e);
+  if (file) {
+    out << " " << file << ":" << line;
+  }
+  throw_runtime_exception( out.str() );
+}
+
+//----------------------------------------------------------------------------
+// Some significant cuda device properties:
+//
+// cudaDeviceProp::name                : Text label for device
+// cudaDeviceProp::major               : Device major number
+// cudaDeviceProp::minor               : Device minor number
+// cudaDeviceProp::warpSize            : number of threads per warp
+// cudaDeviceProp::multiProcessorCount : number of multiprocessors
+// cudaDeviceProp::sharedMemPerBlock   : capacity of shared memory per block
+// cudaDeviceProp::totalConstMem       : capacity of constant memory
+// cudaDeviceProp::totalGlobalMem      : capacity of global memory
+// cudaDeviceProp::maxGridSize[3]      : maximum grid size
+
+//
+//  Section 4.4.2.4 of the CUDA Toolkit Reference Manual
+//
+// struct cudaDeviceProp {
+//   char name[256];
+//   size_t totalGlobalMem;
+//   size_t sharedMemPerBlock;
+//   int regsPerBlock;
+//   int warpSize;
+//   size_t memPitch;
+//   int maxThreadsPerBlock;
+//   int maxThreadsDim[3];
+//   int maxGridSize[3];
+//   size_t totalConstMem;
+//   int major;
+//   int minor;
+//   int clockRate;
+//   size_t textureAlignment;
+//   int deviceOverlap;
+//   int multiProcessorCount;
+//   int kernelExecTimeoutEnabled;
+//   int integrated;
+//   int canMapHostMemory;
+//   int computeMode;
+//   int concurrentKernels;
+//   int ECCEnabled;
+//   int pciBusID;
+//   int pciDeviceID;
+//   int tccDriver;
+//   int asyncEngineCount;
+//   int unifiedAddressing;
+//   int memoryClockRate;
+//   int memoryBusWidth;
+//   int l2CacheSize;
+//   int maxThreadsPerMultiProcessor;
+// };
+
+
+namespace {
+
+
+
+class CudaInternalDevices {
+public:
+  enum { MAXIMUM_DEVICE_COUNT = 64 };
+  struct cudaDeviceProp  m_cudaProp[ MAXIMUM_DEVICE_COUNT ] ;
+  int                    m_cudaDevCount ;
+
+  CudaInternalDevices();
+
+  static const CudaInternalDevices & singleton();
+};
+
+CudaInternalDevices::CudaInternalDevices()
+{
+  // See 'cudaSetDeviceFlags' for host-device thread interaction
+  // Section 4.4.2.6 of the CUDA Toolkit Reference Manual
+
+  CUDA_SAFE_CALL (cudaGetDeviceCount( & m_cudaDevCount ) );
+
+  if(m_cudaDevCount > MAXIMUM_DEVICE_COUNT) {
+    Kokkos::abort("Sorry, you have more GPUs per node than we thought anybody would ever have. Please report this to github.com/kokkos/kokkos.");
+  }
+  for ( int i = 0 ; i < m_cudaDevCount ; ++i ) {
+    CUDA_SAFE_CALL( cudaGetDeviceProperties( m_cudaProp + i , i ) );
+  }
+}
+
+const CudaInternalDevices & CudaInternalDevices::singleton()
+{
+  static CudaInternalDevices self ; return self ;
+}
+
+}
+
+//----------------------------------------------------------------------------
+
+class CudaInternal {
+private:
+
+  CudaInternal( const CudaInternal & );
+  CudaInternal & operator = ( const CudaInternal & );
+
+
+public:
+
+  typedef Cuda::size_type size_type ;
+
+  int         m_cudaDev ;
+  int         m_cudaArch ;
+  unsigned    m_multiProcCount ;
+  unsigned    m_maxWarpCount ;
+  unsigned    m_maxBlock ;
+  unsigned    m_maxSharedWords ;
+  size_type   m_scratchSpaceCount ;
+  size_type   m_scratchFlagsCount ;
+  size_type   m_scratchUnifiedCount ;
+  size_type   m_scratchUnifiedSupported ;
+  size_type   m_streamCount ;
+  size_type * m_scratchSpace ;
+  size_type * m_scratchFlags ;
+  size_type * m_scratchUnified ;
+  cudaStream_t * m_stream ;
+
+  static int was_initialized;
+  static int was_finalized;
+
+  static CudaInternal & singleton();
+
+  int verify_is_initialized( const char * const label ) const ;
+
+  int is_initialized() const
+    { return 0 != m_scratchSpace && 0 != m_scratchFlags ; }
+
+  void initialize( int cuda_device_id , int stream_count );
+  void finalize();
+
+  void print_configuration( std::ostream & ) const ;
+
+  ~CudaInternal();
+
+  CudaInternal()
+    : m_cudaDev( -1 )
+    , m_cudaArch( -1 )
+    , m_multiProcCount( 0 )
+    , m_maxWarpCount( 0 )
+    , m_maxBlock( 0 )
+    , m_maxSharedWords( 0 )
+    , m_scratchSpaceCount( 0 )
+    , m_scratchFlagsCount( 0 )
+    , m_scratchUnifiedCount( 0 )
+    , m_scratchUnifiedSupported( 0 )
+    , m_streamCount( 0 )
+    , m_scratchSpace( 0 )
+    , m_scratchFlags( 0 )
+    , m_scratchUnified( 0 )
+    , m_stream( 0 )
+    {}
+
+  size_type * scratch_space( const size_type size );
+  size_type * scratch_flags( const size_type size );
+  size_type * scratch_unified( const size_type size );
+};
+
+int CudaInternal::was_initialized = 0;
+int CudaInternal::was_finalized = 0;
+//----------------------------------------------------------------------------
+
+
+void CudaInternal::print_configuration( std::ostream & s ) const
+{
+  const CudaInternalDevices & dev_info = CudaInternalDevices::singleton();
+
+#if defined( KOKKOS_HAVE_CUDA )
+    s << "macro  KOKKOS_HAVE_CUDA      : defined" << std::endl ;
+#endif
+#if defined( CUDA_VERSION )
+    s << "macro  CUDA_VERSION          = " << CUDA_VERSION
+      << " = version " << CUDA_VERSION / 1000
+      << "." << ( CUDA_VERSION % 1000 ) / 10
+      << std::endl ;
+#endif
+
+  for ( int i = 0 ; i < dev_info.m_cudaDevCount ; ++i ) {
+    s << "Kokkos::Cuda[ " << i << " ] "
+      << dev_info.m_cudaProp[i].name
+      << " capability " << dev_info.m_cudaProp[i].major << "." << dev_info.m_cudaProp[i].minor
+      << ", Total Global Memory: " << human_memory_size(dev_info.m_cudaProp[i].totalGlobalMem)
+      << ", Shared Memory per Block: " << human_memory_size(dev_info.m_cudaProp[i].sharedMemPerBlock);
+    if ( m_cudaDev == i ) s << " : Selected" ;
+    s << std::endl ;
+  }
+}
+
+//----------------------------------------------------------------------------
+
+CudaInternal::~CudaInternal()
+{
+  if ( m_stream ||
+       m_scratchSpace ||
+       m_scratchFlags ||
+       m_scratchUnified ) {
+    std::cerr << "Kokkos::Cuda ERROR: Failed to call Kokkos::Cuda::finalize()"
+              << std::endl ;
+    std::cerr.flush();
+  }
+
+  m_cudaDev                 = -1 ;
+  m_cudaArch                = -1 ;
+  m_multiProcCount          = 0 ;
+  m_maxWarpCount            = 0 ;
+  m_maxBlock                = 0 ;
+  m_maxSharedWords          = 0 ;
+  m_scratchSpaceCount       = 0 ;
+  m_scratchFlagsCount       = 0 ;
+  m_scratchUnifiedCount     = 0 ;
+  m_scratchUnifiedSupported = 0 ;
+  m_streamCount             = 0 ;
+  m_scratchSpace            = 0 ;
+  m_scratchFlags            = 0 ;
+  m_scratchUnified          = 0 ;
+  m_stream                  = 0 ;
+}
+
+int CudaInternal::verify_is_initialized( const char * const label ) const
+{
+  if ( m_cudaDev < 0 ) {
+    std::cerr << "Kokkos::Cuda::" << label << " : ERROR device not initialized" << std::endl ;
+  }
+  return 0 <= m_cudaDev ;
+}
+
+CudaInternal & CudaInternal::singleton()
+{
+  static CudaInternal self ;
+  return self ;
+}
+
+void CudaInternal::initialize( int cuda_device_id , int stream_count )
+{
+  if ( was_finalized ) Kokkos::abort("Calling Cuda::initialize after Cuda::finalize is illegal\n");
+  was_initialized = 1;
+  if ( is_initialized() ) return;
+
+  enum { WordSize = sizeof(size_type) };
+
+  if ( ! HostSpace::execution_space::is_initialized() ) {
+    const std::string msg("Cuda::initialize ERROR : HostSpace::execution_space is not initialized");
+    throw_runtime_exception( msg );
+  }
+
+  const CudaInternalDevices & dev_info = CudaInternalDevices::singleton();
+
+  const bool ok_init = 0 == m_scratchSpace || 0 == m_scratchFlags ;
+
+  const bool ok_id   = 0 <= cuda_device_id &&
+                            cuda_device_id < dev_info.m_cudaDevCount ;
+
+  // Need device capability 2.0 or better
+
+  const bool ok_dev = ok_id &&
+    ( 2 <= dev_info.m_cudaProp[ cuda_device_id ].major &&
+      0 <= dev_info.m_cudaProp[ cuda_device_id ].minor );
+
+  if ( ok_init && ok_dev ) {
+
+    const struct cudaDeviceProp & cudaProp =
+      dev_info.m_cudaProp[ cuda_device_id ];
+
+    m_cudaDev = cuda_device_id ;
+
+    CUDA_SAFE_CALL( cudaSetDevice( m_cudaDev ) );
+    CUDA_SAFE_CALL( cudaDeviceReset() );
+    Kokkos::Impl::cuda_device_synchronize();
+
+    // Query what compute capability architecture a kernel executes:
+    m_cudaArch = cuda_kernel_arch();
+
+    if ( m_cudaArch != cudaProp.major * 100 + cudaProp.minor * 10 ) {
+      std::cerr << "Kokkos::Cuda::initialize WARNING: running kernels compiled for compute capability "
+                << ( m_cudaArch / 100 ) << "." << ( ( m_cudaArch % 100 ) / 10 )
+                << " on device with compute capability "
+                << cudaProp.major << "." << cudaProp.minor
+                << " , this will likely reduce potential performance."
+                << std::endl ;
+    }
+
+    // number of multiprocessors
+
+    m_multiProcCount = cudaProp.multiProcessorCount ;
+
+    //----------------------------------
+    // Maximum number of warps,
+    // at most one warp per thread in a warp for reduction.
+
+    // HCE 2012-February :
+    // Found bug in CUDA 4.1 that sometimes a kernel launch would fail
+    // if the thread count == 1024 and a functor is passed to the kernel.
+    // Copying the kernel to constant memory and then launching with
+    // thread count == 1024 would work fine.
+    //
+    // HCE 2012-October :
+    // All compute capabilities support at least 16 warps (512 threads).
+    // However, we have found that 8 warps typically gives better performance.
+
+    m_maxWarpCount = 8 ;
+
+    // m_maxWarpCount = cudaProp.maxThreadsPerBlock / Impl::CudaTraits::WarpSize ;
+
+    if ( Impl::CudaTraits::WarpSize < m_maxWarpCount ) {
+      m_maxWarpCount = Impl::CudaTraits::WarpSize ;
+    }
+
+    m_maxSharedWords = cudaProp.sharedMemPerBlock / WordSize ;
+
+    //----------------------------------
+    // Maximum number of blocks:
+
+    m_maxBlock = m_cudaArch < 300 ? 65535 : cudaProp.maxGridSize[0] ;
+
+    //----------------------------------
+
+    m_scratchUnifiedSupported = cudaProp.unifiedAddressing ;
+
+    if ( ! m_scratchUnifiedSupported ) {
+      std::cout << "Kokkos::Cuda device "
+                << cudaProp.name << " capability "
+                << cudaProp.major << "." << cudaProp.minor
+                << " does not support unified virtual address space"
+                << std::endl ;
+    }
+
+    //----------------------------------
+    // Multiblock reduction uses scratch flags for counters
+    // and scratch space for partial reduction values.
+    // Allocate some initial space.  This will grow as needed.
+
+    {
+      const unsigned reduce_block_count = m_maxWarpCount * Impl::CudaTraits::WarpSize ;
+
+      (void) scratch_unified( 16 * sizeof(size_type) );
+      (void) scratch_flags( reduce_block_count * 2  * sizeof(size_type) );
+      (void) scratch_space( reduce_block_count * 16 * sizeof(size_type) );
+    }
+    //----------------------------------
+
+    if ( stream_count ) {
+      m_stream = (cudaStream_t*) ::malloc( stream_count * sizeof(cudaStream_t) );
+      m_streamCount = stream_count ;
+      for ( size_type i = 0 ; i < m_streamCount ; ++i ) m_stream[i] = 0 ;
+    }
+  }
+  else {
+
+    std::ostringstream msg ;
+    msg << "Kokkos::Cuda::initialize(" << cuda_device_id << ") FAILED" ;
+
+    if ( ! ok_init ) {
+      msg << " : Already initialized" ;
+    }
+    if ( ! ok_id ) {
+      msg << " : Device identifier out of range "
+          << "[0.." << dev_info.m_cudaDevCount << "]" ;
+    }
+    else if ( ! ok_dev ) {
+      msg << " : Device " ;
+      msg << dev_info.m_cudaProp[ cuda_device_id ].major ;
+      msg << "." ;
+      msg << dev_info.m_cudaProp[ cuda_device_id ].minor ;
+      msg << " has insufficient capability, required 2.0 or better" ;
+    }
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  #ifdef KOKKOS_CUDA_USE_UVM
+    if(!cuda_launch_blocking()) {
+      std::cout << "Kokkos::Cuda::initialize WARNING: Cuda is allocating into UVMSpace by default" << std::endl;
+      std::cout << "                                  without setting CUDA_LAUNCH_BLOCKING=1." << std::endl;
+      std::cout << "                                  The code must call Cuda::fence() after each kernel" << std::endl;
+      std::cout << "                                  or will likely crash when accessing data on the host." << std::endl; 
+    }
+
+    const char * env_force_device_alloc = getenv("CUDA_MANAGED_FORCE_DEVICE_ALLOC");
+    bool force_device_alloc;
+    if (env_force_device_alloc == 0) force_device_alloc=false;
+    else force_device_alloc=atoi(env_force_device_alloc)!=0;
+  
+    const char * env_visible_devices = getenv("CUDA_VISIBLE_DEVICES");
+    bool visible_devices_one=true;
+    if (env_visible_devices == 0) visible_devices_one=false;
+    
+    if(!visible_devices_one && !force_device_alloc) {
+      std::cout << "Kokkos::Cuda::initialize WARNING: Cuda is allocating into UVMSpace by default" << std::endl;
+      std::cout << "                                  without setting CUDA_MANAGED_FORCE_DEVICE_ALLOC=1 or " << std::endl;
+      std::cout << "                                  setting CUDA_VISIBLE_DEVICES." << std::endl;
+      std::cout << "                                  This could on multi GPU systems lead to severe performance" << std::endl;
+      std::cout << "                                  penalties." << std::endl;
+    }
+  #endif
+
+  cudaThreadSetCacheConfig(cudaFuncCachePreferShared);
+
+  // Init the array for used for arbitrarily sized atomics
+  Impl::init_lock_arrays_cuda_space();
+
+  #ifdef KOKKOS_CUDA_USE_RELOCATABLE_DEVICE_CODE
+  Kokkos::Impl::CudaLockArraysStruct locks;
+  locks.atomic = atomic_lock_array_cuda_space_ptr(false);
+  locks.scratch = scratch_lock_array_cuda_space_ptr(false);
+  locks.threadid = threadid_lock_array_cuda_space_ptr(false);
+  cudaMemcpyToSymbol( kokkos_impl_cuda_lock_arrays , & locks , sizeof(CudaLockArraysStruct) );
+  #endif
+}
+
+//----------------------------------------------------------------------------
+
+typedef Cuda::size_type ScratchGrain[ Impl::CudaTraits::WarpSize ] ;
+enum { sizeScratchGrain = sizeof(ScratchGrain) };
+
+
+Cuda::size_type *
+CudaInternal::scratch_flags( const Cuda::size_type size )
+{
+  if ( verify_is_initialized("scratch_flags") && m_scratchFlagsCount * sizeScratchGrain < size ) {
+
+
+    m_scratchFlagsCount = ( size + sizeScratchGrain - 1 ) / sizeScratchGrain ;
+
+    typedef Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::CudaSpace , void > Record ;
+
+    Record * const r = Record::allocate( Kokkos::CudaSpace()
+                                       , "InternalScratchFlags"
+                                       , ( sizeof( ScratchGrain ) * m_scratchFlagsCount ) );
+
+    Record::increment( r );
+
+    m_scratchFlags = reinterpret_cast<size_type *>( r->data() );
+
+    CUDA_SAFE_CALL( cudaMemset( m_scratchFlags , 0 , m_scratchFlagsCount * sizeScratchGrain ) );
+  }
+
+  return m_scratchFlags ;
+}
+
+Cuda::size_type *
+CudaInternal::scratch_space( const Cuda::size_type size )
+{
+  if ( verify_is_initialized("scratch_space") && m_scratchSpaceCount * sizeScratchGrain < size ) {
+
+    m_scratchSpaceCount = ( size + sizeScratchGrain - 1 ) / sizeScratchGrain ;
+
+     typedef Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::CudaSpace , void > Record ;
+
+     Record * const r = Record::allocate( Kokkos::CudaSpace()
+                                        , "InternalScratchSpace"
+                                        , ( sizeof( ScratchGrain ) * m_scratchSpaceCount ) );
+
+     Record::increment( r );
+
+     m_scratchSpace = reinterpret_cast<size_type *>( r->data() );
+  }
+
+  return m_scratchSpace ;
+}
+
+Cuda::size_type *
+CudaInternal::scratch_unified( const Cuda::size_type size )
+{
+  if ( verify_is_initialized("scratch_unified") &&
+       m_scratchUnifiedSupported && m_scratchUnifiedCount * sizeScratchGrain < size ) {
+
+    m_scratchUnifiedCount = ( size + sizeScratchGrain - 1 ) / sizeScratchGrain ;
+
+    typedef Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void > Record ;
+
+    Record * const r = Record::allocate( Kokkos::CudaHostPinnedSpace()
+                                       , "InternalScratchUnified"
+                                       , ( sizeof( ScratchGrain ) * m_scratchUnifiedCount ) );
+
+    Record::increment( r );
+
+    m_scratchUnified = reinterpret_cast<size_type *>( r->data() );
+  }
+
+  return m_scratchUnified ;
+}
+
+//----------------------------------------------------------------------------
+
+void CudaInternal::finalize()
+{
+  was_finalized = 1;
+  if ( 0 != m_scratchSpace || 0 != m_scratchFlags ) {
+
+    atomic_lock_array_cuda_space_ptr(false);
+    scratch_lock_array_cuda_space_ptr(false);
+    threadid_lock_array_cuda_space_ptr(false);
+
+    if ( m_stream ) {
+      for ( size_type i = 1 ; i < m_streamCount ; ++i ) {
+        cudaStreamDestroy( m_stream[i] );
+        m_stream[i] = 0 ;
+      }
+      ::free( m_stream );
+    }
+
+    typedef Kokkos::Experimental::Impl::SharedAllocationRecord< CudaSpace > RecordCuda ;
+    typedef Kokkos::Experimental::Impl::SharedAllocationRecord< CudaHostPinnedSpace > RecordHost ;
+
+    RecordCuda::decrement( RecordCuda::get_record( m_scratchFlags ) );
+    RecordCuda::decrement( RecordCuda::get_record( m_scratchSpace ) );
+    RecordHost::decrement( RecordHost::get_record( m_scratchUnified ) );
+
+    m_cudaDev             = -1 ;
+    m_multiProcCount      = 0 ;
+    m_maxWarpCount        = 0 ;
+    m_maxBlock            = 0 ;
+    m_maxSharedWords      = 0 ;
+    m_scratchSpaceCount   = 0 ;
+    m_scratchFlagsCount   = 0 ;
+    m_scratchUnifiedCount = 0 ;
+    m_streamCount         = 0 ;
+    m_scratchSpace        = 0 ;
+    m_scratchFlags        = 0 ;
+    m_scratchUnified      = 0 ;
+    m_stream              = 0 ;
+  }
+}
+
+//----------------------------------------------------------------------------
+
+Cuda::size_type cuda_internal_multiprocessor_count()
+{ return CudaInternal::singleton().m_multiProcCount ; }
+
+Cuda::size_type cuda_internal_maximum_warp_count()
+{ return CudaInternal::singleton().m_maxWarpCount ; }
+
+Cuda::size_type cuda_internal_maximum_grid_count()
+{ return CudaInternal::singleton().m_maxBlock ; }
+
+Cuda::size_type cuda_internal_maximum_shared_words()
+{ return CudaInternal::singleton().m_maxSharedWords ; }
+
+Cuda::size_type * cuda_internal_scratch_space( const Cuda::size_type size )
+{ return CudaInternal::singleton().scratch_space( size ); }
+
+Cuda::size_type * cuda_internal_scratch_flags( const Cuda::size_type size )
+{ return CudaInternal::singleton().scratch_flags( size ); }
+
+Cuda::size_type * cuda_internal_scratch_unified( const Cuda::size_type size )
+{ return CudaInternal::singleton().scratch_unified( size ); }
+
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+Cuda::size_type Cuda::detect_device_count()
+{ return Impl::CudaInternalDevices::singleton().m_cudaDevCount ; }
+
+int Cuda::concurrency() {
+  return 131072;
+}
+
+int Cuda::is_initialized()
+{ return Impl::CudaInternal::singleton().is_initialized(); }
+
+void Cuda::initialize( const Cuda::SelectDevice config , size_t num_instances )
+{
+  Impl::CudaInternal::singleton().initialize( config.cuda_device_id , num_instances );
+
+  #if (KOKKOS_ENABLE_PROFILING)
+    Kokkos::Profiling::initialize();
+  #endif
+}
+
+std::vector<unsigned>
+Cuda::detect_device_arch()
+{
+  const Impl::CudaInternalDevices & s = Impl::CudaInternalDevices::singleton();
+
+  std::vector<unsigned> output( s.m_cudaDevCount );
+
+  for ( int i = 0 ; i < s.m_cudaDevCount ; ++i ) {
+    output[i] = s.m_cudaProp[i].major * 100 + s.m_cudaProp[i].minor ;
+  }
+
+  return output ;
+}
+
+Cuda::size_type Cuda::device_arch()
+{
+  const int dev_id = Impl::CudaInternal::singleton().m_cudaDev ;
+
+  int dev_arch = 0 ;
+
+  if ( 0 <= dev_id ) {
+    const struct cudaDeviceProp & cudaProp =
+      Impl::CudaInternalDevices::singleton().m_cudaProp[ dev_id ] ;
+
+    dev_arch = cudaProp.major * 100 + cudaProp.minor ;
+  }
+
+  return dev_arch ;
+}
+
+void Cuda::finalize()
+{
+  Impl::CudaInternal::singleton().finalize();
+
+  #if (KOKKOS_ENABLE_PROFILING)
+    Kokkos::Profiling::finalize();
+  #endif
+}
+
+Cuda::Cuda()
+  : m_device( Impl::CudaInternal::singleton().m_cudaDev )
+  , m_stream( 0 )
+{
+  Impl::CudaInternal::singleton().verify_is_initialized( "Cuda instance constructor" );
+}
+
+Cuda::Cuda( const int instance_id )
+  : m_device( Impl::CudaInternal::singleton().m_cudaDev )
+  , m_stream(
+      Impl::CudaInternal::singleton().verify_is_initialized( "Cuda instance constructor" )
+        ? Impl::CudaInternal::singleton().m_stream[ instance_id % Impl::CudaInternal::singleton().m_streamCount ]
+        : 0 )
+{}
+
+void Cuda::print_configuration( std::ostream & s , const bool )
+{ Impl::CudaInternal::singleton().print_configuration( s ); }
+
+bool Cuda::sleep() { return false ; }
+
+bool Cuda::wake() { return true ; }
+
+void Cuda::fence()
+{
+  Kokkos::Impl::cuda_device_synchronize();
+}
+
+} // namespace Kokkos
+
+#endif // KOKKOS_HAVE_CUDA
+//----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Internal.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Internal.hpp
new file mode 100644
index 0000000000..8b10d47f88
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Internal.hpp
@@ -0,0 +1,202 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDA_INTERNAL_HPP
+#define KOKKOS_CUDA_INTERNAL_HPP
+#include<iostream>
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#ifdef KOKKOS_HAVE_CUDA
+
+#include <Cuda/Kokkos_Cuda_Error.hpp>
+
+namespace Kokkos { namespace Impl {
+
+template<class DriverType, bool Large>
+struct CudaGetMaxBlockSize;
+
+template<class DriverType, bool Large = (CudaTraits::ConstantMemoryUseThreshold < sizeof(DriverType))>
+int cuda_get_max_block_size(const typename DriverType::functor_type & f, const size_t vector_length,
+                            const size_t shmem_extra_block, const size_t shmem_extra_thread) {
+  return CudaGetMaxBlockSize<DriverType,Large>::get_block_size(f,vector_length, shmem_extra_block,shmem_extra_thread);
+}
+
+
+template<class DriverType>
+struct CudaGetMaxBlockSize<DriverType,true> {
+  static int get_block_size(const typename DriverType::functor_type & f, const size_t vector_length,
+                            const size_t shmem_extra_block, const size_t shmem_extra_thread) {
+    int numBlocks;
+    int blockSize=32;
+    int sharedmem = shmem_extra_block + shmem_extra_thread*(blockSize/vector_length) +
+                    FunctorTeamShmemSize< typename DriverType::functor_type  >::value( f , blockSize/vector_length );
+    cudaOccupancyMaxActiveBlocksPerMultiprocessor(
+        &numBlocks,
+        cuda_parallel_launch_constant_memory<DriverType>,
+        blockSize,
+        sharedmem);
+
+    while (blockSize<1024 && numBlocks>0) {
+      blockSize*=2;
+      sharedmem = shmem_extra_block + shmem_extra_thread*(blockSize/vector_length) +
+                  FunctorTeamShmemSize< typename DriverType::functor_type  >::value( f , blockSize/vector_length );
+
+      cudaOccupancyMaxActiveBlocksPerMultiprocessor(
+          &numBlocks,
+          cuda_parallel_launch_constant_memory<DriverType>,
+          blockSize,
+          sharedmem);
+    }
+    if(numBlocks>0) return blockSize;
+    else return blockSize/2;
+  }
+};
+
+template<class DriverType>
+struct CudaGetMaxBlockSize<DriverType,false> {
+  static int get_block_size(const typename DriverType::functor_type & f, const size_t vector_length,
+                            const size_t shmem_extra_block, const size_t shmem_extra_thread) {
+    int numBlocks;
+
+    int blockSize=32;
+    int sharedmem = shmem_extra_block + shmem_extra_thread*(blockSize/vector_length) +
+                    FunctorTeamShmemSize< typename DriverType::functor_type  >::value( f , blockSize/vector_length );
+    cudaOccupancyMaxActiveBlocksPerMultiprocessor(
+        &numBlocks,
+        cuda_parallel_launch_local_memory<DriverType>,
+        blockSize,
+        sharedmem);
+
+    while (blockSize<1024 && numBlocks>0) {
+      blockSize*=2;
+      sharedmem = shmem_extra_block + shmem_extra_thread*(blockSize/vector_length) +
+                  FunctorTeamShmemSize< typename DriverType::functor_type  >::value( f , blockSize/vector_length );
+
+      cudaOccupancyMaxActiveBlocksPerMultiprocessor(
+          &numBlocks,
+          cuda_parallel_launch_local_memory<DriverType>,
+          blockSize,
+          sharedmem);
+    }
+    if(numBlocks>0) return blockSize;
+    else return blockSize/2;
+  }
+};
+
+
+
+template<class DriverType, bool Large>
+struct CudaGetOptBlockSize;
+
+template<class DriverType, bool Large = (CudaTraits::ConstantMemoryUseThreshold < sizeof(DriverType))>
+int cuda_get_opt_block_size(const typename DriverType::functor_type & f, const size_t vector_length,
+                            const size_t shmem_extra_block, const size_t shmem_extra_thread) {
+  return CudaGetOptBlockSize<DriverType,Large>::get_block_size(f,vector_length,shmem_extra_block,shmem_extra_thread);
+}
+
+template<class DriverType>
+struct CudaGetOptBlockSize<DriverType,true> {
+  static int get_block_size(const typename DriverType::functor_type & f, const size_t vector_length,
+                            const size_t shmem_extra_block, const size_t shmem_extra_thread) {
+    int blockSize=16;
+    int numBlocks;
+    int sharedmem;
+    int maxOccupancy=0;
+    int bestBlockSize=0;
+
+    while(blockSize<1024) {
+      blockSize*=2;
+
+      //calculate the occupancy with that optBlockSize and check whether its larger than the largest one found so far
+      sharedmem = shmem_extra_block + shmem_extra_thread*(blockSize/vector_length) +
+                  FunctorTeamShmemSize< typename DriverType::functor_type  >::value( f , blockSize/vector_length );
+      cudaOccupancyMaxActiveBlocksPerMultiprocessor(
+              &numBlocks,
+              cuda_parallel_launch_constant_memory<DriverType>,
+              blockSize,
+              sharedmem);
+      if(maxOccupancy < numBlocks*blockSize) {
+         maxOccupancy = numBlocks*blockSize;
+         bestBlockSize = blockSize;
+      }
+    }
+    return bestBlockSize;
+  }
+};
+
+template<class DriverType>
+struct CudaGetOptBlockSize<DriverType,false> {
+  static int get_block_size(const typename DriverType::functor_type & f, const size_t vector_length,
+                            const size_t shmem_extra_block, const size_t shmem_extra_thread) {
+    int blockSize=16;
+    int numBlocks;
+    int sharedmem;
+    int maxOccupancy=0;
+    int bestBlockSize=0;
+
+    while(blockSize<1024) {
+      blockSize*=2;
+      sharedmem = shmem_extra_block + shmem_extra_thread*(blockSize/vector_length) +
+                  FunctorTeamShmemSize< typename DriverType::functor_type  >::value( f , blockSize/vector_length );
+
+      cudaOccupancyMaxActiveBlocksPerMultiprocessor(
+              &numBlocks,
+              cuda_parallel_launch_local_memory<DriverType>,
+              blockSize,
+              sharedmem);
+
+      if(maxOccupancy < numBlocks*blockSize) {
+        maxOccupancy = numBlocks*blockSize;
+        bestBlockSize = blockSize;
+      }
+    }
+    return bestBlockSize;
+  }
+};
+
+}} // namespace Kokkos::Impl
+
+#endif // KOKKOS_HAVE_CUDA
+#endif /* #ifndef KOKKOS_CUDA_INTERNAL_HPP */
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Parallel.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Parallel.hpp
new file mode 100644
index 0000000000..7afa06fdf5
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Parallel.hpp
@@ -0,0 +1,1926 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDA_PARALLEL_HPP
+#define KOKKOS_CUDA_PARALLEL_HPP
+
+#include <iostream>
+#include <algorithm>
+#include <stdio.h>
+
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#if defined( __CUDACC__ ) && defined( KOKKOS_HAVE_CUDA )
+
+#include <utility>
+#include <Kokkos_Parallel.hpp>
+
+#include <Cuda/Kokkos_CudaExec.hpp>
+#include <Cuda/Kokkos_Cuda_ReduceScan.hpp>
+#include <Cuda/Kokkos_Cuda_Internal.hpp>
+#include <Kokkos_Vectorization.hpp>
+
+#if (KOKKOS_ENABLE_PROFILING)
+#include <impl/Kokkos_Profiling_Interface.hpp>
+#include <typeinfo>
+#endif
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< typename Type >
+struct CudaJoinFunctor {
+  typedef Type value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    volatile const value_type & input )
+    { update += input ; }
+};
+
+class CudaTeamMember {
+private:
+
+  typedef Kokkos::Cuda                           execution_space ;
+  typedef execution_space::scratch_memory_space  scratch_memory_space ;
+
+  void                * m_team_reduce ;
+  scratch_memory_space  m_team_shared ;
+  int                   m_league_rank ;
+  int                   m_league_size ;
+
+public:
+
+#if defined( __CUDA_ARCH__ )
+
+  __device__ inline
+  const execution_space::scratch_memory_space & team_shmem() const
+    { return m_team_shared.set_team_thread_mode(0,1,0) ; }
+  __device__ inline
+  const execution_space::scratch_memory_space & team_scratch(const int& level) const
+    { return m_team_shared.set_team_thread_mode(level,1,0) ; }
+  __device__ inline
+  const execution_space::scratch_memory_space & thread_scratch(const int& level) const
+    { return m_team_shared.set_team_thread_mode(level,team_size(),team_rank()) ; }
+
+  __device__ inline int league_rank() const { return m_league_rank ; }
+  __device__ inline int league_size() const { return m_league_size ; }
+  __device__ inline int team_rank() const { return threadIdx.y ; }
+  __device__ inline int team_size() const { return blockDim.y ; }
+
+  __device__ inline void team_barrier() const { __syncthreads(); }
+
+  template<class ValueType>
+  __device__ inline void team_broadcast(ValueType& value, const int& thread_id) const {
+    __shared__ ValueType sh_val;
+    if(threadIdx.x == 0 && threadIdx.y == thread_id) {
+      sh_val = value;
+    }
+    team_barrier();
+    value = sh_val;
+    team_barrier();
+  }
+
+#ifdef KOKKOS_HAVE_CXX11
+  template< class ValueType, class JoinOp >
+  __device__ inline
+  typename JoinOp::value_type team_reduce( const ValueType & value
+                                         , const JoinOp & op_in ) const
+    {
+      typedef JoinLambdaAdapter<ValueType,JoinOp> JoinOpFunctor ;
+      const JoinOpFunctor op(op_in);
+      ValueType * const base_data = (ValueType *) m_team_reduce ;
+#else
+  template< class JoinOp >
+  __device__ inline
+  typename JoinOp::value_type team_reduce( const typename JoinOp::value_type & value
+                                         , const JoinOp & op ) const
+    {
+      typedef JoinOp JoinOpFunctor ;
+      typename JoinOp::value_type * const base_data = (typename JoinOp::value_type *) m_team_reduce ;
+#endif
+
+      __syncthreads(); // Don't write in to shared data until all threads have entered this function
+
+      if ( 0 == threadIdx.y ) { base_data[0] = 0 ; }
+
+      base_data[ threadIdx.y ] = value ;
+
+      Impl::cuda_intra_block_reduce_scan<false,JoinOpFunctor,void>( op , base_data );
+
+      return base_data[ blockDim.y - 1 ];
+    }
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering
+   *          with intra-team non-deterministic ordering accumulation.
+   *
+   *  The global inter-team accumulation value will, at the end of the
+   *  league's parallel execution, be the scan's total.
+   *  Parallel execution ordering of the league's teams is non-deterministic.
+   *  As such the base value for each team's scan operation is similarly
+   *  non-deterministic.
+   */
+  template< typename Type >
+  __device__ inline Type team_scan( const Type & value , Type * const global_accum ) const
+    {
+      Type * const base_data = (Type *) m_team_reduce ;
+
+      __syncthreads(); // Don't write in to shared data until all threads have entered this function
+
+      if ( 0 == threadIdx.y ) { base_data[0] = 0 ; }
+
+      base_data[ threadIdx.y + 1 ] = value ;
+
+      Impl::cuda_intra_block_reduce_scan<true,Impl::CudaJoinFunctor<Type>,void>( Impl::CudaJoinFunctor<Type>() , base_data + 1 );
+
+      if ( global_accum ) {
+        if ( blockDim.y == threadIdx.y + 1 ) {
+          base_data[ blockDim.y ] = atomic_fetch_add( global_accum , base_data[ blockDim.y ] );
+        }
+        __syncthreads(); // Wait for atomic
+        base_data[ threadIdx.y ] += base_data[ blockDim.y ] ;
+      }
+
+      return base_data[ threadIdx.y ];
+    }
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering.
+   *
+   *  The highest rank thread can compute the reduction total as
+   *    reduction_total = dev.team_scan( value ) + value ;
+   */
+  template< typename Type >
+  __device__ inline Type team_scan( const Type & value ) const
+    { return this->template team_scan<Type>( value , 0 ); }
+
+  //----------------------------------------
+  // Private for the driver
+
+  __device__ inline
+  CudaTeamMember( void * shared
+                , const int shared_begin
+                , const int shared_size
+                , void*     scratch_level_1_ptr
+                , const int scratch_level_1_size
+                , const int arg_league_rank
+                , const int arg_league_size )
+    : m_team_reduce( shared )
+    , m_team_shared( ((char *)shared) + shared_begin , shared_size,  scratch_level_1_ptr, scratch_level_1_size)
+    , m_league_rank( arg_league_rank ) 
+    , m_league_size( arg_league_size ) 
+    {}
+
+#else
+
+  const execution_space::scratch_memory_space & team_shmem() const
+    { return m_team_shared.set_team_thread_mode(0, 1,0) ; }
+  const execution_space::scratch_memory_space & team_scratch(const int& level) const
+    { return m_team_shared.set_team_thread_mode(level,1,0) ; }
+  const execution_space::scratch_memory_space & thread_scratch(const int& level) const
+    { return m_team_shared.set_team_thread_mode(level,team_size(),team_rank()) ; }
+
+  int league_rank() const {return 0;}
+  int league_size() const {return 1;}
+  int team_rank() const {return 0;}
+  int team_size() const {return 1;}
+
+  void team_barrier() const {}
+  template<class ValueType>
+  void team_broadcast(ValueType& value, const int& thread_id) const {}
+
+  template< class JoinOp >
+  typename JoinOp::value_type team_reduce( const typename JoinOp::value_type & value
+                                         , const JoinOp & op ) const {return typename JoinOp::value_type();}
+
+  template< typename Type >
+  Type team_scan( const Type & value , Type * const global_accum ) const {return Type();}
+
+  template< typename Type >
+  Type team_scan( const Type & value ) const {return Type();}
+
+  //----------------------------------------
+  // Private for the driver
+
+  CudaTeamMember( void * shared
+                , const int shared_begin
+                , const int shared_end
+                , void*     scratch_level_1_ptr
+                , const int scratch_level_1_size
+                , const int arg_league_rank
+                , const int arg_league_size );
+
+#endif /* #if ! defined( __CUDA_ARCH__ ) */
+
+};
+
+} // namespace Impl
+
+namespace Impl {
+template< class ... Properties >
+class TeamPolicyInternal< Kokkos::Cuda , Properties ... >: public PolicyTraits<Properties ... >
+{
+public:
+
+  //! Tag this class as a kokkos execution policy
+  typedef TeamPolicyInternal      execution_policy ;
+
+  typedef PolicyTraits<Properties ... > traits;
+
+private:
+
+  enum { MAX_WARP = 8 };
+
+  int m_league_size ;
+  int m_team_size ;
+  int m_vector_length ;
+  int m_team_scratch_size[2] ;
+  int m_thread_scratch_size[2] ;
+  int m_chunk_size;
+
+public:
+
+  //! Execution space of this execution policy
+  typedef Kokkos::Cuda  execution_space ;
+
+  TeamPolicyInternal& operator = (const TeamPolicyInternal& p) {
+    m_league_size = p.m_league_size;
+    m_team_size = p.m_team_size;
+    m_vector_length = p.m_vector_length;
+    m_team_scratch_size[0] = p.m_team_scratch_size[0];
+    m_team_scratch_size[1] = p.m_team_scratch_size[1];
+    m_thread_scratch_size[0] = p.m_thread_scratch_size[0];
+    m_thread_scratch_size[1] = p.m_thread_scratch_size[1];
+    m_chunk_size = p.m_chunk_size;
+    return *this;
+  }
+
+  //----------------------------------------
+
+  template< class FunctorType >
+  inline static
+  int team_size_max( const FunctorType & functor )
+    {
+      int n = MAX_WARP * Impl::CudaTraits::WarpSize ;
+
+      for ( ; n ; n >>= 1 ) {
+        const int shmem_size =
+          /* for global reduce */ Impl::cuda_single_inter_block_reduce_scan_shmem<false,FunctorType,typename traits::work_tag>( functor , n )
+          /* for team   reduce */ + ( n + 2 ) * sizeof(double)
+          /* for team   shared */ + Impl::FunctorTeamShmemSize< FunctorType >::value( functor , n );
+
+        if ( shmem_size < Impl::CudaTraits::SharedMemoryCapacity ) break ;
+      }
+
+      return n ;
+    }
+
+  template< class FunctorType >
+  static int team_size_recommended( const FunctorType & functor )
+    { return team_size_max( functor ); }
+
+  template< class FunctorType >
+  static int team_size_recommended( const FunctorType & functor , const int vector_length)
+    {
+      int max = team_size_max( functor )/vector_length;
+      if(max<1) max = 1;
+      return max;
+    }
+
+  inline static
+  int vector_length_max()
+    { return Impl::CudaTraits::WarpSize; }
+
+  //----------------------------------------
+
+  inline int vector_length()   const { return m_vector_length ; }
+  inline int team_size()   const { return m_team_size ; }
+  inline int league_size() const { return m_league_size ; }
+  inline int scratch_size(int level, int team_size_ = -1) const {
+    if(team_size_<0) team_size_ = m_team_size;
+    return m_team_scratch_size[level] + team_size_*m_thread_scratch_size[level];
+  }
+  inline size_t team_scratch_size(int level) const {
+    return m_team_scratch_size[level];
+  }
+  inline size_t thread_scratch_size(int level) const {
+    return m_thread_scratch_size[level];
+  }
+
+  TeamPolicyInternal()
+    : m_league_size( 0 )
+    , m_team_size( 0 )
+    , m_vector_length( 0 )
+    , m_team_scratch_size {0,0}
+    , m_thread_scratch_size {0,0}
+    , m_chunk_size ( 32 ) 
+   {}
+
+  /** \brief  Specify league size, request team size */
+  TeamPolicyInternal( execution_space &
+            , int league_size_
+            , int team_size_request
+            , int vector_length_request = 1 )
+    : m_league_size( league_size_ )
+    , m_team_size( team_size_request )
+    , m_vector_length( vector_length_request )
+    , m_team_scratch_size {0,0}
+    , m_thread_scratch_size {0,0}
+    , m_chunk_size ( 32 )
+    {
+      // Allow only power-of-two vector_length
+      if ( ! Kokkos::Impl::is_integral_power_of_two( vector_length_request ) ) {
+        Impl::throw_runtime_exception( "Requested non-power-of-two vector length for TeamPolicy.");
+      }
+
+      // Make sure league size is permissable
+      if(league_size_ >= int(Impl::cuda_internal_maximum_grid_count()))
+        Impl::throw_runtime_exception( "Requested too large league_size for TeamPolicy on Cuda execution space.");
+
+      // Make sure total block size is permissable
+      if ( m_team_size * m_vector_length > 1024 ) {
+        Impl::throw_runtime_exception(std::string("Kokkos::TeamPolicy< Cuda > the team size is too large. Team size x vector length must be smaller than 1024."));
+      }
+    }
+
+  /** \brief  Specify league size, request team size */
+  TeamPolicyInternal( execution_space &
+            , int league_size_
+            , const Kokkos::AUTO_t & /* team_size_request */
+            , int vector_length_request = 1 )
+    : m_league_size( league_size_ )
+    , m_team_size( -1 )
+    , m_vector_length( vector_length_request )
+    , m_team_scratch_size {0,0}
+    , m_thread_scratch_size {0,0}
+    , m_chunk_size ( 32 )
+    {
+      // Allow only power-of-two vector_length
+      if ( ! Kokkos::Impl::is_integral_power_of_two( vector_length_request ) ) {
+        Impl::throw_runtime_exception( "Requested non-power-of-two vector length for TeamPolicy.");
+      }
+
+      // Make sure league size is permissable
+      if(league_size_ >= int(Impl::cuda_internal_maximum_grid_count()))
+        Impl::throw_runtime_exception( "Requested too large league_size for TeamPolicy on Cuda execution space.");
+    }
+
+  TeamPolicyInternal( int league_size_
+            , int team_size_request
+            , int vector_length_request = 1 )
+    : m_league_size( league_size_ )
+    , m_team_size( team_size_request )
+    , m_vector_length ( vector_length_request )
+    , m_team_scratch_size {0,0}
+    , m_thread_scratch_size {0,0}
+    , m_chunk_size ( 32 )
+    {
+      // Allow only power-of-two vector_length
+      if ( ! Kokkos::Impl::is_integral_power_of_two( vector_length_request ) ) {
+        Impl::throw_runtime_exception( "Requested non-power-of-two vector length for TeamPolicy.");
+      }
+
+      // Make sure league size is permissable
+      if(league_size_ >= int(Impl::cuda_internal_maximum_grid_count()))
+        Impl::throw_runtime_exception( "Requested too large league_size for TeamPolicy on Cuda execution space.");
+
+      // Make sure total block size is permissable
+      if ( m_team_size * m_vector_length > 1024 ) {
+        Impl::throw_runtime_exception(std::string("Kokkos::TeamPolicy< Cuda > the team size is too large. Team size x vector length must be smaller than 1024."));
+      }
+    }
+
+  TeamPolicyInternal( int league_size_
+            , const Kokkos::AUTO_t & /* team_size_request */
+            , int vector_length_request = 1 )
+    : m_league_size( league_size_ )
+    , m_team_size( -1 )
+    , m_vector_length ( vector_length_request )
+    , m_team_scratch_size {0,0}
+    , m_thread_scratch_size {0,0}
+    , m_chunk_size ( 32 )
+    {
+      // Allow only power-of-two vector_length
+      if ( ! Kokkos::Impl::is_integral_power_of_two( vector_length_request ) ) {
+        Impl::throw_runtime_exception( "Requested non-power-of-two vector length for TeamPolicy.");
+      }
+
+      // Make sure league size is permissable
+      if(league_size_ >= int(Impl::cuda_internal_maximum_grid_count()))
+        Impl::throw_runtime_exception( "Requested too large league_size for TeamPolicy on Cuda execution space.");
+    }
+
+  inline int chunk_size() const { return m_chunk_size ; }
+
+  /** \brief set chunk_size to a discrete value*/
+  inline TeamPolicyInternal set_chunk_size(typename traits::index_type chunk_size_) const {
+    TeamPolicyInternal p = *this;
+    p.m_chunk_size = chunk_size_;
+    return p;
+  }
+
+  /** \brief set per team scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerTeamValue& per_team) const {
+    TeamPolicyInternal p = *this;
+    p.m_team_scratch_size[level] = per_team.value;
+    return p;
+  };
+
+  /** \brief set per thread scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerThreadValue& per_thread) const {
+    TeamPolicyInternal p = *this;
+    p.m_thread_scratch_size[level] = per_thread.value;
+    return p;
+  };
+
+  /** \brief set per thread and per team scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerTeamValue& per_team, const PerThreadValue& per_thread) const {
+    TeamPolicyInternal p = *this;
+    p.m_team_scratch_size[level] = per_team.value;
+    p.m_thread_scratch_size[level] = per_thread.value;
+    return p;
+  };
+
+  typedef Kokkos::Impl::CudaTeamMember member_type ;
+};
+} // namspace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ... Traits >
+class ParallelFor< FunctorType
+                 , Kokkos::RangePolicy< Traits ... >
+                 , Kokkos::Cuda
+                 >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy;
+  typedef typename Policy::member_type  Member ;
+  typedef typename Policy::work_tag     WorkTag ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;  
+
+  ParallelFor() = delete ;
+  ParallelFor & operator = ( const ParallelFor & ) = delete ;
+
+  template< class TagType >
+  inline __device__
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const Member i ) const
+    { m_functor( i ); }
+
+  template< class TagType >
+  inline __device__
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const Member i ) const
+    { m_functor( TagType() , i ); }
+
+public:
+
+  typedef FunctorType functor_type ;
+
+  inline
+  __device__
+  void operator()(void) const
+    {
+      const Member work_stride = blockDim.y * gridDim.x ;
+      const Member work_end    = m_policy.end();
+
+      for ( Member
+              iwork =  m_policy.begin() + threadIdx.y + blockDim.y * blockIdx.x ;
+              iwork <  work_end ;
+              iwork += work_stride ) {
+        this-> template exec_range< WorkTag >( iwork );
+      }
+    }
+
+  inline
+  void execute() const
+    {
+      const int nwork = m_policy.end() - m_policy.begin();
+      const dim3 block(  1 , CudaTraits::WarpSize * cuda_internal_maximum_warp_count(), 1);
+      const dim3 grid( std::min( ( nwork + block.y - 1 ) / block.y , cuda_internal_maximum_grid_count() ) , 1 , 1);
+
+      CudaParallelLaunch< ParallelFor >( *this , grid , block , 0 );
+    }
+
+  ParallelFor( const FunctorType  & arg_functor ,
+               const Policy       & arg_policy )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    { }
+};
+
+template< class FunctorType , class ... Properties >
+class ParallelFor< FunctorType
+                 , Kokkos::TeamPolicy< Properties ... >
+                 , Kokkos::Cuda
+                 >
+{
+private:
+
+  typedef TeamPolicyInternal< Kokkos::Cuda , Properties ... >   Policy ;
+  typedef typename Policy::member_type  Member ;
+  typedef typename Policy::work_tag     WorkTag ;
+
+public:
+
+  typedef FunctorType      functor_type ;
+  typedef Cuda::size_type  size_type ;
+
+private:
+
+  // Algorithmic constraints: blockDim.y is a power of two AND blockDim.y == blockDim.z == 1
+  // shared memory utilization:
+  //
+  //  [ team   reduce space ]
+  //  [ team   shared space ]
+  //
+
+  const FunctorType m_functor ;
+  const size_type   m_league_size ;
+  const size_type   m_team_size ;
+  const size_type   m_vector_size ;
+  const size_type   m_shmem_begin ;
+  const size_type   m_shmem_size ;
+  void*             m_scratch_ptr[2] ;
+  const int         m_scratch_size[2] ;
+
+  template< class TagType >
+  __device__ inline
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_team( const Member & member ) const
+    { m_functor( member ); }
+
+  template< class TagType >
+  __device__ inline
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_team( const Member & member ) const
+    { m_functor( TagType() , member ); }
+
+public:
+
+  __device__ inline
+  void operator()(void) const
+  {
+    // Iterate this block through the league
+    for ( int league_rank = blockIdx.x ; league_rank < m_league_size ; league_rank += gridDim.x ) {
+
+      this-> template exec_team< WorkTag >(
+        typename Policy::member_type( kokkos_impl_cuda_shared_memory<void>()
+                                    , m_shmem_begin
+                                    , m_shmem_size
+                                    , m_scratch_ptr[1]
+                                    , m_scratch_size[1]
+                                    , league_rank
+                                    , m_league_size ) );
+    }
+  }
+
+  inline
+  void execute() const
+    {
+      const int shmem_size_total = m_shmem_begin + m_shmem_size ;
+      const dim3 grid( int(m_league_size) , 1 , 1 );
+      const dim3 block( int(m_vector_size) , int(m_team_size) , 1 );
+
+      CudaParallelLaunch< ParallelFor >( *this, grid, block, shmem_size_total ); // copy to device and execute
+
+    }
+
+  ParallelFor( const FunctorType  & arg_functor 
+             , const Policy       & arg_policy 
+             )
+    : m_functor( arg_functor )
+    , m_league_size( arg_policy.league_size() )
+    , m_team_size( 0 <= arg_policy.team_size() ? arg_policy.team_size() :
+        Kokkos::Impl::cuda_get_opt_block_size< ParallelFor >( arg_functor , arg_policy.vector_length(), arg_policy.team_scratch_size(0),arg_policy.thread_scratch_size(0) ) / arg_policy.vector_length() )
+    , m_vector_size( arg_policy.vector_length() )
+    , m_shmem_begin( sizeof(double) * ( m_team_size + 2 ) )
+    , m_shmem_size( arg_policy.scratch_size(0,m_team_size) + FunctorTeamShmemSize< FunctorType >::value( m_functor , m_team_size ) )
+    , m_scratch_ptr{NULL,NULL}
+    , m_scratch_size{arg_policy.scratch_size(0,m_team_size),arg_policy.scratch_size(1,m_team_size)}
+    {
+      // Functor's reduce memory, team scan memory, and team shared memory depend upon team size.
+      m_scratch_ptr[1] = cuda_resize_scratch_space(m_scratch_size[1]*(Cuda::concurrency()/(m_team_size*m_vector_size)));
+
+      const int shmem_size_total = m_shmem_begin + m_shmem_size ;
+      if ( CudaTraits::SharedMemoryCapacity < shmem_size_total ) {
+        Kokkos::Impl::throw_runtime_exception(std::string("Kokkos::Impl::ParallelFor< Cuda > insufficient shared memory"));
+      }
+
+      if ( int(m_team_size) >
+           int(Kokkos::Impl::cuda_get_max_block_size< ParallelFor >
+                 ( arg_functor , arg_policy.vector_length(), arg_policy.team_scratch_size(0),arg_policy.thread_scratch_size(0) ) / arg_policy.vector_length())) {
+        Kokkos::Impl::throw_runtime_exception(std::string("Kokkos::Impl::ParallelFor< Cuda > requested too large team size."));
+      }
+    }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ReducerType, class ... Traits >
+class ParallelReduce< FunctorType
+                    , Kokkos::RangePolicy< Traits ... >
+                    , ReducerType
+                    , Kokkos::Cuda 
+                    >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... >         Policy ;
+
+  typedef typename Policy::WorkRange    WorkRange ;
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::member_type  Member ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd, WorkTag > ValueInit ;
+  typedef Kokkos::Impl::FunctorValueJoin<   ReducerTypeFwd, WorkTag > ValueJoin ;
+
+public:
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::value_type      value_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+  typedef FunctorType                           functor_type ;
+  typedef Cuda::size_type                       size_type ;
+
+  // Algorithmic constraints: blockSize is a power of two AND blockDim.y == blockDim.z == 1
+
+  const FunctorType   m_functor ;
+  const Policy        m_policy ;
+  const ReducerType   m_reducer ;
+  const pointer_type  m_result_ptr ;
+  size_type *         m_scratch_space ;
+  size_type *         m_scratch_flags ;
+  size_type *         m_unified_space ;
+
+  // Shall we use the shfl based reduction or not (only use it for static sized types of more than 128bit
+  enum { UseShflReduction = ((sizeof(value_type)>2*sizeof(double)) && ValueTraits::StaticValueSize) };
+  // Some crutch to do function overloading
+private:
+  typedef double DummyShflReductionType;
+  typedef int DummySHMEMReductionType;
+
+public:
+  template< class TagType >
+  __device__ inline
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const Member & i , reference_type update ) const
+    { m_functor( i , update ); }
+
+  template< class TagType >
+  __device__ inline
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const Member & i , reference_type update ) const
+    { m_functor( TagType() , i , update ); }
+
+  __device__ inline
+  void operator() () const {
+    run(Kokkos::Impl::if_c<UseShflReduction, DummyShflReductionType, DummySHMEMReductionType>::select(1,1.0) );
+  }
+
+  __device__ inline
+  void run(const DummySHMEMReductionType& ) const
+  {
+    const integral_nonzero_constant< size_type , ValueTraits::StaticValueSize / sizeof(size_type) >
+      word_count( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) / sizeof(size_type) );
+
+    {
+      reference_type value =
+        ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , kokkos_impl_cuda_shared_memory<size_type>() + threadIdx.y * word_count.value );
+
+      // Number of blocks is bounded so that the reduction can be limited to two passes.
+      // Each thread block is given an approximately equal amount of work to perform.
+      // Accumulate the values for this block.
+      // The accumulation ordering does not match the final pass, but is arithmatically equivalent.
+
+      const WorkRange range( m_policy , blockIdx.x , gridDim.x );
+
+      for ( Member iwork = range.begin() + threadIdx.y , iwork_end = range.end() ;
+            iwork < iwork_end ; iwork += blockDim.y ) {
+        this-> template exec_range< WorkTag >( iwork , value );
+      }
+    }
+
+    // Reduce with final value at blockDim.y - 1 location.
+    if ( cuda_single_inter_block_reduce_scan<false,ReducerTypeFwd,WorkTag>(
+           ReducerConditional::select(m_functor , m_reducer) , blockIdx.x , gridDim.x ,
+           kokkos_impl_cuda_shared_memory<size_type>() , m_scratch_space , m_scratch_flags ) ) {
+
+      // This is the final block with the final result at the final threads' location
+
+      size_type * const shared = kokkos_impl_cuda_shared_memory<size_type>() + ( blockDim.y - 1 ) * word_count.value ;
+      size_type * const global = m_unified_space ? m_unified_space : m_scratch_space ;
+
+      if ( threadIdx.y == 0 ) {
+        Kokkos::Impl::FunctorFinal< ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer) , shared );
+      }
+
+      if ( CudaTraits::WarpSize < word_count.value ) { __syncthreads(); }
+
+      for ( unsigned i = threadIdx.y ; i < word_count.value ; i += blockDim.y ) { global[i] = shared[i]; }
+    }
+  }
+
+  __device__ inline
+   void run(const DummyShflReductionType&) const
+   {
+
+     value_type value;
+     ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , &value);
+     // Number of blocks is bounded so that the reduction can be limited to two passes.
+     // Each thread block is given an approximately equal amount of work to perform.
+     // Accumulate the values for this block.
+     // The accumulation ordering does not match the final pass, but is arithmatically equivalent.
+
+     const WorkRange range( m_policy , blockIdx.x , gridDim.x );
+
+     for ( Member iwork = range.begin() + threadIdx.y , iwork_end = range.end() ;
+           iwork < iwork_end ; iwork += blockDim.y ) {
+       this-> template exec_range< WorkTag >( iwork , value );
+     }
+
+     pointer_type const result = (pointer_type) (m_unified_space ? m_unified_space : m_scratch_space) ;
+
+     int max_active_thread = range.end()-range.begin() < blockDim.y ? range.end() - range.begin():blockDim.y;
+
+     max_active_thread = (max_active_thread == 0)?blockDim.y:max_active_thread;
+
+    value_type init;
+    ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , &init);
+     if(Impl::cuda_inter_block_reduction<ReducerTypeFwd,ValueJoin,WorkTag>
+            (value,init,ValueJoin(ReducerConditional::select(m_functor , m_reducer)),m_scratch_space,result,m_scratch_flags,max_active_thread)) {
+       const unsigned id = threadIdx.y*blockDim.x + threadIdx.x;
+       if(id==0) {
+         Kokkos::Impl::FunctorFinal< ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer) , (void*) &value );
+         *result = value;
+       }
+     }
+   }
+
+  // Determine block size constrained by shared memory:
+  static inline
+  unsigned local_block_size( const FunctorType & f )
+    {
+      unsigned n = CudaTraits::WarpSize * 8 ;
+      while ( n && CudaTraits::SharedMemoryCapacity < cuda_single_inter_block_reduce_scan_shmem<false,FunctorType,WorkTag>( f , n ) ) { n >>= 1 ; }
+      return n ;
+    }
+
+  inline
+  void execute()
+    {
+      const int nwork = m_policy.end() - m_policy.begin();
+      if ( nwork ) {
+        const int block_size = local_block_size( m_functor );
+  
+        m_scratch_space = cuda_internal_scratch_space( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) * block_size /* block_size == max block_count */ );
+        m_scratch_flags = cuda_internal_scratch_flags( sizeof(size_type) );
+        m_unified_space = cuda_internal_scratch_unified( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) );
+  
+        // REQUIRED ( 1 , N , 1 )
+        const dim3 block( 1 , block_size , 1 );
+        // Required grid.x <= block.y
+        const dim3 grid( std::min( int(block.y) , int( ( nwork + block.y - 1 ) / block.y ) ) , 1 , 1 );
+  
+      const int shmem = UseShflReduction?0:cuda_single_inter_block_reduce_scan_shmem<false,FunctorType,WorkTag>( m_functor , block.y );
+
+  
+      CudaParallelLaunch< ParallelReduce >( *this, grid, block, shmem ); // copy to device and execute
+  
+      Cuda::fence();
+  
+      if ( m_result_ptr ) {
+        if ( m_unified_space ) {
+          const int count = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer)  );
+          for ( int i = 0 ; i < count ; ++i ) { m_result_ptr[i] = pointer_type(m_unified_space)[i] ; }
+        }
+        else {
+          const int size = ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer)  );
+          DeepCopy<HostSpace,CudaSpace>( m_result_ptr , m_scratch_space , size );
+        }
+      }
+    }
+    else {
+      if (m_result_ptr) {
+        ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , m_result_ptr );
+      }
+    }
+  }
+
+  template< class HostViewType >
+  ParallelReduce( const FunctorType  & arg_functor 
+                , const Policy       & arg_policy 
+                , const HostViewType & arg_result
+                , typename std::enable_if<
+                   Kokkos::is_view< HostViewType >::value
+                ,void*>::type = NULL)
+  : m_functor( arg_functor )
+  , m_policy(  arg_policy )
+  , m_reducer( InvalidType() )
+  , m_result_ptr( arg_result.ptr_on_device() )
+  , m_scratch_space( 0 )
+  , m_scratch_flags( 0 )
+  , m_unified_space( 0 )
+  { }
+
+  ParallelReduce( const FunctorType  & arg_functor
+                , const Policy       & arg_policy
+                , const ReducerType & reducer)
+  : m_functor( arg_functor )
+  , m_policy(  arg_policy )
+  , m_reducer( reducer )
+  , m_result_ptr( reducer.result_view().ptr_on_device() )
+  , m_scratch_space( 0 )
+  , m_scratch_flags( 0 )
+  , m_unified_space( 0 )
+  { }
+};
+
+//----------------------------------------------------------------------------
+
+template< class FunctorType , class ReducerType, class ... Properties >
+class ParallelReduce< FunctorType
+                    , Kokkos::TeamPolicy< Properties ... >
+                    , ReducerType
+                    , Kokkos::Cuda
+                    >
+{
+private:
+
+  typedef TeamPolicyInternal< Kokkos::Cuda, Properties ... >  Policy ;
+  typedef typename Policy::member_type  Member ;
+  typedef typename Policy::work_tag     WorkTag ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd, WorkTag > ValueInit ;
+  typedef Kokkos::Impl::FunctorValueJoin<   ReducerTypeFwd, WorkTag > ValueJoin ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+  typedef typename ValueTraits::value_type      value_type ;
+
+
+public:
+
+  typedef FunctorType      functor_type ;
+  typedef Cuda::size_type  size_type ;
+
+  enum { UseShflReduction = (true && ValueTraits::StaticValueSize) };
+
+private:
+  typedef double DummyShflReductionType;
+  typedef int DummySHMEMReductionType;
+
+
+  // Algorithmic constraints: blockDim.y is a power of two AND blockDim.y == blockDim.z == 1
+  // shared memory utilization:
+  //
+  //  [ global reduce space ]
+  //  [ team   reduce space ]
+  //  [ team   shared space ]
+  //
+
+  const FunctorType   m_functor ;
+  const ReducerType   m_reducer ;
+  const pointer_type  m_result_ptr ;
+  size_type *         m_scratch_space ;
+  size_type *         m_scratch_flags ;
+  size_type *         m_unified_space ;
+  size_type           m_team_begin ;
+  size_type           m_shmem_begin ;
+  size_type           m_shmem_size ;
+  void*               m_scratch_ptr[2] ;
+  int                 m_scratch_size[2] ;
+  const size_type     m_league_size ;
+  const size_type     m_team_size ;
+  const size_type     m_vector_size ;
+
+  template< class TagType >
+  __device__ inline
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_team( const Member & member , reference_type update ) const
+    { m_functor( member , update ); }
+
+  template< class TagType >
+  __device__ inline
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_team( const Member & member , reference_type update ) const
+    { m_functor( TagType() , member , update ); }
+
+public:
+
+  __device__ inline
+  void operator() () const {
+    run(Kokkos::Impl::if_c<UseShflReduction, DummyShflReductionType, DummySHMEMReductionType>::select(1,1.0) );
+  }
+
+  __device__ inline
+  void run(const DummySHMEMReductionType&) const
+  {
+    const integral_nonzero_constant< size_type , ValueTraits::StaticValueSize / sizeof(size_type) >
+      word_count( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) / sizeof(size_type) );
+
+    reference_type value =
+      ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , kokkos_impl_cuda_shared_memory<size_type>() + threadIdx.y * word_count.value );
+
+    // Iterate this block through the league
+    for ( int league_rank = blockIdx.x ; league_rank < m_league_size ; league_rank += gridDim.x ) {
+      this-> template exec_team< WorkTag >
+        ( Member( kokkos_impl_cuda_shared_memory<char>() + m_team_begin
+                                        , m_shmem_begin
+                                        , m_shmem_size
+                                        , m_scratch_ptr[1]
+                                        , m_scratch_size[1]
+                                        , league_rank
+                                        , m_league_size )
+        , value );
+    }
+
+    // Reduce with final value at blockDim.y - 1 location.
+    if ( cuda_single_inter_block_reduce_scan<false,FunctorType,WorkTag>(
+           ReducerConditional::select(m_functor , m_reducer) , blockIdx.x , gridDim.x ,
+           kokkos_impl_cuda_shared_memory<size_type>() , m_scratch_space , m_scratch_flags ) ) {
+
+      // This is the final block with the final result at the final threads' location
+
+      size_type * const shared = kokkos_impl_cuda_shared_memory<size_type>() + ( blockDim.y - 1 ) * word_count.value ;
+      size_type * const global = m_unified_space ? m_unified_space : m_scratch_space ;
+
+      if ( threadIdx.y == 0 ) {
+        Kokkos::Impl::FunctorFinal< ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer) , shared );
+      }
+
+      if ( CudaTraits::WarpSize < word_count.value ) { __syncthreads(); }
+
+      for ( unsigned i = threadIdx.y ; i < word_count.value ; i += blockDim.y ) { global[i] = shared[i]; }
+    }
+  }
+
+  __device__ inline
+  void run(const DummyShflReductionType&) const
+  {
+    value_type value;
+    ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , &value);
+
+    // Iterate this block through the league
+    for ( int league_rank = blockIdx.x ; league_rank < m_league_size ; league_rank += gridDim.x ) {
+      this-> template exec_team< WorkTag >
+        ( Member( kokkos_impl_cuda_shared_memory<char>() + m_team_begin
+                                        , m_shmem_begin
+                                        , m_shmem_size
+                                        , m_scratch_ptr[1]
+                                        , m_scratch_size[1]
+                                        , league_rank
+                                        , m_league_size )
+        , value );
+    }
+
+    pointer_type const result = (pointer_type) (m_unified_space ? m_unified_space : m_scratch_space) ;
+
+    value_type init;
+    ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , &init);
+    if(Impl::cuda_inter_block_reduction<FunctorType,ValueJoin,WorkTag>
+           (value,init,ValueJoin(ReducerConditional::select(m_functor , m_reducer)),m_scratch_space,result,m_scratch_flags,blockDim.y)) {
+      const unsigned id = threadIdx.y*blockDim.x + threadIdx.x;
+      if(id==0) {
+        Kokkos::Impl::FunctorFinal< ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer) , (void*) &value );
+        *result = value;
+      }
+    }
+  }
+
+  inline
+  void execute()
+    {
+      const int block_count = UseShflReduction? std::min( m_league_size , size_type(1024) )
+                                               :std::min( m_league_size , m_team_size );
+
+      m_scratch_space = cuda_internal_scratch_space( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) * block_count );
+      m_scratch_flags = cuda_internal_scratch_flags( sizeof(size_type) );
+      m_unified_space = cuda_internal_scratch_unified( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) );
+
+      const dim3 block( m_vector_size , m_team_size , 1 );
+      const dim3 grid( block_count , 1 , 1 );
+      const int shmem_size_total = m_team_begin + m_shmem_begin + m_shmem_size ;
+
+      CudaParallelLaunch< ParallelReduce >( *this, grid, block, shmem_size_total ); // copy to device and execute
+
+      Cuda::fence();
+
+      if ( m_result_ptr ) {
+        if ( m_unified_space ) {
+          const int count = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer) );
+          for ( int i = 0 ; i < count ; ++i ) { m_result_ptr[i] = pointer_type(m_unified_space)[i] ; }
+        }
+        else {
+          const int size = ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) );
+          DeepCopy<HostSpace,CudaSpace>( m_result_ptr, m_scratch_space, size );
+        }
+      }
+    }
+
+  template< class HostViewType >
+  ParallelReduce( const FunctorType  & arg_functor 
+                , const Policy       & arg_policy 
+                , const HostViewType & arg_result
+                , typename std::enable_if<
+                                   Kokkos::is_view< HostViewType >::value
+                                ,void*>::type = NULL)
+  : m_functor( arg_functor )
+  , m_reducer( InvalidType() )
+  , m_result_ptr( arg_result.ptr_on_device() )
+  , m_scratch_space( 0 )
+  , m_scratch_flags( 0 )
+  , m_unified_space( 0 )
+  , m_team_begin( 0 )
+  , m_shmem_begin( 0 )
+  , m_shmem_size( 0 )
+  , m_scratch_ptr{NULL,NULL}
+  , m_league_size( arg_policy.league_size() )
+  , m_team_size( 0 <= arg_policy.team_size() ? arg_policy.team_size() :
+      Kokkos::Impl::cuda_get_opt_block_size< ParallelReduce >( arg_functor , arg_policy.vector_length(),
+                                                               arg_policy.team_scratch_size(0),arg_policy.thread_scratch_size(0) ) /
+      arg_policy.vector_length() )
+  , m_vector_size( arg_policy.vector_length() )
+  , m_scratch_size{arg_policy.scratch_size(0,m_team_size),arg_policy.scratch_size(1,m_team_size)}
+  {
+    // Return Init value if the number of worksets is zero
+    if( arg_policy.league_size() == 0) {
+      ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , arg_result.ptr_on_device() );
+      return ;
+    }
+
+    m_team_begin = UseShflReduction?0:cuda_single_inter_block_reduce_scan_shmem<false,FunctorType,WorkTag>( arg_functor , m_team_size );
+    m_shmem_begin = sizeof(double) * ( m_team_size + 2 );
+    m_shmem_size = arg_policy.scratch_size(0,m_team_size) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , m_team_size );
+    m_scratch_ptr[1] = cuda_resize_scratch_space(m_scratch_size[1]*(Cuda::concurrency()/(m_team_size*m_vector_size)));
+    m_scratch_size[0] = m_shmem_size;
+    m_scratch_size[1] = arg_policy.scratch_size(1,m_team_size);
+
+    // The global parallel_reduce does not support vector_length other than 1 at the moment
+    if( (arg_policy.vector_length() > 1) && !UseShflReduction )
+      Impl::throw_runtime_exception( "Kokkos::parallel_reduce with a TeamPolicy using a vector length of greater than 1 is not currently supported for CUDA for dynamic sized reduction types.");
+
+    if( (m_team_size < 32) && !UseShflReduction )
+      Impl::throw_runtime_exception( "Kokkos::parallel_reduce with a TeamPolicy using a team_size smaller than 32 is not currently supported with CUDA for dynamic sized reduction types.");
+
+    // Functor's reduce memory, team scan memory, and team shared memory depend upon team size.
+
+    const int shmem_size_total = m_team_begin + m_shmem_begin + m_shmem_size ;
+
+    if (! Kokkos::Impl::is_integral_power_of_two( m_team_size )  && !UseShflReduction ) {
+      Kokkos::Impl::throw_runtime_exception(std::string("Kokkos::Impl::ParallelReduce< Cuda > bad team size"));
+    }
+
+    if ( CudaTraits::SharedMemoryCapacity < shmem_size_total ) {
+      Kokkos::Impl::throw_runtime_exception(std::string("Kokkos::Impl::ParallelReduce< Cuda > requested too much L0 scratch memory"));
+    }
+
+    if ( m_team_size >
+         Kokkos::Impl::cuda_get_max_block_size< ParallelReduce >
+               ( arg_functor , arg_policy.vector_length(), arg_policy.team_scratch_size(0),arg_policy.thread_scratch_size(0) ) / arg_policy.vector_length()) {
+      Kokkos::Impl::throw_runtime_exception(std::string("Kokkos::Impl::ParallelReduce< Cuda > requested too large team size."));
+    }
+
+  }
+
+  ParallelReduce( const FunctorType  & arg_functor
+                , const Policy       & arg_policy
+                , const ReducerType & reducer)
+  : m_functor( arg_functor )
+  , m_reducer( reducer )
+  , m_result_ptr( reducer.result_view().ptr_on_device() )
+  , m_scratch_space( 0 )
+  , m_scratch_flags( 0 )
+  , m_unified_space( 0 )
+  , m_team_begin( 0 )
+  , m_shmem_begin( 0 )
+  , m_shmem_size( 0 )
+  , m_scratch_ptr{NULL,NULL}
+  , m_league_size( arg_policy.league_size() )
+  , m_team_size( 0 <= arg_policy.team_size() ? arg_policy.team_size() :
+      Kokkos::Impl::cuda_get_opt_block_size< ParallelReduce >( arg_functor , arg_policy.vector_length(),
+                                                               arg_policy.team_scratch_size(0),arg_policy.thread_scratch_size(0) ) /
+      arg_policy.vector_length() )
+  , m_vector_size( arg_policy.vector_length() )
+  {
+    // Return Init value if the number of worksets is zero
+    if( arg_policy.league_size() == 0) {
+      ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , m_result_ptr );
+      return ;
+    }
+
+    m_team_begin = UseShflReduction?0:cuda_single_inter_block_reduce_scan_shmem<false,FunctorType,WorkTag>( arg_functor , m_team_size );
+    m_shmem_begin = sizeof(double) * ( m_team_size + 2 );
+    m_shmem_size = arg_policy.scratch_size(0,m_team_size) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , m_team_size );
+    m_scratch_ptr[1] = cuda_resize_scratch_space(m_scratch_size[1]*(Cuda::concurrency()/(m_team_size*m_vector_size)));
+    m_scratch_size[0] = m_shmem_size;
+    m_scratch_size[1] = arg_policy.scratch_size(1,m_team_size);
+
+    // The global parallel_reduce does not support vector_length other than 1 at the moment
+    if( (arg_policy.vector_length() > 1) && !UseShflReduction )
+      Impl::throw_runtime_exception( "Kokkos::parallel_reduce with a TeamPolicy using a vector length of greater than 1 is not currently supported for CUDA for dynamic sized reduction types.");
+
+    if( (m_team_size < 32) && !UseShflReduction )
+      Impl::throw_runtime_exception( "Kokkos::parallel_reduce with a TeamPolicy using a team_size smaller than 32 is not currently supported with CUDA for dynamic sized reduction types.");
+
+    // Functor's reduce memory, team scan memory, and team shared memory depend upon team size.
+
+    const int shmem_size_total = m_team_begin + m_shmem_begin + m_shmem_size ;
+
+    if ( (! Kokkos::Impl::is_integral_power_of_two( m_team_size )  && !UseShflReduction ) ||
+         CudaTraits::SharedMemoryCapacity < shmem_size_total ) {
+      Kokkos::Impl::throw_runtime_exception(std::string("Kokkos::Impl::ParallelReduce< Cuda > bad team size"));
+    }
+
+    if ( int(m_team_size) >
+         int(Kokkos::Impl::cuda_get_max_block_size< ParallelReduce >
+               ( arg_functor , arg_policy.vector_length(), arg_policy.team_scratch_size(0),arg_policy.thread_scratch_size(0) ) / arg_policy.vector_length())) {
+      Kokkos::Impl::throw_runtime_exception(std::string("Kokkos::Impl::ParallelReduce< Cuda > requested too large team size."));
+    }
+
+  }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ... Traits >
+class ParallelScan< FunctorType
+                  , Kokkos::RangePolicy< Traits ... >
+                  , Kokkos::Cuda
+                  >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... >  Policy ;
+  typedef typename Policy::member_type  Member ;
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::WorkRange    WorkRange ;
+
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   FunctorType, WorkTag > ValueInit ;
+  typedef Kokkos::Impl::FunctorValueOps<    FunctorType, WorkTag > ValueOps ;
+
+public:
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+  typedef FunctorType                           functor_type ;
+  typedef Cuda::size_type                       size_type ;
+
+private:
+
+  // Algorithmic constraints:
+  //  (a) blockDim.y is a power of two
+  //  (b) blockDim.y == blockDim.z == 1
+  //  (c) gridDim.x  <= blockDim.y * blockDim.y
+  //  (d) gridDim.y  == gridDim.z == 1
+
+  const FunctorType m_functor ;
+  const Policy      m_policy ;
+  size_type *       m_scratch_space ;
+  size_type *       m_scratch_flags ;
+  size_type         m_final ;
+
+  template< class TagType >
+  __device__ inline
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const Member & i , reference_type update , const bool final_result ) const
+    { m_functor( i , update , final_result ); }
+
+  template< class TagType >
+  __device__ inline
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const Member & i , reference_type update , const bool final_result ) const
+    { m_functor( TagType() , i , update , final_result ); }
+
+  //----------------------------------------
+
+  __device__ inline
+  void initial(void) const
+  {
+    const integral_nonzero_constant< size_type , ValueTraits::StaticValueSize / sizeof(size_type) >
+      word_count( ValueTraits::value_size( m_functor ) / sizeof(size_type) );
+
+    size_type * const shared_value = kokkos_impl_cuda_shared_memory<size_type>() + word_count.value * threadIdx.y ;
+
+    ValueInit::init( m_functor , shared_value );
+
+    // Number of blocks is bounded so that the reduction can be limited to two passes.
+    // Each thread block is given an approximately equal amount of work to perform.
+    // Accumulate the values for this block.
+    // The accumulation ordering does not match the final pass, but is arithmatically equivalent.
+
+    const WorkRange range( m_policy , blockIdx.x , gridDim.x );
+
+    for ( Member iwork = range.begin() + threadIdx.y , iwork_end = range.end() ;
+          iwork < iwork_end ; iwork += blockDim.y ) {
+      this-> template exec_range< WorkTag >( iwork , ValueOps::reference( shared_value ) , false );
+    }
+
+    // Reduce and scan, writing out scan of blocks' totals and block-groups' totals.
+    // Blocks' scan values are written to 'blockIdx.x' location.
+    // Block-groups' scan values are at: i = ( j * blockDim.y - 1 ) for i < gridDim.x
+    cuda_single_inter_block_reduce_scan<true,FunctorType,WorkTag>( m_functor , blockIdx.x , gridDim.x , kokkos_impl_cuda_shared_memory<size_type>() , m_scratch_space , m_scratch_flags );
+  }
+
+  //----------------------------------------
+
+  __device__ inline
+  void final(void) const
+  {
+    const integral_nonzero_constant< size_type , ValueTraits::StaticValueSize / sizeof(size_type) >
+      word_count( ValueTraits::value_size( m_functor ) / sizeof(size_type) );
+
+    // Use shared memory as an exclusive scan: { 0 , value[0] , value[1] , value[2] , ... }
+    size_type * const shared_data   = kokkos_impl_cuda_shared_memory<size_type>();
+    size_type * const shared_prefix = shared_data + word_count.value * threadIdx.y ;
+    size_type * const shared_accum  = shared_data + word_count.value * ( blockDim.y + 1 );
+
+    // Starting value for this thread block is the previous block's total.
+    if ( blockIdx.x ) {
+      size_type * const block_total = m_scratch_space + word_count.value * ( blockIdx.x - 1 );
+      for ( unsigned i = threadIdx.y ; i < word_count.value ; ++i ) { shared_accum[i] = block_total[i] ; }
+    }
+    else if ( 0 == threadIdx.y ) {
+      ValueInit::init( m_functor , shared_accum );
+    }
+
+    const WorkRange range( m_policy , blockIdx.x , gridDim.x );
+
+    for ( typename Policy::member_type iwork_base = range.begin(); iwork_base < range.end() ; iwork_base += blockDim.y ) {
+
+      const typename Policy::member_type iwork = iwork_base + threadIdx.y ;
+
+      __syncthreads(); // Don't overwrite previous iteration values until they are used
+
+      ValueInit::init( m_functor , shared_prefix + word_count.value );
+
+      // Copy previous block's accumulation total into thread[0] prefix and inclusive scan value of this block
+      for ( unsigned i = threadIdx.y ; i < word_count.value ; ++i ) {
+        shared_data[i + word_count.value] = shared_data[i] = shared_accum[i] ;
+      }
+
+      if ( CudaTraits::WarpSize < word_count.value ) { __syncthreads(); } // Protect against large scan values.
+
+      // Call functor to accumulate inclusive scan value for this work item
+      if ( iwork < range.end() ) {
+        this-> template exec_range< WorkTag >( iwork , ValueOps::reference( shared_prefix + word_count.value ) , false );
+      }
+
+      // Scan block values into locations shared_data[1..blockDim.y]
+      cuda_intra_block_reduce_scan<true,FunctorType,WorkTag>( m_functor , ValueTraits::pointer_type(shared_data+word_count.value) );
+
+      {
+        size_type * const block_total = shared_data + word_count.value * blockDim.y ;
+        for ( unsigned i = threadIdx.y ; i < word_count.value ; ++i ) { shared_accum[i] = block_total[i]; }
+      }
+
+      // Call functor with exclusive scan value
+      if ( iwork < range.end() ) {
+        this-> template exec_range< WorkTag >( iwork , ValueOps::reference( shared_prefix ) , true );
+      }
+    }
+  }
+
+public:
+
+  //----------------------------------------
+
+  __device__ inline
+  void operator()(void) const
+  {
+    if ( ! m_final ) {
+      initial();
+    }
+    else {
+      final();
+    }
+  }
+
+  // Determine block size constrained by shared memory:
+  static inline
+  unsigned local_block_size( const FunctorType & f )
+    {
+      // blockDim.y must be power of two = 128 (4 warps) or 256 (8 warps) or 512 (16 warps)
+      // gridDim.x <= blockDim.y * blockDim.y
+      //
+      // 4 warps was 10% faster than 8 warps and 20% faster than 16 warps in unit testing
+
+      unsigned n = CudaTraits::WarpSize * 4 ;
+      while ( n && CudaTraits::SharedMemoryCapacity < cuda_single_inter_block_reduce_scan_shmem<false,FunctorType,WorkTag>( f , n ) ) { n >>= 1 ; }
+      return n ;
+    }
+
+  inline
+  void execute()
+    {
+      const int nwork    = m_policy.end() - m_policy.begin();
+      if ( nwork ) {
+        enum { GridMaxComputeCapability_2x = 0x0ffff };
+  
+        const int block_size = local_block_size( m_functor );
+  
+        const int grid_max =
+          ( block_size * block_size ) < GridMaxComputeCapability_2x ?
+          ( block_size * block_size ) : GridMaxComputeCapability_2x ;
+  
+        // At most 'max_grid' blocks:
+        const int max_grid = std::min( int(grid_max) , int(( nwork + block_size - 1 ) / block_size ));
+  
+        // How much work per block:
+        const int work_per_block = ( nwork + max_grid - 1 ) / max_grid ;
+  
+        // How many block are really needed for this much work:
+        const int grid_x = ( nwork + work_per_block - 1 ) / work_per_block ;
+  
+        m_scratch_space = cuda_internal_scratch_space( ValueTraits::value_size( m_functor ) * grid_x );
+        m_scratch_flags = cuda_internal_scratch_flags( sizeof(size_type) * 1 );
+  
+        const dim3 grid( grid_x , 1 , 1 );
+        const dim3 block( 1 , block_size , 1 ); // REQUIRED DIMENSIONS ( 1 , N , 1 )
+        const int shmem = ValueTraits::value_size( m_functor ) * ( block_size + 2 );
+  
+        m_final = false ;
+        CudaParallelLaunch< ParallelScan >( *this, grid, block, shmem ); // copy to device and execute
+  
+        m_final = true ;
+        CudaParallelLaunch< ParallelScan >( *this, grid, block, shmem ); // copy to device and execute
+      }
+    }
+
+  ParallelScan( const FunctorType  & arg_functor ,
+                const Policy       & arg_policy )
+  : m_functor( arg_functor )
+  , m_policy( arg_policy )
+  , m_scratch_space( 0 )
+  , m_scratch_flags( 0 )
+  , m_final( false )
+  { }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+  template<typename iType>
+  struct TeamThreadRangeBoundariesStruct<iType,CudaTeamMember> {
+    typedef iType index_type;
+    const iType start;
+    const iType end;
+    const iType increment;
+    const CudaTeamMember& thread;
+
+#ifdef __CUDA_ARCH__
+    __device__ inline
+    TeamThreadRangeBoundariesStruct (const CudaTeamMember& thread_, const iType& count):
+      start( threadIdx.y ),
+      end( count ),
+      increment( blockDim.y ),
+      thread(thread_)
+    {}
+    __device__ inline
+    TeamThreadRangeBoundariesStruct (const CudaTeamMember& thread_, const iType& begin_, const iType& end_):
+      start( begin_+threadIdx.y ),
+      end( end_ ),
+      increment( blockDim.y ),
+      thread(thread_)
+    {}
+#else
+    KOKKOS_INLINE_FUNCTION
+    TeamThreadRangeBoundariesStruct (const CudaTeamMember& thread_, const iType& count):
+      start( 0 ),
+      end( count ),
+      increment( 1 ),
+      thread(thread_)
+    {}
+    KOKKOS_INLINE_FUNCTION
+    TeamThreadRangeBoundariesStruct (const CudaTeamMember& thread_,  const iType& begin_, const iType& end_):
+      start( begin_ ),
+      end( end_ ),
+      increment( 1 ),
+      thread(thread_)
+    {}
+#endif
+  };
+
+  template<typename iType>
+  struct ThreadVectorRangeBoundariesStruct<iType,CudaTeamMember> {
+    typedef iType index_type;
+    const iType start;
+    const iType end;
+    const iType increment;
+
+#ifdef __CUDA_ARCH__
+    __device__ inline
+    ThreadVectorRangeBoundariesStruct (const CudaTeamMember& thread, const iType& count):
+    start( threadIdx.x ),
+    end( count ),
+    increment( blockDim.x )
+    {}
+#else
+    KOKKOS_INLINE_FUNCTION
+    ThreadVectorRangeBoundariesStruct (const CudaTeamMember& thread_, const iType& count):
+      start( 0 ),
+      end( count ),
+      increment( 1 )
+    {}
+#endif
+    };
+
+} // namespace Impl
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::CudaTeamMember>
+  TeamThreadRange(const Impl::CudaTeamMember& thread, const iType& count) {
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::CudaTeamMember>(thread,count);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::CudaTeamMember>
+  TeamThreadRange(const Impl::CudaTeamMember& thread, const iType& begin, const iType& end) {
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::CudaTeamMember>(thread,begin,end);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::CudaTeamMember >
+  ThreadVectorRange(const Impl::CudaTeamMember& thread, const iType& count) {
+  return Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::CudaTeamMember >(thread,count);
+}
+
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadSingleStruct<Impl::CudaTeamMember> PerTeam(const Impl::CudaTeamMember& thread) {
+  return Impl::ThreadSingleStruct<Impl::CudaTeamMember>(thread);
+}
+
+KOKKOS_INLINE_FUNCTION
+Impl::VectorSingleStruct<Impl::CudaTeamMember> PerThread(const Impl::CudaTeamMember& thread) {
+  return Impl::VectorSingleStruct<Impl::CudaTeamMember>(thread);
+}
+
+} // namespace Kokkos
+
+namespace Kokkos {
+
+  /** \brief  Inter-thread parallel_for. Executes lambda(iType i) for each i=0..N-1.
+   *
+   * The range i=0..N-1 is mapped to all threads of the the calling thread team.
+   * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::CudaTeamMember>& loop_boundaries, const Lambda& lambda) {
+  #ifdef __CUDA_ARCH__
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+  #endif
+}
+
+/** \brief  Inter-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all threads of the the calling thread team and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::CudaTeamMember>& loop_boundaries,
+                     const Lambda & lambda, ValueType& result) {
+
+#ifdef __CUDA_ARCH__
+  result = ValueType();
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,result);
+  }
+
+  Impl::cuda_intra_warp_reduction(result,[&] (ValueType& dst, const ValueType& src) { dst+=src; });
+  Impl::cuda_inter_warp_reduction(result,[&] (ValueType& dst, const ValueType& src) { dst+=src; });
+
+#endif
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::CudaTeamMember>& loop_boundaries,
+                     const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+#ifdef __CUDA_ARCH__
+  ValueType result = init_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,result);
+  }
+
+  Impl::cuda_intra_warp_reduction(result, join );
+  Impl::cuda_inter_warp_reduction(result, join );
+
+  init_result = result;
+#endif
+}
+
+} //namespace Kokkos
+
+namespace Kokkos {
+/** \brief  Intra-thread vector parallel_for. Executes lambda(iType i) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread.
+ * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::CudaTeamMember >&
+    loop_boundaries, const Lambda& lambda) {
+#ifdef __CUDA_ARCH__
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+#endif
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::CudaTeamMember >&
+      loop_boundaries, const Lambda & lambda, ValueType& result) {
+#ifdef __CUDA_ARCH__
+  result = ValueType();
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,result);
+  }
+
+  if (loop_boundaries.increment > 1)
+    result += shfl_down(result, 1,loop_boundaries.increment);
+  if (loop_boundaries.increment > 2)
+    result += shfl_down(result, 2,loop_boundaries.increment);
+  if (loop_boundaries.increment > 4)
+    result += shfl_down(result, 4,loop_boundaries.increment);
+  if (loop_boundaries.increment > 8)
+    result += shfl_down(result, 8,loop_boundaries.increment);
+  if (loop_boundaries.increment > 16)
+    result += shfl_down(result, 16,loop_boundaries.increment);
+
+  result = shfl(result,0,loop_boundaries.increment);
+#endif
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::CudaTeamMember >&
+      loop_boundaries, const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+#ifdef __CUDA_ARCH__
+  ValueType result = init_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,result);
+  }
+
+  if (loop_boundaries.increment > 1)
+    join( result, shfl_down(result, 1,loop_boundaries.increment));
+  if (loop_boundaries.increment > 2)
+    join( result, shfl_down(result, 2,loop_boundaries.increment));
+  if (loop_boundaries.increment > 4)
+    join( result, shfl_down(result, 4,loop_boundaries.increment));
+  if (loop_boundaries.increment > 8)
+    join( result, shfl_down(result, 8,loop_boundaries.increment));
+  if (loop_boundaries.increment > 16)
+    join( result, shfl_down(result, 16,loop_boundaries.increment));
+
+  init_result = shfl(result,0,loop_boundaries.increment);
+#endif
+}
+
+/** \brief  Intra-thread vector parallel exclusive prefix sum. Executes lambda(iType i, ValueType & val, bool final)
+ *          for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes in the thread and a scan operation is performed.
+ * Depending on the target execution space the operator might be called twice: once with final=false
+ * and once with final=true. When final==true val contains the prefix sum value. The contribution of this
+ * "i" needs to be added to val no matter whether final==true or not. In a serial execution
+ * (i.e. team_size==1) the operator is only called once with final==true. Scan_val will be set
+ * to the final sum value over all vector lanes.
+ * This functionality requires C++11 support.*/
+template< typename iType, class FunctorType >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::CudaTeamMember >&
+      loop_boundaries, const FunctorType & lambda) {
+
+#ifdef __CUDA_ARCH__
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
+  typedef typename ValueTraits::value_type value_type ;
+
+  value_type scan_val = value_type();
+  const int VectorLength = blockDim.x;
+
+  iType loop_bound = ((loop_boundaries.end+VectorLength-1)/VectorLength) * VectorLength;
+  for(int _i = threadIdx.x; _i < loop_bound; _i += VectorLength) {
+    value_type val = value_type();
+    if(_i<loop_boundaries.end)
+      lambda(_i , val , false);
+
+    value_type tmp = val;
+    value_type result_i;
+
+    if(threadIdx.x%VectorLength == 0)
+      result_i = tmp;
+    if (VectorLength > 1) {
+      const value_type tmp2 = shfl_up(tmp, 1,VectorLength);
+      if(threadIdx.x > 0)
+        tmp+=tmp2;
+    }
+    if(threadIdx.x%VectorLength == 1)
+      result_i = tmp;
+    if (VectorLength > 3) {
+      const value_type tmp2 = shfl_up(tmp, 2,VectorLength);
+      if(threadIdx.x > 1)
+        tmp+=tmp2;
+    }
+    if ((threadIdx.x%VectorLength >= 2) &&
+        (threadIdx.x%VectorLength < 4))
+      result_i = tmp;
+    if (VectorLength > 7) {
+      const value_type tmp2 = shfl_up(tmp, 4,VectorLength);
+      if(threadIdx.x > 3)
+        tmp+=tmp2;
+    }
+    if ((threadIdx.x%VectorLength >= 4) &&
+        (threadIdx.x%VectorLength < 8))
+      result_i = tmp;
+    if (VectorLength > 15) {
+      const value_type tmp2 = shfl_up(tmp, 8,VectorLength);
+      if(threadIdx.x > 7)
+        tmp+=tmp2;
+    }
+    if ((threadIdx.x%VectorLength >= 8) &&
+        (threadIdx.x%VectorLength < 16))
+      result_i = tmp;
+    if (VectorLength > 31) {
+      const value_type tmp2 = shfl_up(tmp, 16,VectorLength);
+      if(threadIdx.x > 15)
+        tmp+=tmp2;
+    }
+    if (threadIdx.x%VectorLength >= 16)
+      result_i = tmp;
+
+    val = scan_val + result_i - val;
+    scan_val += shfl(tmp,VectorLength-1,VectorLength);
+    if(_i<loop_boundaries.end)
+      lambda(_i , val , true);
+  }
+#endif
+}
+
+}
+
+namespace Kokkos {
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::CudaTeamMember>& , const FunctorType& lambda) {
+#ifdef __CUDA_ARCH__
+  if(threadIdx.x == 0) lambda();
+#endif
+}
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::CudaTeamMember>& , const FunctorType& lambda) {
+#ifdef __CUDA_ARCH__
+  if(threadIdx.x == 0 && threadIdx.y == 0) lambda();
+#endif
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::CudaTeamMember>& , const FunctorType& lambda, ValueType& val) {
+#ifdef __CUDA_ARCH__
+  if(threadIdx.x == 0) lambda(val);
+  val = shfl(val,0,blockDim.x);
+#endif
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::CudaTeamMember>& single_struct, const FunctorType& lambda, ValueType& val) {
+#ifdef __CUDA_ARCH__
+  if(threadIdx.x == 0 && threadIdx.y == 0) {
+    lambda(val);
+  }
+  single_struct.team_member.team_broadcast(val,0);
+#endif
+}
+
+}
+
+namespace Kokkos {
+
+namespace Impl {
+  template< class FunctorType, class ExecPolicy, class ValueType , class Tag = typename ExecPolicy::work_tag>
+  struct CudaFunctorAdapter {
+    const FunctorType f;
+    typedef ValueType value_type;
+    CudaFunctorAdapter(const FunctorType& f_):f(f_) {}
+
+    __device__ inline
+    void operator() (typename ExecPolicy::work_tag, const typename ExecPolicy::member_type& i, ValueType& val) const {
+      //Insert Static Assert with decltype on ValueType equals third argument type of FunctorType::operator()
+      f(typename ExecPolicy::work_tag(), i,val);
+    }
+  };
+
+  template< class FunctorType, class ExecPolicy, class ValueType >
+  struct CudaFunctorAdapter<FunctorType,ExecPolicy,ValueType,void> {
+    const FunctorType f;
+    typedef ValueType value_type;
+    CudaFunctorAdapter(const FunctorType& f_):f(f_) {}
+
+    __device__ inline
+    void operator() (const typename ExecPolicy::member_type& i, ValueType& val) const {
+      //Insert Static Assert with decltype on ValueType equals second argument type of FunctorType::operator()
+      f(i,val);
+    }
+    __device__ inline
+    void operator() (typename ExecPolicy::member_type& i, ValueType& val) const {
+      //Insert Static Assert with decltype on ValueType equals second argument type of FunctorType::operator()
+      f(i,val);
+    }
+
+  };
+
+  template< class FunctorType, class Enable = void>
+  struct ReduceFunctorHasInit {
+    enum {value = false};
+  };
+
+  template< class FunctorType>
+  struct ReduceFunctorHasInit<FunctorType, typename Impl::enable_if< 0 < sizeof( & FunctorType::init ) >::type > {
+    enum {value = true};
+  };
+
+  template< class FunctorType, class Enable = void>
+  struct ReduceFunctorHasJoin {
+    enum {value = false};
+  };
+
+  template< class FunctorType>
+  struct ReduceFunctorHasJoin<FunctorType, typename Impl::enable_if< 0 < sizeof( & FunctorType::join ) >::type > {
+    enum {value = true};
+  };
+
+  template< class FunctorType, class Enable = void>
+  struct ReduceFunctorHasFinal {
+    enum {value = false};
+  };
+
+  template< class FunctorType>
+  struct ReduceFunctorHasFinal<FunctorType, typename Impl::enable_if< 0 < sizeof( & FunctorType::final ) >::type > {
+    enum {value = true};
+  };
+
+  template< class FunctorType, class Enable = void>
+    struct ReduceFunctorHasShmemSize {
+      enum {value = false};
+    };
+
+    template< class FunctorType>
+    struct ReduceFunctorHasShmemSize<FunctorType, typename Impl::enable_if< 0 < sizeof( & FunctorType::team_shmem_size ) >::type > {
+      enum {value = true};
+    };
+
+  template< class FunctorType, bool Enable =
+      ( FunctorDeclaresValueType<FunctorType,void>::value) ||
+      ( ReduceFunctorHasInit<FunctorType>::value  ) ||
+      ( ReduceFunctorHasJoin<FunctorType>::value  ) ||
+      ( ReduceFunctorHasFinal<FunctorType>::value ) ||
+      ( ReduceFunctorHasShmemSize<FunctorType>::value )
+      >
+  struct IsNonTrivialReduceFunctor {
+    enum {value = false};
+  };
+
+  template< class FunctorType>
+  struct IsNonTrivialReduceFunctor<FunctorType, true> {
+    enum {value = true};
+  };
+
+  template<class FunctorType, class ResultType, class Tag, bool Enable = IsNonTrivialReduceFunctor<FunctorType>::value >
+  struct FunctorReferenceType {
+    typedef ResultType& reference_type;
+  };
+
+  template<class FunctorType, class ResultType, class Tag>
+  struct FunctorReferenceType<FunctorType, ResultType, Tag, true> {
+    typedef typename Kokkos::Impl::FunctorValueTraits< FunctorType ,Tag >::reference_type reference_type;
+  };
+
+  template< class FunctorTypeIn, class ExecPolicy, class ValueType>
+  struct ParallelReduceFunctorType<FunctorTypeIn,ExecPolicy,ValueType,Cuda> {
+
+    enum {FunctorHasValueType = IsNonTrivialReduceFunctor<FunctorTypeIn>::value };
+    typedef typename Kokkos::Impl::if_c<FunctorHasValueType, FunctorTypeIn, Impl::CudaFunctorAdapter<FunctorTypeIn,ExecPolicy,ValueType> >::type functor_type;
+    static functor_type functor(const FunctorTypeIn& functor_in) {
+      return Impl::if_c<FunctorHasValueType,FunctorTypeIn,functor_type>::select(functor_in,functor_type(functor_in));
+    }
+  };
+
+}
+
+} // namespace Kokkos
+#endif /* defined( __CUDACC__ ) */
+
+#endif /* #ifndef KOKKOS_CUDA_PARALLEL_HPP */
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_ReduceScan.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_ReduceScan.hpp
new file mode 100644
index 0000000000..1778f631c0
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_ReduceScan.hpp
@@ -0,0 +1,433 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDA_REDUCESCAN_HPP
+#define KOKKOS_CUDA_REDUCESCAN_HPP
+
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#if defined( __CUDACC__ ) && defined( KOKKOS_HAVE_CUDA )
+
+#include <utility>
+
+#include <Kokkos_Parallel.hpp>
+#include <impl/Kokkos_FunctorAdapter.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <Cuda/Kokkos_Cuda_Vectorization.hpp>
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+
+
+//Shfl based reductions
+/*
+ *  Algorithmic constraints:
+ *   (a) threads with same threadIdx.y have same value
+ *   (b) blockDim.x == power of two
+ *   (c) blockDim.z == 1
+ */
+
+template< class ValueType , class JoinOp>
+__device__
+inline void cuda_intra_warp_reduction( ValueType& result,
+                                       const JoinOp& join,
+                                       const int max_active_thread = blockDim.y) {
+
+  unsigned int shift = 1;
+
+  //Reduce over values from threads with different threadIdx.y
+  while(blockDim.x * shift < 32 ) {
+    const ValueType tmp = shfl_down(result, blockDim.x*shift,32u);
+    //Only join if upper thread is active (this allows non power of two for blockDim.y
+    if(threadIdx.y + shift < max_active_thread)
+      join(result , tmp);
+    shift*=2;
+  }
+
+  result = shfl(result,0,32);
+}
+
+template< class ValueType , class JoinOp>
+__device__
+inline void cuda_inter_warp_reduction( ValueType& value,
+                                       const JoinOp& join,
+                                       const int max_active_thread = blockDim.y) {
+
+  #define STEP_WIDTH 4
+  __shared__ char sh_result[sizeof(ValueType)*STEP_WIDTH];
+  ValueType* result = (ValueType*) & sh_result;
+  const unsigned step = 32 / blockDim.x;
+  unsigned shift = STEP_WIDTH;
+  const int id = threadIdx.y%step==0?threadIdx.y/step:65000;
+  if(id < STEP_WIDTH ) {
+    result[id] = value;
+  }
+  __syncthreads();
+  while (shift<=max_active_thread/step) {
+    if(shift<=id && shift+STEP_WIDTH>id && threadIdx.x==0) {
+      join(result[id%STEP_WIDTH],value);
+    }
+    __syncthreads();
+    shift+=STEP_WIDTH;
+  }
+
+
+  value = result[0];
+  for(int i = 1; (i*step<max_active_thread) && i<STEP_WIDTH; i++)
+    join(value,result[i]);
+}
+
+template< class ValueType , class JoinOp>
+__device__
+inline void cuda_intra_block_reduction( ValueType& value,
+                                        const JoinOp& join,
+                                        const int max_active_thread = blockDim.y) {
+  cuda_intra_warp_reduction(value,join,max_active_thread);
+  cuda_inter_warp_reduction(value,join,max_active_thread);
+}
+
+template< class FunctorType , class JoinOp , class ArgTag = void >
+__device__
+bool cuda_inter_block_reduction( typename FunctorValueTraits< FunctorType , ArgTag >::reference_type  value,
+                                 typename FunctorValueTraits< FunctorType , ArgTag >::reference_type  neutral,
+                                 const JoinOp& join,
+                                 Cuda::size_type * const m_scratch_space,
+                                 typename FunctorValueTraits< FunctorType , ArgTag >::pointer_type const result,
+                                 Cuda::size_type * const m_scratch_flags,
+                                 const int max_active_thread = blockDim.y) {
+  typedef typename FunctorValueTraits< FunctorType , ArgTag >::pointer_type pointer_type;
+  typedef typename FunctorValueTraits< FunctorType , ArgTag >::value_type value_type;
+
+  //Do the intra-block reduction with shfl operations and static shared memory
+  cuda_intra_block_reduction(value,join,max_active_thread);
+
+  const unsigned id = threadIdx.y*blockDim.x + threadIdx.x;
+
+  //One thread in the block writes block result to global scratch_memory
+  if(id == 0 ) {
+    pointer_type global = ((pointer_type) m_scratch_space) + blockIdx.x;
+    *global = value;
+  }
+
+  //One warp of last block performs inter block reduction through loading the block values from global scratch_memory
+  bool last_block = false;
+
+  __syncthreads();
+  if ( id < 32 ) {
+    Cuda::size_type count;
+
+    //Figure out whether this is the last block
+    if(id == 0)
+      count = Kokkos::atomic_fetch_add(m_scratch_flags,1);
+    count = Kokkos::shfl(count,0,32);
+
+    //Last block does the inter block reduction
+    if( count == gridDim.x - 1) {
+      //set flag back to zero
+      if(id == 0)
+        *m_scratch_flags = 0;
+      last_block = true;
+      value = neutral;
+
+      pointer_type const volatile global = (pointer_type) m_scratch_space ;
+
+      //Reduce all global values with splitting work over threads in one warp
+      const int step_size = blockDim.x*blockDim.y < 32 ? blockDim.x*blockDim.y : 32;
+      for(int i=id; i<gridDim.x; i+=step_size) {
+        value_type tmp = global[i];
+        join(value, tmp);
+      }
+
+      //Perform shfl reductions within the warp only join if contribution is valid (allows gridDim.x non power of two and <32)
+      if (blockDim.x*blockDim.y > 1) {
+        value_type tmp = Kokkos::shfl_down(value, 1,32);
+        if( id + 1 < gridDim.x )
+          join(value, tmp);
+      }
+      if (blockDim.x*blockDim.y > 2) {
+        value_type tmp = Kokkos::shfl_down(value, 2,32);
+        if( id + 2 < gridDim.x )
+          join(value, tmp);
+      }
+      if (blockDim.x*blockDim.y > 4) {
+        value_type tmp = Kokkos::shfl_down(value, 4,32);
+        if( id + 4 < gridDim.x )
+          join(value, tmp);
+      }
+      if (blockDim.x*blockDim.y > 8) {
+        value_type tmp = Kokkos::shfl_down(value, 8,32);
+        if( id + 8 < gridDim.x )
+          join(value, tmp);
+      }
+      if (blockDim.x*blockDim.y > 16) {
+        value_type tmp = Kokkos::shfl_down(value, 16,32);
+        if( id + 16 < gridDim.x )
+          join(value, tmp);
+      }
+    }
+  }
+
+  //The last block has in its thread=0 the global reduction value through "value"
+  return last_block;
+}
+
+//----------------------------------------------------------------------------
+// See section B.17 of Cuda C Programming Guide Version 3.2
+// for discussion of
+//   __launch_bounds__(maxThreadsPerBlock,minBlocksPerMultiprocessor)
+// function qualifier which could be used to improve performance.
+//----------------------------------------------------------------------------
+// Maximize shared memory and minimize L1 cache:
+//   cudaFuncSetCacheConfig(MyKernel, cudaFuncCachePreferShared );
+// For 2.0 capability: 48 KB shared and 16 KB L1
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+/*
+ *  Algorithmic constraints:
+ *   (a) blockDim.y is a power of two
+ *   (b) blockDim.y <= 512
+ *   (c) blockDim.x == blockDim.z == 1
+ */
+
+template< bool DoScan , class FunctorType , class ArgTag >
+__device__
+void cuda_intra_block_reduce_scan( const FunctorType & functor ,
+                                   const typename FunctorValueTraits< FunctorType , ArgTag >::pointer_type base_data )
+{
+  typedef FunctorValueTraits< FunctorType , ArgTag >  ValueTraits ;
+  typedef FunctorValueJoin<   FunctorType , ArgTag >  ValueJoin ;
+
+  typedef typename ValueTraits::pointer_type  pointer_type ;
+
+  const unsigned value_count   = ValueTraits::value_count( functor );
+  const unsigned BlockSizeMask = blockDim.y - 1 ;
+
+  // Must have power of two thread count
+
+  if ( BlockSizeMask & blockDim.y ) { Kokkos::abort("Cuda::cuda_intra_block_scan requires power-of-two blockDim"); }
+
+#define BLOCK_REDUCE_STEP( R , TD , S )  \
+  if ( ! ( R & ((1<<(S+1))-1) ) ) { ValueJoin::join( functor , TD , (TD - (value_count<<S)) ); }
+
+#define BLOCK_SCAN_STEP( TD , N , S )  \
+  if ( N == (1<<S) ) { ValueJoin::join( functor , TD , (TD - (value_count<<S))); }
+
+  const unsigned     rtid_intra = threadIdx.y ^ BlockSizeMask ;
+  const pointer_type tdata_intra = base_data + value_count * threadIdx.y ;
+
+  { // Intra-warp reduction:
+    BLOCK_REDUCE_STEP(rtid_intra,tdata_intra,0)
+    BLOCK_REDUCE_STEP(rtid_intra,tdata_intra,1)
+    BLOCK_REDUCE_STEP(rtid_intra,tdata_intra,2)
+    BLOCK_REDUCE_STEP(rtid_intra,tdata_intra,3)
+    BLOCK_REDUCE_STEP(rtid_intra,tdata_intra,4)
+  }
+
+  __syncthreads(); // Wait for all warps to reduce
+
+  { // Inter-warp reduce-scan by a single warp to avoid extra synchronizations
+    const unsigned rtid_inter = ( threadIdx.y ^ BlockSizeMask ) << CudaTraits::WarpIndexShift ;
+
+    if ( rtid_inter < blockDim.y ) {
+
+      const pointer_type tdata_inter = base_data + value_count * ( rtid_inter ^ BlockSizeMask );
+
+      if ( (1<<5) < BlockSizeMask ) {                        BLOCK_REDUCE_STEP(rtid_inter,tdata_inter,5) }
+      if ( (1<<6) < BlockSizeMask ) { __threadfence_block(); BLOCK_REDUCE_STEP(rtid_inter,tdata_inter,6) }
+      if ( (1<<7) < BlockSizeMask ) { __threadfence_block(); BLOCK_REDUCE_STEP(rtid_inter,tdata_inter,7) }
+      if ( (1<<8) < BlockSizeMask ) { __threadfence_block(); BLOCK_REDUCE_STEP(rtid_inter,tdata_inter,8) }
+
+      if ( DoScan ) {
+
+        int n = ( rtid_inter &  32 ) ?  32 : (
+                ( rtid_inter &  64 ) ?  64 : (
+                ( rtid_inter & 128 ) ? 128 : (
+                ( rtid_inter & 256 ) ? 256 : 0 )));
+
+        if ( ! ( rtid_inter + n < blockDim.y ) ) n = 0 ;
+
+        BLOCK_SCAN_STEP(tdata_inter,n,8)
+        BLOCK_SCAN_STEP(tdata_inter,n,7)
+        BLOCK_SCAN_STEP(tdata_inter,n,6)
+        BLOCK_SCAN_STEP(tdata_inter,n,5)
+      }
+    }
+  }
+
+  __syncthreads(); // Wait for inter-warp reduce-scan to complete
+
+  if ( DoScan ) {
+    int n = ( rtid_intra &  1 ) ?  1 : (
+            ( rtid_intra &  2 ) ?  2 : (
+            ( rtid_intra &  4 ) ?  4 : (
+            ( rtid_intra &  8 ) ?  8 : (
+            ( rtid_intra & 16 ) ? 16 : 0 ))));
+
+    if ( ! ( rtid_intra + n < blockDim.y ) ) n = 0 ;
+
+    BLOCK_SCAN_STEP(tdata_intra,n,4) __threadfence_block();
+    BLOCK_SCAN_STEP(tdata_intra,n,3) __threadfence_block();
+    BLOCK_SCAN_STEP(tdata_intra,n,2) __threadfence_block();
+    BLOCK_SCAN_STEP(tdata_intra,n,1) __threadfence_block();
+    BLOCK_SCAN_STEP(tdata_intra,n,0)
+  }
+
+#undef BLOCK_SCAN_STEP
+#undef BLOCK_REDUCE_STEP
+}
+
+//----------------------------------------------------------------------------
+/**\brief  Input value-per-thread starting at 'shared_data'.
+ *         Reduction value at last thread's location.
+ *
+ *  If 'DoScan' then write blocks' scan values and block-groups' scan values.
+ *
+ *  Global reduce result is in the last threads' 'shared_data' location.
+ */
+template< bool DoScan , class FunctorType , class ArgTag >
+__device__
+bool cuda_single_inter_block_reduce_scan( const FunctorType     & functor ,
+                                          const Cuda::size_type   block_id ,
+                                          const Cuda::size_type   block_count ,
+                                          Cuda::size_type * const shared_data ,
+                                          Cuda::size_type * const global_data ,
+                                          Cuda::size_type * const global_flags )
+{
+  typedef Cuda::size_type                  size_type ;
+  typedef FunctorValueTraits< FunctorType , ArgTag >  ValueTraits ;
+  typedef FunctorValueJoin<   FunctorType , ArgTag >  ValueJoin ;
+  typedef FunctorValueInit<   FunctorType , ArgTag >  ValueInit ;
+  typedef FunctorValueOps<    FunctorType , ArgTag >  ValueOps ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  // '__ffs' = position of the least significant bit set to 1.
+  // 'blockDim.y' is guaranteed to be a power of two so this
+  // is the integral shift value that can replace an integral divide.
+  const unsigned BlockSizeShift = __ffs( blockDim.y ) - 1 ;
+  const unsigned BlockSizeMask  = blockDim.y - 1 ;
+
+  // Must have power of two thread count
+  if ( BlockSizeMask & blockDim.y ) { Kokkos::abort("Cuda::cuda_single_inter_block_reduce_scan requires power-of-two blockDim"); }
+
+  const integral_nonzero_constant< size_type , ValueTraits::StaticValueSize / sizeof(size_type) >
+    word_count( ValueTraits::value_size( functor ) / sizeof(size_type) );
+
+  // Reduce the accumulation for the entire block.
+  cuda_intra_block_reduce_scan<false,FunctorType,ArgTag>( functor , pointer_type(shared_data) );
+
+  {
+    // Write accumulation total to global scratch space.
+    // Accumulation total is the last thread's data.
+    size_type * const shared = shared_data + word_count.value * BlockSizeMask ;
+    size_type * const global = global_data + word_count.value * block_id ;
+
+#if (__CUDA_ARCH__ < 500)
+    for ( size_type i = threadIdx.y ; i < word_count.value ; i += blockDim.y ) { global[i] = shared[i] ; }
+#else
+    for ( size_type i = 0 ; i < word_count.value ; i += 1 ) { global[i] = shared[i] ; }
+#endif
+
+  }
+
+  // Contributing blocks note that their contribution has been completed via an atomic-increment flag
+  // If this block is not the last block to contribute to this group then the block is done.
+  const bool is_last_block =
+    ! __syncthreads_or( threadIdx.y ? 0 : ( 1 + atomicInc( global_flags , block_count - 1 ) < block_count ) );
+
+  if ( is_last_block ) {
+
+    const size_type b = ( long(block_count) * long(threadIdx.y) ) >> BlockSizeShift ;
+    const size_type e = ( long(block_count) * long( threadIdx.y + 1 ) ) >> BlockSizeShift ;
+
+    {
+      void * const shared_ptr = shared_data + word_count.value * threadIdx.y ;
+      reference_type shared_value = ValueInit::init( functor , shared_ptr );
+
+      for ( size_type i = b ; i < e ; ++i ) {
+        ValueJoin::join( functor , shared_ptr , global_data + word_count.value * i );
+      }
+    }
+
+    cuda_intra_block_reduce_scan<DoScan,FunctorType,ArgTag>( functor , pointer_type(shared_data) );
+
+    if ( DoScan ) {
+
+      size_type * const shared_value = shared_data + word_count.value * ( threadIdx.y ? threadIdx.y - 1 : blockDim.y );
+
+      if ( ! threadIdx.y ) { ValueInit::init( functor , shared_value ); }
+
+      // Join previous inclusive scan value to each member
+      for ( size_type i = b ; i < e ; ++i ) {
+        size_type * const global_value = global_data + word_count.value * i ;
+        ValueJoin::join( functor , shared_value , global_value );
+        ValueOps ::copy( functor , global_value , shared_value );
+      }
+    }
+  }
+
+  return is_last_block ;
+}
+
+// Size in bytes required for inter block reduce or scan
+template< bool DoScan , class FunctorType , class ArgTag >
+inline
+unsigned cuda_single_inter_block_reduce_scan_shmem( const FunctorType & functor , const unsigned BlockSize )
+{
+  return ( BlockSize + 2 ) * Impl::FunctorValueTraits< FunctorType , ArgTag >::value_size( functor );
+}
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( __CUDACC__ ) */
+#endif /* KOKKOS_CUDA_REDUCESCAN_HPP */
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.cpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.cpp
new file mode 100644
index 0000000000..701d267e1b
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.cpp
@@ -0,0 +1,179 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_CUDA ) && defined( KOKKOS_ENABLE_TASKPOLICY )
+
+#include <impl/Kokkos_TaskQueue_impl.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template class TaskQueue< Kokkos::Cuda > ;
+
+//----------------------------------------------------------------------------
+
+__device__
+void TaskQueueSpecialization< Kokkos::Cuda >::driver
+  ( TaskQueueSpecialization< Kokkos::Cuda >::queue_type * const queue )
+{
+  using Member = TaskExec< Kokkos::Cuda > ;
+  using Queue  = TaskQueue< Kokkos::Cuda > ;
+  using task_root_type = TaskBase< Kokkos::Cuda , void , void > ;
+
+  task_root_type * const end = (task_root_type *) task_root_type::EndTag ;
+
+  Member single_exec( 1 );
+  Member team_exec( blockDim.y );
+
+  const int warp_lane = threadIdx.x + threadIdx.y * blockDim.x ;
+
+  union {
+    task_root_type * ptr ;
+    int              raw[2] ;
+  } task ;
+
+  // Loop until all queues are empty and no tasks in flight
+
+  do {
+
+    // Each team lead attempts to acquire either a thread team task
+    // or collection of single thread tasks for the team.
+
+    if ( 0 == warp_lane ) {
+
+      task.ptr = 0 < *((volatile int *) & queue->m_ready_count) ? end : 0 ;
+
+      // Loop by priority and then type
+      for ( int i = 0 ; i < Queue::NumQueue && end == task.ptr ; ++i ) {
+        for ( int j = 0 ; j < 2 && end == task.ptr ; ++j ) {
+          task.ptr = Queue::pop_task( & queue->m_ready[i][j] );
+        }
+      }
+
+#if 0
+printf("TaskQueue<Cuda>::driver(%d,%d) task(%lx)\n",threadIdx.z,blockIdx.x
+      , uintptr_t(task.ptr));
+#endif
+
+    }
+
+    // shuffle broadcast
+
+    task.raw[0] = __shfl( task.raw[0] , 0 );
+    task.raw[1] = __shfl( task.raw[1] , 0 );
+
+    if ( 0 == task.ptr ) break ; // 0 == queue->m_ready_count
+
+    if ( end != task.ptr ) {
+      if ( task_root_type::TaskTeam == task.ptr->m_task_type ) {
+        // Thread Team Task
+        (*task.ptr->m_apply)( task.ptr , & team_exec );
+      }
+      else if ( 0 == threadIdx.y ) {
+        // Single Thread Task
+        (*task.ptr->m_apply)( task.ptr , & single_exec );
+      }
+
+      if ( 0 == warp_lane ) {
+        queue->complete( task.ptr ); 
+      }
+    }
+  } while(1);
+}
+
+namespace {
+
+__global__
+void cuda_task_queue_execute( TaskQueue< Kokkos::Cuda > * queue )
+{ TaskQueueSpecialization< Kokkos::Cuda >::driver( queue ); }
+
+}
+
+void TaskQueueSpecialization< Kokkos::Cuda >::execute
+  ( TaskQueue< Kokkos::Cuda > * const queue )
+{
+  const int warps_per_block = 4 ;
+  const dim3 grid( Kokkos::Impl::cuda_internal_multiprocessor_count() , 1 , 1 );
+  const dim3 block( 1 , Kokkos::Impl::CudaTraits::WarpSize , warps_per_block );
+  const int shared = 0 ;
+  const cudaStream_t stream = 0 ;
+
+  CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+
+#if 0
+printf("cuda_task_queue_execute before\n");
+#endif
+
+  // Query the stack size, in bytes:
+  //
+  // size_t stack_size = 0 ;
+  // CUDA_SAFE_CALL( cudaDeviceGetLimit( & stack_size , cudaLimitStackSize ) );
+  //
+  // If not large enough then set the stack size, in bytes:
+  //
+  // CUDA_SAFE_CALL( cudaDeviceSetLimit( cudaLimitStackSize , stack_size ) );
+ 
+  cuda_task_queue_execute<<< grid , block , shared , stream >>>( queue );
+
+  CUDA_SAFE_CALL( cudaGetLastError() );
+
+  CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+
+#if 0
+printf("cuda_task_queue_execute after\n");
+#endif
+
+}
+
+}} /* namespace Kokkos::Impl */
+
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) && defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.hpp
new file mode 100644
index 0000000000..9d9347cc8d
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Task.hpp
@@ -0,0 +1,519 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_IMPL_CUDA_TASK_HPP
+#define KOKKOS_IMPL_CUDA_TASK_HPP
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+namespace {
+
+template< typename TaskType >
+__global__
+void set_cuda_task_base_apply_function_pointer
+  ( TaskBase<Kokkos::Cuda,void,void>::function_type * ptr )
+{ *ptr = TaskType::apply ; }
+
+}
+
+template<>
+class TaskQueueSpecialization< Kokkos::Cuda >
+{
+public:
+
+  using execution_space = Kokkos::Cuda ;
+  using memory_space    = Kokkos::CudaUVMSpace ;
+  using queue_type      = TaskQueue< execution_space > ;
+
+  static
+  void iff_single_thread_recursive_execute( queue_type * const ) {}
+
+  __device__
+  static void driver( queue_type * const );
+
+  static
+  void execute( queue_type * const );
+
+  template< typename FunctorType >
+  static
+  void proc_set_apply( TaskBase<execution_space,void,void>::function_type * ptr )
+    {
+      using TaskType = TaskBase< execution_space
+                               , typename FunctorType::value_type
+                               , FunctorType > ;
+
+      CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+
+      set_cuda_task_base_apply_function_pointer<TaskType><<<1,1>>>(ptr);
+
+      CUDA_SAFE_CALL( cudaGetLastError() );
+      CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+    }
+};
+
+extern template class TaskQueue< Kokkos::Cuda > ;
+
+//----------------------------------------------------------------------------
+/**\brief  Impl::TaskExec<Cuda> is the TaskPolicy<Cuda>::member_type
+ *         passed to tasks running in a Cuda space.
+ *
+ *  Cuda thread blocks for tasking are dimensioned:
+ *    blockDim.x == vector length
+ *    blockDim.y == team size
+ *    blockDim.z == number of teams
+ *  where
+ *    blockDim.x * blockDim.y == WarpSize
+ *
+ *  Both single thread and thread team tasks are run by a full Cuda warp.
+ *  A single thread task is called by warp lane #0 and the remaining
+ *  lanes of the warp are idle.
+ */
+template<>
+class TaskExec< Kokkos::Cuda >
+{
+private:
+
+  TaskExec( TaskExec && ) = delete ;
+  TaskExec( TaskExec const & ) = delete ;
+  TaskExec & operator = ( TaskExec && ) = delete ;
+  TaskExec & operator = ( TaskExec const & ) = delete ;
+
+  friend class Kokkos::Impl::TaskQueue< Kokkos::Cuda > ;
+  friend class Kokkos::Impl::TaskQueueSpecialization< Kokkos::Cuda > ;
+
+  const int m_team_size ;
+
+  __device__
+  TaskExec( int arg_team_size = blockDim.y )
+    : m_team_size( arg_team_size ) {}
+
+public:
+
+#if defined( __CUDA_ARCH__ )
+  __device__ void team_barrier() { /* __threadfence_block(); */ }
+  __device__ int  team_rank() const { return threadIdx.y ; }
+  __device__ int  team_size() const { return m_team_size ; }
+#else
+  __host__ void team_barrier() {}
+  __host__ int  team_rank() const { return 0 ; }
+  __host__ int  team_size() const { return 0 ; }
+#endif
+
+};
+
+//----------------------------------------------------------------------------
+
+template<typename iType>
+struct TeamThreadRangeBoundariesStruct<iType, TaskExec< Kokkos::Cuda > >
+{
+  typedef iType index_type;
+  const iType start ;
+  const iType end ;
+  const iType increment ;
+  const TaskExec< Kokkos::Cuda > & thread;
+
+#if defined( __CUDA_ARCH__ )
+
+  __device__ inline
+  TeamThreadRangeBoundariesStruct
+    ( const TaskExec< Kokkos::Cuda > & arg_thread, const iType& arg_count)
+    : start( threadIdx.y )
+    , end(arg_count)
+    , increment( blockDim.y )
+    , thread(arg_thread)
+    {}
+
+  __device__ inline
+  TeamThreadRangeBoundariesStruct
+    ( const TaskExec< Kokkos::Cuda > & arg_thread
+    , const iType & arg_start
+    , const iType & arg_end
+    )
+    : start( arg_start + threadIdx.y )
+    , end(   arg_end)
+    , increment( blockDim.y )
+    , thread( arg_thread )
+    {}
+
+#else
+
+  TeamThreadRangeBoundariesStruct
+    ( const TaskExec< Kokkos::Cuda > & arg_thread, const iType& arg_count);
+
+  TeamThreadRangeBoundariesStruct
+    ( const TaskExec< Kokkos::Cuda > & arg_thread
+    , const iType & arg_start
+    , const iType & arg_end
+    );
+
+#endif
+
+};
+
+//----------------------------------------------------------------------------
+
+template<typename iType>
+struct ThreadVectorRangeBoundariesStruct<iType, TaskExec< Kokkos::Cuda > >
+{
+  typedef iType index_type;
+  const iType start ;
+  const iType end ;
+  const iType increment ;
+  const TaskExec< Kokkos::Cuda > & thread;
+
+#if defined( __CUDA_ARCH__ )
+
+  __device__ inline
+  ThreadVectorRangeBoundariesStruct
+    ( const TaskExec< Kokkos::Cuda > & arg_thread, const iType& arg_count)
+    : start( threadIdx.x )
+    , end(arg_count)
+    , increment( blockDim.x )
+    , thread(arg_thread)
+    {}
+
+#else
+
+  ThreadVectorRangeBoundariesStruct
+    ( const TaskExec< Kokkos::Cuda > & arg_thread, const iType& arg_count);
+
+#endif
+
+};
+
+}} /* namespace Kokkos::Impl */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >
+TeamThreadRange( const Impl::TaskExec< Kokkos::Cuda > & thread
+               , const iType & count )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >(thread,count);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >
+TeamThreadRange( const Impl::TaskExec< Kokkos::Cuda > & thread, const iType & start , const iType & end )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::Cuda > >(thread,start,end);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >
+ThreadVectorRange( const Impl::TaskExec< Kokkos::Cuda > & thread
+               , const iType & count )
+{
+  return Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >(thread,count);
+}
+
+/** \brief  Inter-thread parallel_for. Executes lambda(iType i) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all threads of the the calling thread team.
+ * This functionality requires C++11 support.
+*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for
+  ( const Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::Cuda > >& loop_boundaries
+  , const Lambda& lambda
+  )
+{
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i);
+  }
+}
+
+// reduce across corresponding lanes between team members within warp
+// assume stride*team_size == warp_size
+template< typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void strided_shfl_warp_reduction
+  (const JoinType& join,
+   ValueType& val,
+   int team_size,
+   int stride)
+{
+  for (int lane_delta=(team_size*stride)>>1; lane_delta>=stride; lane_delta>>=1) {
+    join(val, Kokkos::shfl_down(val, lane_delta, team_size*stride));
+  }
+}
+
+// multiple within-warp non-strided reductions
+template< typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void multi_shfl_warp_reduction
+  (const JoinType& join,
+   ValueType& val,
+   int vec_length)
+{
+  for (int lane_delta=vec_length>>1; lane_delta; lane_delta>>=1) {
+    join(val, Kokkos::shfl_down(val, lane_delta, vec_length));
+  }
+}
+
+// broadcast within warp
+template< class ValueType >
+KOKKOS_INLINE_FUNCTION
+ValueType shfl_warp_broadcast
+  (ValueType& val,
+   int src_lane,
+   int width)
+{
+  return Kokkos::shfl(val, src_lane, width);
+}
+
+// all-reduce across corresponding vector lanes between team members within warp
+// assume vec_length*team_size == warp_size 
+// blockDim.x == vec_length == stride
+// blockDim.y == team_size
+// threadIdx.x == position in vec
+// threadIdx.y == member number
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >& loop_boundaries,
+   const Lambda & lambda,
+   const JoinType& join,
+   ValueType& initialized_result) {
+
+  ValueType result = initialized_result;
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,result);
+  }
+  initialized_result = result;
+
+  strided_shfl_warp_reduction<ValueType, JoinType>(
+                          join,
+                          initialized_result,
+                          loop_boundaries.thread.team_size(),
+                          blockDim.x);
+  initialized_result = shfl_warp_broadcast<ValueType>( initialized_result, threadIdx.x, Impl::CudaTraits::WarpSize );
+}
+
+// all-reduce across corresponding vector lanes between team members within warp
+// if no join() provided, use sum
+// assume vec_length*team_size == warp_size 
+// blockDim.x == vec_length == stride
+// blockDim.y == team_size
+// threadIdx.x == position in vec
+// threadIdx.y == member number
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >& loop_boundaries,
+   const Lambda & lambda,
+   ValueType& initialized_result) {
+
+  //TODO what is the point of creating this temporary?
+  ValueType result = initialized_result;
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,result);
+  }
+  initialized_result = result;
+
+  strided_shfl_warp_reduction(
+                          [&] (ValueType& val1, const ValueType& val2) { val1 += val2; },
+                          initialized_result,
+                          loop_boundaries.thread.team_size(),
+                          blockDim.x);
+  initialized_result = shfl_warp_broadcast<ValueType>( initialized_result, threadIdx.x, Impl::CudaTraits::WarpSize );
+}
+
+// all-reduce within team members within warp
+// assume vec_length*team_size == warp_size 
+// blockDim.x == vec_length == stride
+// blockDim.y == team_size
+// threadIdx.x == position in vec
+// threadIdx.y == member number
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >& loop_boundaries,
+   const Lambda & lambda,
+   const JoinType& join,
+   ValueType& initialized_result) {
+
+  ValueType result = initialized_result;
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,result);
+  }
+  initialized_result = result;
+
+  multi_shfl_warp_reduction<ValueType, JoinType>(join, initialized_result, blockDim.x);
+  initialized_result = shfl_warp_broadcast<ValueType>( initialized_result, 0, blockDim.x );
+}
+
+// all-reduce within team members within warp
+// if no join() provided, use sum
+// assume vec_length*team_size == warp_size 
+// blockDim.x == vec_length == stride
+// blockDim.y == team_size
+// threadIdx.x == position in vec
+// threadIdx.y == member number
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >& loop_boundaries,
+   const Lambda & lambda,
+   ValueType& initialized_result) {
+
+  ValueType result = initialized_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,result);
+  }
+
+  initialized_result = result;
+
+  //initialized_result = multi_shfl_warp_reduction(
+  multi_shfl_warp_reduction(
+                          [&] (ValueType& val1, const ValueType& val2) { val1 += val2; },
+                          initialized_result,
+                          blockDim.x);
+  initialized_result = shfl_warp_broadcast<ValueType>( initialized_result, 0, blockDim.x );
+}
+
+// scan across corresponding vector lanes between team members within warp
+// assume vec_length*team_size == warp_size 
+// blockDim.x == vec_length == stride
+// blockDim.y == team_size
+// threadIdx.x == position in vec
+// threadIdx.y == member number
+template< typename ValueType, typename iType, class Lambda >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan
+  (const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >& loop_boundaries,
+   const Lambda & lambda) {
+
+  ValueType accum = 0 ;
+  ValueType val, y, local_total;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    val = 0;
+    lambda(i,val,false);
+
+    // intra-blockDim.y exclusive scan on 'val'
+    // accum = accumulated, sum in total for this iteration
+
+    // INCLUSIVE scan
+    for( int offset = blockDim.x ; offset < Impl::CudaTraits::WarpSize ; offset <<= 1 ) {
+      y = Kokkos::shfl_up(val, offset, Impl::CudaTraits::WarpSize);
+      if(threadIdx.y*blockDim.x >= offset) { val += y; }
+    }
+
+    // pass accum to all threads
+    local_total = shfl_warp_broadcast<ValueType>(val,
+                                            threadIdx.x+Impl::CudaTraits::WarpSize-blockDim.x,
+                                            Impl::CudaTraits::WarpSize);
+
+    // make EXCLUSIVE scan by shifting values over one
+    val = Kokkos::shfl_up(val, blockDim.x, Impl::CudaTraits::WarpSize);
+    if ( threadIdx.y == 0 ) { val = 0 ; }
+
+    val += accum;
+    lambda(i,val,true);
+    accum += local_total;
+  }
+}
+
+// scan within team member (vector) within warp
+// assume vec_length*team_size == warp_size 
+// blockDim.x == vec_length == stride
+// blockDim.y == team_size
+// threadIdx.x == position in vec
+// threadIdx.y == member number
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Cuda > >& loop_boundaries,
+   const Lambda & lambda)
+{
+  ValueType accum = 0 ;
+  ValueType val, y, local_total;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    val = 0;
+    lambda(i,val,false);
+
+    // intra-blockDim.x exclusive scan on 'val'
+    // accum = accumulated, sum in total for this iteration
+
+    // INCLUSIVE scan
+    for( int offset = 1 ; offset < blockDim.x ; offset <<= 1 ) {
+      y = Kokkos::shfl_up(val, offset, blockDim.x);
+      if(threadIdx.x >= offset) { val += y; }
+    }
+
+    // pass accum to all threads
+    local_total = shfl_warp_broadcast<ValueType>(val, blockDim.x-1, blockDim.x);
+
+    // make EXCLUSIVE scan by shifting values over one
+    val = Kokkos::shfl_up(val, 1, blockDim.x);
+    if ( threadIdx.x == 0 ) { val = 0 ; }
+
+    val += accum;
+    lambda(i,val,true);
+    accum += local_total;
+  }
+}
+
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #ifndef KOKKOS_IMPL_CUDA_TASK_HPP */
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_TaskPolicy.cpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_TaskPolicy.cpp
new file mode 100644
index 0000000000..bb3cd2640d
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_TaskPolicy.cpp
@@ -0,0 +1,932 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#include <stdio.h>
+#include <iostream>
+#include <sstream>
+#include <Kokkos_Core.hpp>
+#include <Cuda/Kokkos_Cuda_TaskPolicy.hpp>
+
+#if defined( KOKKOS_HAVE_CUDA ) && defined( KOKKOS_ENABLE_TASKPOLICY )
+
+// #define DETAILED_PRINT
+
+//----------------------------------------------------------------------------
+
+#define QLOCK   reinterpret_cast<void*>( ~((uintptr_t)0) )
+#define QDENIED reinterpret_cast<void*>( ~((uintptr_t)0) - 1 )
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+void CudaTaskPolicyQueue::Destroy::destroy_shared_allocation()
+{
+  // Verify the queue is empty
+
+  if ( m_policy->m_count_ready ||
+       m_policy->m_team[0] ||
+       m_policy->m_team[1] ||
+       m_policy->m_team[2] ||
+       m_policy->m_serial[0] ||
+       m_policy->m_serial[1] ||
+       m_policy->m_serial[2] ) {
+    Kokkos::abort("CudaTaskPolicyQueue ERROR : Attempt to destroy non-empty queue" );
+  }
+
+  m_policy->~CudaTaskPolicyQueue();
+
+  Kokkos::Cuda::fence();
+}
+
+CudaTaskPolicyQueue::
+~CudaTaskPolicyQueue()
+{
+}
+
+CudaTaskPolicyQueue::
+CudaTaskPolicyQueue
+  ( const unsigned arg_task_max_count
+  , const unsigned arg_task_max_size
+  , const unsigned arg_task_default_dependence_capacity 
+  , const unsigned arg_team_size
+  )
+  : m_space( Kokkos::CudaUVMSpace()
+           , arg_task_max_size * arg_task_max_count * 1.2
+           , 16 /* log2(superblock size) */
+           )
+  , m_team { 0 , 0 , 0 }
+  , m_serial { 0 , 0 , 0 }
+  , m_team_size( 32 /* 1 warps */ )
+  , m_default_dependence_capacity( arg_task_default_dependence_capacity )
+  , m_count_ready(0)
+{
+  constexpr int max_team_size = 32 * 16 /* 16 warps */ ;
+
+  const int target_team_size =
+    std::min( int(arg_team_size) , max_team_size );
+
+  while ( m_team_size < target_team_size ) { m_team_size *= 2 ; }
+}
+
+//-----------------------------------------------------------------------
+// Called by each block & thread
+
+__device__
+void Kokkos::Experimental::Impl::CudaTaskPolicyQueue::driver()
+{
+  task_root_type * const q_denied = reinterpret_cast<task_root_type*>(QDENIED);
+
+#define IS_TEAM_LEAD ( threadIdx.x == 0 && threadIdx.y == 0 )
+
+#ifdef DETAILED_PRINT
+if ( IS_TEAM_LEAD ) {
+  printf( "CudaTaskPolicyQueue::driver() begin on %d with count %d\n"
+        , blockIdx.x , m_count_ready );
+}
+#endif
+
+  // Each thread block must iterate this loop synchronously
+  // to insure team-execution of team-task
+
+  __shared__ task_root_type * team_task ;
+
+  __syncthreads();
+
+  do {
+
+    if ( IS_TEAM_LEAD ) {
+      if ( 0 == m_count_ready ) {
+        team_task = q_denied ; // All queues are empty and no running tasks
+      }
+      else {
+        team_task = 0 ;
+        for ( int i = 0 ; i < int(NPRIORITY) && 0 == team_task ; ++i ) {
+          if ( ( i < 2 /* regular queue */ )
+               || ( ! m_space.is_empty() /* waiting for memory */ ) ) {
+            team_task = pop_ready_task( & m_team[i] );
+          }
+        }
+      }
+    }
+
+    __syncthreads();
+
+#ifdef DETAILED_PRINT
+if ( IS_TEAM_LEAD && 0 != team_task ) {
+  printf( "CudaTaskPolicyQueue::driver() (%d) team_task(0x%lx)\n"
+        , blockIdx.x
+        , (unsigned long) team_task );
+}
+#endif
+
+    // team_task == q_denied if all queues are empty
+    // team_task == 0 if no team tasks available
+
+    if ( q_denied != team_task ) {
+      if ( 0 != team_task ) {
+
+        Kokkos::Impl::CudaTeamMember
+          member( kokkos_impl_cuda_shared_memory<void>()
+                , 16                      /* shared_begin */
+                , team_task->m_shmem_size /* shared size */
+                , 0                       /* scratch level 1 pointer */
+                , 0                       /* scratch level 1 size */
+                , 0                       /* league rank */
+                , 1                       /* league size */
+                );
+
+        (*team_task->m_team)( team_task , member );
+
+        // A __synthreads was called and if completed the
+        // functor was destroyed.
+
+        if ( IS_TEAM_LEAD ) {
+          complete_executed_task( team_task );
+        }
+      }
+      else {
+        // One thread of one warp performs this serial task
+        if ( threadIdx.x == 0 &&
+             0 == ( threadIdx.y % 32 ) ) {
+          task_root_type * task = 0 ;
+          for ( int i = 0 ; i < int(NPRIORITY) && 0 == task ; ++i ) {
+            if ( ( i < 2 /* regular queue */ )
+                 || ( ! m_space.is_empty() /* waiting for memory */ ) ) {
+              task = pop_ready_task( & m_serial[i] );
+            }
+          }
+
+#ifdef DETAILED_PRINT
+if ( 0 != task ) {
+  printf( "CudaTaskPolicyQueue::driver() (%2d)(%d) single task(0x%lx)\n"
+        , blockIdx.x
+        , threadIdx.y
+        , (unsigned long) task );
+}
+#endif
+
+          if ( task ) {
+            (*task->m_serial)( task );
+            complete_executed_task( task );
+          }
+        }
+
+        __syncthreads();
+      }
+    }
+  } while ( q_denied != team_task );
+
+#ifdef DETAILED_PRINT
+if ( IS_TEAM_LEAD ) {
+  printf( "CudaTaskPolicyQueue::driver() end on %d with count %d\n"
+        , blockIdx.x , m_count_ready );
+}
+#endif
+
+#undef IS_TEAM_LEAD
+}
+
+//-----------------------------------------------------------------------
+
+__device__
+CudaTaskPolicyQueue::task_root_type *
+CudaTaskPolicyQueue::pop_ready_task(
+  CudaTaskPolicyQueue::task_root_type * volatile * const queue )
+{
+  task_root_type * const q_lock = reinterpret_cast<task_root_type*>(QLOCK);
+  task_root_type * task = 0 ;
+  task_root_type * const task_claim = *queue ;
+
+  if ( ( q_lock != task_claim ) && ( 0 != task_claim ) ) {
+
+    // Queue is not locked and not null, try to claim head of queue.
+    // Is a race among threads to claim the queue.
+
+    if ( task_claim == atomic_compare_exchange(queue,task_claim,q_lock) ) {
+
+      // Aquired the task which must be in the waiting state.
+
+      const int claim_state =
+        atomic_compare_exchange( & task_claim->m_state
+                               , int(TASK_STATE_WAITING)
+                               , int(TASK_STATE_EXECUTING) );
+
+      task_root_type * lock_verify = 0 ;
+
+      if ( claim_state == int(TASK_STATE_WAITING) ) {
+
+        // Transitioned this task from waiting to executing
+        // Update the queue to the next entry and release the lock
+
+        task_root_type * const next =
+          *((task_root_type * volatile *) & task_claim->m_next );
+
+        *((task_root_type * volatile *) & task_claim->m_next ) = 0 ;
+
+        lock_verify = atomic_compare_exchange( queue , q_lock , next );
+      }
+
+      if ( ( claim_state != int(TASK_STATE_WAITING) ) |
+           ( q_lock != lock_verify ) ) {
+
+        printf( "CudaTaskPolicyQueue::pop_ready_task(0x%lx) task(0x%lx) state(%d) ERROR %s\n"
+              , (unsigned long) queue
+               , (unsigned long) task
+               , claim_state
+               , ( claim_state != int(TASK_STATE_WAITING)
+                 ? "NOT WAITING"
+                 : "UNLOCK" ) );
+        Kokkos::abort("CudaTaskPolicyQueue::pop_ready_task");
+      }
+
+      task = task_claim ;
+    }
+  }
+  return task ;
+}
+
+//-----------------------------------------------------------------------
+
+__device__
+void CudaTaskPolicyQueue::complete_executed_task(
+  CudaTaskPolicyQueue::task_root_type * task )
+{
+  task_root_type * const q_denied = reinterpret_cast<task_root_type*>(QDENIED);
+  
+
+#ifdef DETAILED_PRINT
+printf( "CudaTaskPolicyQueue::complete_executed_task(0x%lx) state(%d) (%d)(%d,%d)\n"
+      , (unsigned long) task
+      , task->m_state
+      , blockIdx.x
+      , threadIdx.x
+      , threadIdx.y
+      );
+#endif
+
+  // State is either executing or if respawned then waiting,
+  // try to transition from executing to complete.
+  // Reads the current value.
+  
+  const int state_old =
+    atomic_compare_exchange( & task->m_state
+                           , int(Kokkos::Experimental::TASK_STATE_EXECUTING)
+                           , int(Kokkos::Experimental::TASK_STATE_COMPLETE) );
+  
+  if ( int(Kokkos::Experimental::TASK_STATE_WAITING) == state_old ) {
+    /* Task requested a respawn so reschedule it */
+    schedule_task( task , false /* not initial spawn */ );
+  }
+  else if ( int(Kokkos::Experimental::TASK_STATE_EXECUTING) == state_old ) {
+    /* Task is complete */
+
+    // Clear dependences of this task before locking wait queue
+    
+    task->clear_dependence();
+    
+    // Stop other tasks from adding themselves to this task's wait queue.
+    // The wait queue is updated concurrently so guard with an atomic.
+    
+    task_root_type * wait_queue     = *((task_root_type * volatile *) & task->m_wait );
+    task_root_type * wait_queue_old = 0 ;
+    
+    do {
+      wait_queue_old = wait_queue ;
+      wait_queue     = atomic_compare_exchange( & task->m_wait , wait_queue_old , q_denied ); 
+    } while ( wait_queue_old != wait_queue );
+    
+    // The task has been removed from ready queue and
+    // execution is complete so decrement the reference count.
+    // The reference count was incremented by the initial spawning.
+    // The task may be deleted if this was the last reference.
+
+    task_root_type::assign( & task , 0 );
+
+    // Pop waiting tasks and schedule them
+    while ( wait_queue ) {
+      task_root_type * const x = wait_queue ; wait_queue = x->m_next ; x->m_next = 0 ;
+      schedule_task( x , false /* not initial spawn */ );
+    }
+  }
+  else {
+    printf( "CudaTaskPolicyQueue::complete_executed_task(0x%lx) ERROR state_old(%d) dep_size(%d)\n"
+           , (unsigned long)( task )
+           , int(state_old)
+           , task->m_dep_size
+           );
+    Kokkos::abort("CudaTaskPolicyQueue::complete_executed_task" );
+  }
+  
+  // If the task was respawned it may have already been
+  // put in a ready queue and the count incremented.
+  // By decrementing the count last it will never go to zero
+  // with a ready or executing task.
+  
+  atomic_fetch_add( & m_count_ready , -1 );
+}
+
+__device__
+void TaskMember< Kokkos::Cuda , void , void >::latch_add( const int k )
+{
+  typedef TaskMember< Kokkos::Cuda , void , void >  task_root_type ;
+
+  task_root_type * const q_denied = reinterpret_cast<task_root_type*>(QDENIED);
+
+  const bool ok_input = 0 < k ;
+
+  const int count = ok_input ? atomic_fetch_add( & m_dep_size , -k ) - k 
+                             : k ;
+
+  const bool ok_count = 0 <= count ;
+
+  const int state = 0 != count ? TASK_STATE_WAITING :
+    atomic_compare_exchange( & m_state
+                           , TASK_STATE_WAITING
+                           , TASK_STATE_COMPLETE );
+
+  const bool ok_state = state == TASK_STATE_WAITING ;
+
+  if ( ! ok_count || ! ok_state ) {
+    printf( "CudaTaskPolicyQueue::latch_add[0x%lx](%d) ERROR %s %d\n"
+          , (unsigned long) this
+          , k
+          , ( ! ok_input ? "Non-positive input" :
+            ( ! ok_count ? "Negative count" : "Bad State" ) )
+          , ( ! ok_input ? k :
+            ( ! ok_count ? count : state ) )
+          );
+    Kokkos::abort( "CudaTaskPolicyQueue::latch_add ERROR" );
+  }
+  else if ( 0 == count ) {
+    // Stop other tasks from adding themselves to this latch's wait queue.
+    // The wait queue is updated concurrently so guard with an atomic.
+
+    CudaTaskPolicyQueue & policy    = *m_policy ;
+    task_root_type * wait_queue     = *((task_root_type * volatile *) &m_wait);
+    task_root_type * wait_queue_old = 0 ;
+    
+    do {
+      wait_queue_old = wait_queue ;
+      wait_queue     = atomic_compare_exchange( & m_wait , wait_queue_old , q_denied ); 
+    } while ( wait_queue_old != wait_queue );
+    
+    // Pop waiting tasks and schedule them
+    while ( wait_queue ) {
+      task_root_type * const x = wait_queue ; wait_queue = x->m_next ; x->m_next = 0 ;
+      policy.schedule_task( x , false /* not initial spawn */ );
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+
+void CudaTaskPolicyQueue::reschedule_task(
+  CudaTaskPolicyQueue::task_root_type * const task )
+{
+  // Reschedule transitions from executing back to waiting.
+  const int old_state =
+    atomic_compare_exchange( & task->m_state
+                           , int(TASK_STATE_EXECUTING)
+                           , int(TASK_STATE_WAITING) );
+
+  if ( old_state != int(TASK_STATE_EXECUTING) ) {
+
+    printf( "CudaTaskPolicyQueue::reschedule_task(0x%lx) ERROR state(%d)\n"
+          , (unsigned long) task
+          , old_state
+          );
+    Kokkos::abort("CudaTaskPolicyQueue::reschedule" );
+  }
+}
+
+KOKKOS_FUNCTION
+void CudaTaskPolicyQueue::schedule_task(
+  CudaTaskPolicyQueue::task_root_type * const task ,
+  const bool initial_spawn )
+{
+  task_root_type * const q_lock = reinterpret_cast<task_root_type*>(QLOCK);
+  task_root_type * const q_denied = reinterpret_cast<task_root_type*>(QDENIED);
+
+  //----------------------------------------
+  // State is either constructing or already waiting.
+  // If constructing then transition to waiting.
+
+  {
+    const int old_state = atomic_compare_exchange( & task->m_state
+                                                 , int(TASK_STATE_CONSTRUCTING)
+                                                 , int(TASK_STATE_WAITING) );
+
+    // Head of linked list of tasks waiting on this task
+    task_root_type * const waitTask =
+      *((task_root_type * volatile const *) & task->m_wait );
+
+    // Member of linked list of tasks waiting on some other task
+    task_root_type * const next =
+      *((task_root_type * volatile const *) & task->m_next );
+
+    // An incomplete and non-executing task has:
+    //   task->m_state == TASK_STATE_CONSTRUCTING or TASK_STATE_WAITING
+    //   task->m_wait  != q_denied
+    //   task->m_next  == 0
+    //
+    if ( ( q_denied == waitTask ) ||
+         ( 0 != next ) ||
+         ( old_state != int(TASK_STATE_CONSTRUCTING) &&
+           old_state != int(TASK_STATE_WAITING) ) ) {
+      printf( "CudaTaskPolicyQueue::schedule_task(0x%lx) STATE ERROR: state(%d) wait(0x%lx) next(0x%lx)\n"
+            , (unsigned long) task
+            , old_state
+            , (unsigned long) waitTask
+            , (unsigned long) next );
+      Kokkos::abort("CudaTaskPolicyQueue::schedule" );
+    }
+  }
+
+  //----------------------------------------
+
+  if ( initial_spawn ) {
+    // The initial spawn of a task increments the reference count
+    // for the task's existence in either a waiting or ready queue
+    // until the task has completed.
+    // Completing the task's execution is the matching
+    // decrement of the reference count.
+    task_root_type::assign( 0 , task );
+  }
+
+  //----------------------------------------
+  // Insert this task into a dependence task that is not complete.
+  // Push on to that task's wait queue.
+
+  bool attempt_insert_in_queue = true ;
+
+  task_root_type * volatile * queue =
+    task->m_dep_size ? & task->m_dep[0]->m_wait : (task_root_type **) 0 ;
+
+  for ( int i = 0 ; attempt_insert_in_queue && ( 0 != queue ) ; ) {
+
+    task_root_type * const head_value_old = *queue ;
+
+    if ( q_denied == head_value_old ) {
+      // Wait queue is closed because task is complete,
+      // try again with the next dependence wait queue.
+      ++i ;
+      queue = i < task->m_dep_size ? & task->m_dep[i]->m_wait
+                                   : (task_root_type **) 0 ;
+    }
+    else {
+
+      // Wait queue is open and not denied.
+      // Have exclusive access to this task.
+      // Assign m_next assuming a successfull insertion into the queue.
+      // Fence the memory assignment before attempting the CAS.
+
+      *((task_root_type * volatile *) & task->m_next ) = head_value_old ;
+
+      memory_fence();
+
+      // Attempt to insert this task into the queue.
+      // If fails then continue the attempt.
+
+      attempt_insert_in_queue =
+        head_value_old != atomic_compare_exchange(queue,head_value_old,task);
+    }
+  }
+
+  //----------------------------------------
+  // All dependences are complete, insert into the ready list
+
+  if ( attempt_insert_in_queue ) {
+
+    // Increment the count of ready tasks.
+    // Count will be decremented when task is complete.
+
+    atomic_fetch_add( & m_count_ready , 1 );
+
+    queue = task->m_queue ;
+
+    while ( attempt_insert_in_queue ) {
+
+      // A locked queue is being popped.
+
+      task_root_type * const head_value_old = *queue ;
+
+      if ( q_lock != head_value_old ) {
+        // Read the head of ready queue,
+        // if same as previous value then CAS locks the ready queue
+
+        // Have exclusive access to this task,
+        // assign to head of queue, assuming successful insert
+        // Fence assignment before attempting insert.
+        *((task_root_type * volatile *) & task->m_next ) = head_value_old ;
+
+        memory_fence();
+
+        attempt_insert_in_queue =
+          head_value_old != atomic_compare_exchange(queue,head_value_old,task);
+      }
+    }
+  }
+}
+
+void CudaTaskPolicyQueue::deallocate_task
+  ( CudaTaskPolicyQueue::task_root_type * const task )
+{
+  m_space.deallocate( task , task->m_size_alloc );
+}
+
+KOKKOS_FUNCTION
+CudaTaskPolicyQueue::task_root_type *
+CudaTaskPolicyQueue::allocate_task
+  ( const unsigned arg_sizeof_task
+  , const unsigned arg_dep_capacity
+  , const unsigned arg_team_shmem
+  )
+{
+  const unsigned base_size = arg_sizeof_task +
+    ( arg_sizeof_task % sizeof(task_root_type*)
+    ? sizeof(task_root_type*) - arg_sizeof_task % sizeof(task_root_type*)
+    : 0 );
+
+  const unsigned dep_capacity
+    = ~0u == arg_dep_capacity
+    ? m_default_dependence_capacity
+    : arg_dep_capacity ;
+
+  const unsigned size_alloc =
+     base_size + sizeof(task_root_type*) * dep_capacity ;
+
+  task_root_type * const task =
+    reinterpret_cast<task_root_type*>( m_space.allocate( size_alloc ) );
+
+  if ( task != 0 ) {
+
+    // Initialize task's root and value data structure
+    // Calling function must copy construct the functor.
+
+    new( (void*) task ) task_root_type();
+
+    task->m_policy       = this ;
+    task->m_size_alloc   = size_alloc ;
+    task->m_dep_capacity = dep_capacity ;
+    task->m_shmem_size   = arg_team_shmem ;
+
+    if ( dep_capacity ) {
+      task->m_dep =
+        reinterpret_cast<task_root_type**>(
+        reinterpret_cast<unsigned char*>(task) + base_size );
+
+      for ( unsigned i = 0 ; i < dep_capacity ; ++i )
+        task->task_root_type::m_dep[i] = 0 ;
+    }
+  }
+  return  task ;
+}
+
+//----------------------------------------------------------------------------
+
+void CudaTaskPolicyQueue::add_dependence
+  ( CudaTaskPolicyQueue::task_root_type * const after
+  , CudaTaskPolicyQueue::task_root_type * const before
+  )
+{
+  if ( ( after != 0 ) && ( before != 0 ) ) {
+
+    int const state = *((volatile const int *) & after->m_state );
+
+    // Only add dependence during construction or during execution.
+    // Both tasks must have the same policy.
+    // Dependence on non-full memory cannot be mixed with any other dependence.
+
+    const bool ok_state =
+      Kokkos::Experimental::TASK_STATE_CONSTRUCTING == state ||
+      Kokkos::Experimental::TASK_STATE_EXECUTING    == state ;
+
+    const bool ok_capacity =
+      after->m_dep_size < after->m_dep_capacity ;
+
+    const bool ok_policy =
+      after->m_policy == this && before->m_policy == this ;
+
+    if ( ok_state && ok_capacity && ok_policy ) {
+
+      ++after->m_dep_size ;
+
+      task_root_type::assign( after->m_dep + (after->m_dep_size-1) , before );
+
+      memory_fence();
+    }
+    else {
+
+printf( "CudaTaskPolicyQueue::add_dependence( 0x%lx , 0x%lx ) ERROR %s\n"
+      , (unsigned long) after
+      , (unsigned long) before
+      , ( ! ok_state    ? "Task not constructing or executing" :
+        ( ! ok_capacity ? "Task Exceeded dependence capacity"
+                        : "Tasks from different policies" )) );
+
+      Kokkos::abort("CudaTaskPolicyQueue::add_dependence ERROR");
+    }
+  }
+}
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+TaskPolicy< Kokkos::Cuda >::TaskPolicy
+  ( const unsigned arg_task_max_count
+  , const unsigned arg_task_max_size
+  , const unsigned arg_task_default_dependence_capacity
+  , const unsigned arg_task_team_size
+  )
+  : m_track()
+  , m_policy(0)
+{
+  // Allocate the queue data sructure in UVM space
+
+  typedef Kokkos::Experimental::Impl::SharedAllocationRecord
+    < Kokkos::CudaUVMSpace , Impl::CudaTaskPolicyQueue::Destroy > record_type ;
+
+  record_type * record =
+    record_type::allocate( Kokkos::CudaUVMSpace()
+                         , "CudaUVM task queue"
+                         , sizeof(Impl::CudaTaskPolicyQueue)
+                         );
+
+  m_policy = reinterpret_cast< Impl::CudaTaskPolicyQueue * >( record->data() );
+
+  // Tasks are allocated with application's task size + sizeof(task_root_type)
+
+  const size_t full_task_size_estimate =
+    arg_task_max_size +
+    sizeof(task_root_type) +
+    sizeof(task_root_type*) * arg_task_default_dependence_capacity ;
+
+  new( m_policy )
+    Impl::CudaTaskPolicyQueue( arg_task_max_count
+                             , full_task_size_estimate
+                             , arg_task_default_dependence_capacity
+                             , arg_task_team_size );
+
+  record->m_destroy.m_policy = m_policy ;
+  
+  m_track.assign_allocated_record_to_uninitialized( record );
+}
+
+__global__
+static void kokkos_cuda_task_policy_queue_driver
+  ( Kokkos::Experimental::Impl::CudaTaskPolicyQueue * queue )
+{
+  queue->driver();
+}
+
+void wait( Kokkos::Experimental::TaskPolicy< Kokkos::Cuda > & policy )
+{
+  const dim3 grid( Kokkos::Impl::cuda_internal_multiprocessor_count() , 1 , 1 );
+  const dim3 block( 1 , policy.m_policy->m_team_size , 1 );
+
+  const int shared = 0 ; // Kokkos::Impl::CudaTraits::SharedMemoryUsage / 2 ;
+  const cudaStream_t stream = 0 ;
+
+
+#ifdef DETAILED_PRINT
+printf("kokkos_cuda_task_policy_queue_driver grid(%d,%d,%d) block(%d,%d,%d) shared(%d) policy(0x%lx)\n"
+      , grid.x , grid.y , grid.z
+      , block.x , block.y , block.z
+      , shared
+      , (unsigned long)( policy.m_policy ) );
+fflush(stdout);
+#endif
+
+  CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+
+/*
+  CUDA_SAFE_CALL(
+    cudaFuncSetCacheConfig( kokkos_cuda_task_policy_queue_driver
+                          , cudaFuncCachePreferL1 ) );
+
+  CUDA_SAFE_CALL( cudaGetLastError() );
+*/
+
+  kokkos_cuda_task_policy_queue_driver<<< grid , block , shared , stream >>>
+    ( policy.m_policy );
+ 
+  CUDA_SAFE_CALL( cudaGetLastError() );
+
+  CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+
+#ifdef DETAILED_PRINT
+printf("kokkos_cuda_task_policy_queue_driver end\n");
+fflush(stdout);
+#endif
+
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+typedef TaskMember< Kokkos::Cuda , void , void > Task ;
+
+__host__ __device__
+Task::~TaskMember()
+{
+}
+
+__host__ __device__
+void Task::assign( Task ** const lhs_ptr , Task * rhs )
+{
+  Task * const q_denied = reinterpret_cast<Task*>(QDENIED);
+
+  // Increment rhs reference count.
+  if ( rhs ) { atomic_fetch_add( & rhs->m_ref_count , 1 ); }
+
+  if ( 0 == lhs_ptr ) return ;
+
+  // Must have exclusive access to *lhs_ptr.
+  // Assign the pointer and retrieve the previous value.
+  // Cannot use atomic exchange since *lhs_ptr may be
+  // in Cuda register space.
+
+#if 0
+
+  Task * const old_lhs = *((Task*volatile*)lhs_ptr);
+
+  *((Task*volatile*)lhs_ptr) = rhs ;
+
+  Kokkos::memory_fence();
+
+#else
+
+  Task * const old_lhs = *lhs_ptr ;
+
+  *lhs_ptr = rhs ;
+
+#endif
+
+  if ( old_lhs && rhs && old_lhs->m_policy != rhs->m_policy ) {
+    Kokkos::abort( "Kokkos::Impl::TaskMember<Kokkos::Cuda>::assign ERROR different queues");
+  }
+
+  if ( old_lhs ) {
+
+    Kokkos::memory_fence();
+
+    // Decrement former lhs reference count.
+    // If reference count is zero task must be complete, then delete task.
+    // Task is ready for deletion when  wait == q_denied
+
+    int const count = atomic_fetch_add( & (old_lhs->m_ref_count) , -1 ) - 1 ;
+    int const state = old_lhs->m_state ;
+    Task * const wait = *((Task * const volatile *) & old_lhs->m_wait );
+
+    const bool ok_count = 0 <= count ;
+
+    // If count == 0 then will be deleting
+    // and must either be constructing or complete.
+    const bool ok_state = 0 < count ? true :
+      ( ( state == int(TASK_STATE_CONSTRUCTING) && wait == 0 ) ||
+        ( state == int(TASK_STATE_COMPLETE)     && wait == q_denied ) )
+      &&
+     old_lhs->m_next == 0 &&
+     old_lhs->m_dep_size == 0 ;
+
+    if ( ! ok_count || ! ok_state ) {
+
+      printf( "%s Kokkos::Impl::TaskManager<Kokkos::Cuda>::assign ERROR deleting task(0x%lx) m_ref_count(%d) m_state(%d) m_wait(0x%ld)\n"
+#if defined( KOKKOS_ACTIVE_EXECUTION_SPACE_CUDA )
+            , "CUDA "
+#else
+            , "HOST "
+#endif
+            , (unsigned long) old_lhs
+            , count
+            , state
+            , (unsigned long) wait );
+      Kokkos::abort( "Kokkos::Impl::TaskMember<Kokkos::Cuda>::assign ERROR deleting");
+    }
+
+    if ( count == 0 ) {
+      // When 'count == 0' this thread has exclusive access to 'old_lhs'
+
+#ifdef DETAILED_PRINT
+printf( "Task::assign(...) old_lhs(0x%lx) deallocate\n"
+      , (unsigned long) old_lhs
+      );
+#endif
+
+      old_lhs->m_policy->deallocate_task( old_lhs );
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+
+__device__
+int Task::get_dependence() const
+{
+  return m_dep_size ;
+}
+
+__device__
+Task * Task::get_dependence( int i ) const
+{
+  Task * const t = ((Task*volatile*)m_dep)[i] ;
+
+  if ( Kokkos::Experimental::TASK_STATE_EXECUTING != m_state || i < 0 || m_dep_size <= i || 0 == t ) {
+
+printf( "TaskMember< Cuda >::get_dependence ERROR : task[%lx]{ state(%d) dep_size(%d) dep[%d] = %lx }\n"
+      , (unsigned long) this
+      , m_state
+      , m_dep_size
+      , i
+      , (unsigned long) t
+      );
+
+    Kokkos::abort("TaskMember< Cuda >::get_dependence ERROR");
+  }
+
+  return t ;
+}
+
+//----------------------------------------------------------------------------
+
+__device__ __host__
+void Task::clear_dependence()
+{
+  for ( int i = m_dep_size - 1 ; 0 <= i ; --i ) {
+    assign( m_dep + i , 0 );
+  }
+
+  *((volatile int *) & m_dep_size ) = 0 ;
+
+  memory_fence();
+}
+
+//----------------------------------------------------------------------------
+
+
+//----------------------------------------------------------------------------
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+
+#endif  /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_TaskPolicy.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_TaskPolicy.hpp
new file mode 100644
index 0000000000..e71512f039
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_TaskPolicy.hpp
@@ -0,0 +1,833 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#ifndef KOKKOS_CUDA_TASKPOLICY_HPP
+#define KOKKOS_CUDA_TASKPOLICY_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_Cuda.hpp>
+#include <Kokkos_TaskPolicy.hpp>
+
+#if defined( KOKKOS_HAVE_CUDA ) && defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+struct CudaTaskPolicyQueue ;
+
+/** \brief  Base class for all Kokkos::Cuda tasks */
+template<>
+class TaskMember< Kokkos::Cuda , void , void > {
+public:
+
+  template< class > friend class Kokkos::Experimental::TaskPolicy ;
+  friend struct CudaTaskPolicyQueue ;
+
+  typedef void (* function_single_type) ( TaskMember * );
+  typedef void (* function_team_type)   ( TaskMember * , Kokkos::Impl::CudaTeamMember & );
+
+private:
+
+  CudaTaskPolicyQueue   * m_policy ;
+  TaskMember * volatile * m_queue ;
+  function_team_type      m_team ;    ///< Apply function on CUDA
+  function_single_type    m_serial ;  ///< Apply function on CUDA
+  TaskMember **           m_dep ;     ///< Dependences
+  TaskMember *            m_wait ;    ///< Linked list of tasks waiting on this task
+  TaskMember *            m_next ;    ///< Linked list of tasks waiting on a different task
+  int                    m_dep_capacity ; ///< Capacity of dependences
+  int                    m_dep_size ;     ///< Actual count of dependences
+  int                    m_size_alloc ;
+  int                    m_shmem_size ;
+  int                    m_ref_count ;    ///< Reference count
+  int                    m_state ;        ///< State of the task
+
+
+  TaskMember( TaskMember && ) = delete ;
+  TaskMember( const TaskMember & ) = delete ;
+  TaskMember & operator = ( TaskMember && ) = delete ;
+  TaskMember & operator = ( const TaskMember & ) = delete ;
+
+protected:
+
+  KOKKOS_INLINE_FUNCTION
+  TaskMember()
+    : m_policy(0)
+    , m_queue(0)
+    , m_team(0)
+    , m_serial(0)
+    , m_dep(0)
+    , m_wait(0)
+    , m_next(0)
+    , m_size_alloc(0)
+    , m_dep_capacity(0)
+    , m_dep_size(0)
+    , m_shmem_size(0)
+    , m_ref_count(0)
+    , m_state( TASK_STATE_CONSTRUCTING )
+    {}
+
+public:
+
+  KOKKOS_FUNCTION
+  ~TaskMember();
+
+  KOKKOS_INLINE_FUNCTION
+  int reference_count() const
+    { return *((volatile int *) & m_ref_count ); }
+
+  // Cannot use the function pointer to verify the type
+  // since the function pointer is not unique between
+  // Host and Cuda. Don't run verificaton for Cuda. 
+  // Assume testing on Host-only back-end will catch such errors.
+
+  template< typename ResultType >
+  KOKKOS_INLINE_FUNCTION static
+  TaskMember * verify_type( TaskMember * t ) { return t ; }
+
+  //----------------------------------------
+  /*  Inheritence Requirements on task types:
+   *
+   *    class DerivedTaskType
+   *      : public TaskMember< Cuda , DerivedType::value_type , FunctorType >
+   *      { ... };
+   *
+   *    class TaskMember< Cuda , DerivedType::value_type , FunctorType >
+   *      : public TaskMember< Cuda , DerivedType::value_type , void >
+   *      , public Functor
+   *      { ... };
+   *
+   *  If value_type != void
+   *    class TaskMember< Cuda , value_type , void >
+   *      : public TaskMember< Cuda , void , void >
+   *
+   *  Allocate space for DerivedTaskType followed by TaskMember*[ dependence_capacity ]
+   *
+   */
+  //----------------------------------------
+  // If after the 'apply' the task's state is waiting 
+  // then it will be rescheduled and called again.
+  // Otherwise the functor must be destroyed.
+
+  template< class DerivedTaskType , class Tag >
+  __device__ static
+  void apply_single(
+    typename std::enable_if
+      <( std::is_same< Tag , void >::value &&
+        std::is_same< typename DerivedTaskType::result_type , void >::value
+       ), TaskMember * >::type t )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+
+      functor_type * const f =
+        static_cast< functor_type * >( static_cast< DerivedTaskType * >(t) );
+
+      f->apply();
+
+      if ( t->m_state == int(Kokkos::Experimental::TASK_STATE_EXECUTING) ) {
+        f->~functor_type();
+      }
+    }
+
+  template< class DerivedTaskType , class Tag >
+  __device__ static
+  void apply_single(
+    typename std::enable_if
+      <( std::is_same< Tag , void >::value &&
+        ! std::is_same< typename DerivedTaskType::result_type , void >::value
+       ), TaskMember * >::type t )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+
+      DerivedTaskType * const self = static_cast< DerivedTaskType * >(t);
+      functor_type    * const f    = static_cast< functor_type * >( self );
+
+      f->apply( self->m_result );
+
+      if ( t->m_state == int(Kokkos::Experimental::TASK_STATE_EXECUTING) ) {
+        f->~functor_type();
+      }
+    }
+
+  template< class DerivedTaskType , class Tag >
+  __device__
+  void set_apply_single()
+    {
+      m_serial = & TaskMember::template apply_single<DerivedTaskType,Tag> ;
+    }
+
+  //----------------------------------------
+
+  template< class DerivedTaskType , class Tag >
+  __device__ static
+  void apply_team(
+    typename std::enable_if
+      <( std::is_same<Tag,void>::value &&
+         std::is_same<typename DerivedTaskType::result_type,void>::value
+       ), TaskMember * >::type t
+    , Kokkos::Impl::CudaTeamMember & member
+    )
+    {
+      typedef typename DerivedTaskType::functor_type functor_type ;
+
+      functor_type * const f =
+        static_cast< functor_type * >( static_cast< DerivedTaskType * >(t) );
+
+      f->apply( member );
+
+      __syncthreads(); // Wait for team to finish calling function
+
+      if ( threadIdx.x == 0 &&
+           threadIdx.y == 0 &&
+           t->m_state == int(Kokkos::Experimental::TASK_STATE_EXECUTING) ) {
+        f->~functor_type();
+      }
+    }
+
+  template< class DerivedTaskType , class Tag >
+  __device__ static
+  void apply_team(
+    typename std::enable_if
+      <( std::is_same<Tag,void>::value &&
+         ! std::is_same<typename DerivedTaskType::result_type,void>::value
+       ), TaskMember * >::type t
+    , Kokkos::Impl::CudaTeamMember & member
+    )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+
+      DerivedTaskType * const self = static_cast< DerivedTaskType * >(t);
+      functor_type    * const f    = static_cast< functor_type * >( self );
+
+      f->apply( member , self->m_result );
+
+      __syncthreads(); // Wait for team to finish calling function
+
+      if ( threadIdx.x == 0 &&
+           threadIdx.y == 0 &&
+           t->m_state == int(Kokkos::Experimental::TASK_STATE_EXECUTING) ) {
+        f->~functor_type();
+      }
+    }
+
+  template< class DerivedTaskType , class Tag >
+  __device__
+  void set_apply_team()
+    {
+      m_team = & TaskMember::template apply_team<DerivedTaskType,Tag> ;
+    }
+
+  //----------------------------------------
+
+  KOKKOS_FUNCTION static
+  void assign( TaskMember ** const lhs , TaskMember * const rhs );
+
+  __device__
+  TaskMember * get_dependence( int i ) const ;
+
+  __device__
+  int get_dependence() const ;
+
+  KOKKOS_FUNCTION void clear_dependence();
+
+  __device__
+  void latch_add( const int k );
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION static
+  void construct_result( TaskMember * const ) {}
+
+  typedef FutureValueTypeIsVoidError get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const { return get_result_type() ; }
+
+  KOKKOS_INLINE_FUNCTION
+  Kokkos::Experimental::TaskState get_state() const { return Kokkos::Experimental::TaskState( m_state ); }
+
+};
+
+/** \brief  A Future< Kokkos::Cuda , ResultType > will cast
+ *          from  TaskMember< Kokkos::Cuda , void , void >
+ *          to    TaskMember< Kokkos::Cuda , ResultType , void >
+ *          to query the result.
+ */
+template< class ResultType >
+class TaskMember< Kokkos::Cuda , ResultType , void >
+  : public TaskMember< Kokkos::Cuda , void , void >
+{
+public:
+
+  typedef ResultType result_type ;
+
+  result_type  m_result ;
+
+  typedef const result_type & get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const { return m_result ; }
+
+  KOKKOS_INLINE_FUNCTION static
+  void construct_result( TaskMember * const ptr )
+    {
+      new((void*)(& ptr->m_result)) result_type();
+    }
+
+  TaskMember() = delete ;
+  TaskMember( TaskMember && ) = delete ;
+  TaskMember( const TaskMember & ) = delete ;
+  TaskMember & operator = ( TaskMember && ) = delete ;
+  TaskMember & operator = ( const TaskMember & ) = delete ;
+};
+
+/** \brief  Callback functions will cast
+ *          from  TaskMember< Kokkos::Cuda , void , void >
+ *          to    TaskMember< Kokkos::Cuda , ResultType , FunctorType >
+ *          to execute work functions.
+ */
+template< class ResultType , class FunctorType >
+class TaskMember< Kokkos::Cuda , ResultType , FunctorType >
+  : public TaskMember< Kokkos::Cuda , ResultType , void >
+  , public FunctorType
+{
+public:
+  typedef ResultType   result_type ;
+  typedef FunctorType  functor_type ;
+
+  KOKKOS_INLINE_FUNCTION static
+  void copy_construct( TaskMember * const ptr
+                     , const functor_type & arg_functor )
+    {
+      typedef TaskMember< Kokkos::Cuda , ResultType , void > base_type ;
+
+      new((void*)static_cast<FunctorType*>(ptr)) functor_type( arg_functor );
+
+      base_type::construct_result( static_cast<base_type*>( ptr ) );
+    }
+
+  TaskMember() = delete ;
+  TaskMember( TaskMember && ) = delete ;
+  TaskMember( const TaskMember & ) = delete ;
+  TaskMember & operator = ( TaskMember && ) = delete ;
+  TaskMember & operator = ( const TaskMember & ) = delete ;
+};
+
+//----------------------------------------------------------------------------
+
+namespace {
+
+template< class DerivedTaskType , class Tag >
+__global__
+void cuda_set_apply_single( DerivedTaskType * task )
+{
+  typedef Kokkos::Experimental::Impl::TaskMember< Kokkos::Cuda , void , void >
+    task_root_type ;
+
+  task->task_root_type::template set_apply_single< DerivedTaskType , Tag >();
+}
+
+template< class DerivedTaskType , class Tag >
+__global__
+void cuda_set_apply_team( DerivedTaskType * task )
+{
+  typedef Kokkos::Experimental::Impl::TaskMember< Kokkos::Cuda , void , void >
+    task_root_type ;
+
+  task->task_root_type::template set_apply_team< DerivedTaskType , Tag >();
+}
+
+} /* namespace */
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+struct CudaTaskPolicyQueue {
+
+  enum { NPRIORITY = 3 };
+
+  // Must use UVM so that tasks can be created in both
+  // Host and Cuda space.
+
+  typedef Kokkos::Experimental::MemoryPool< Kokkos::CudaUVMSpace >
+    memory_space ;
+
+  typedef Kokkos::Experimental::Impl::TaskMember< Kokkos::Cuda , void , void >
+    task_root_type ;
+
+  memory_space     m_space ;
+  task_root_type * m_team[ NPRIORITY ] ;
+  task_root_type * m_serial[ NPRIORITY ];
+  int              m_team_size ;
+  int              m_default_dependence_capacity ;
+  int volatile     m_count_ready ; ///< Ready plus executing tasks
+
+  // Execute tasks until all non-waiting tasks are complete
+  __device__
+  void driver();
+
+  __device__ static
+  task_root_type * pop_ready_task( task_root_type * volatile * const queue );
+
+  // When a task finishes executing.
+  __device__
+  void complete_executed_task( task_root_type * );
+
+  KOKKOS_FUNCTION void schedule_task( task_root_type * const 
+                                    , const bool initial_spawn = true );
+  KOKKOS_FUNCTION void reschedule_task( task_root_type * const );
+  KOKKOS_FUNCTION
+  void add_dependence( task_root_type * const after
+                     , task_root_type * const before );
+
+
+  CudaTaskPolicyQueue() = delete ;
+  CudaTaskPolicyQueue( CudaTaskPolicyQueue && ) = delete ;
+  CudaTaskPolicyQueue( const CudaTaskPolicyQueue & ) = delete ;
+  CudaTaskPolicyQueue & operator = ( CudaTaskPolicyQueue && ) = delete ;
+  CudaTaskPolicyQueue & operator = ( const CudaTaskPolicyQueue & ) = delete ;
+
+
+  ~CudaTaskPolicyQueue();
+
+  // Construct only on the Host
+  CudaTaskPolicyQueue
+    ( const unsigned arg_task_max_count
+    , const unsigned arg_task_max_size
+    , const unsigned arg_task_default_dependence_capacity
+    , const unsigned arg_task_team_size
+    );
+
+  struct Destroy {
+    CudaTaskPolicyQueue * m_policy ;
+    void destroy_shared_allocation();
+  };
+
+  //----------------------------------------
+  /** \brief  Allocate and construct a task.
+   *
+   *  Allocate space for DerivedTaskType followed
+   *  by TaskMember*[ dependence_capacity ]
+   */
+  KOKKOS_FUNCTION
+  task_root_type *
+  allocate_task( const unsigned arg_sizeof_task
+               , const unsigned arg_dep_capacity
+               , const unsigned arg_team_shmem = 0 );
+
+  KOKKOS_FUNCTION void deallocate_task( task_root_type * const );
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+void wait( TaskPolicy< Kokkos::Cuda > & );
+
+template<>
+class TaskPolicy< Kokkos::Cuda >
+{
+public:
+
+  typedef Kokkos::Cuda                  execution_space ;
+  typedef TaskPolicy                    execution_policy ;
+  typedef Kokkos::Impl::CudaTeamMember  member_type ;
+
+private:
+
+  typedef Impl::TaskMember< Kokkos::Cuda , void , void >  task_root_type ;
+  typedef Kokkos::Experimental::MemoryPool< Kokkos::CudaUVMSpace > memory_space ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker track_type ;
+
+  track_type                   m_track ;
+  Impl::CudaTaskPolicyQueue  * m_policy ;
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION static
+  const task_root_type * get_task_root( const FunctorType * f )
+    {
+      typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
+      return static_cast< const task_root_type * >( static_cast< const task_type * >(f) );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION static
+  task_root_type * get_task_root( FunctorType * f )
+    {
+      typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
+      return static_cast< task_root_type * >( static_cast< task_type * >(f) );
+    }
+
+public:
+
+  TaskPolicy
+    ( const unsigned arg_task_max_count
+    , const unsigned arg_task_max_size
+    , const unsigned arg_task_default_dependence_capacity = 4
+    , const unsigned arg_task_team_size = 0 /* choose default */
+    );
+
+  KOKKOS_FUNCTION TaskPolicy() = default ;
+  KOKKOS_FUNCTION TaskPolicy( TaskPolicy && rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy( const TaskPolicy & rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy & operator = ( TaskPolicy && rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy & operator = ( const TaskPolicy & rhs ) = default ;
+
+  KOKKOS_FUNCTION
+  int allocated_task_count() const { return 0 ; }
+
+  //----------------------------------------
+  // Create serial-thread task
+  // Main process and tasks must use different functions
+  // to work around CUDA limitation where __host__ __device__
+  // functions are not allowed to invoke templated __global__ functions.
+
+  template< class FunctorType >
+  Future< typename FunctorType::value_type , execution_space >
+  proc_create( const FunctorType & arg_functor
+             , const unsigned      arg_dep_capacity = ~0u ) const
+    {
+      typedef typename FunctorType::value_type  value_type ;
+
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >
+        task_type ;
+
+      task_type * const task =
+        static_cast<task_type*>(
+          m_policy->allocate_task( sizeof(task_type) , arg_dep_capacity ) );
+
+      if ( task ) {
+        // The root part of the class has been constructed.
+        // Must now construct the functor and result specific part.
+
+        task_type::copy_construct( task , arg_functor );
+
+        // Setting the apply pointer on the device requires code
+        // executing on the GPU.  This function is called on the
+        // host process so a kernel must be run.
+
+        // Launching a kernel will cause the allocated task in
+        // UVM memory to be copied to the GPU.
+        // Synchronize to guarantee non-concurrent access
+        // between host and device.
+
+        CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+
+        Impl::cuda_set_apply_single<task_type,void><<<1,1>>>( task );
+
+        CUDA_SAFE_CALL( cudaGetLastError() );
+        CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+      }
+
+      return Future< value_type , execution_space >( task );
+    }
+
+  template< class FunctorType >
+  __device__
+  Future< typename FunctorType::value_type , execution_space >
+  task_create( const FunctorType & arg_functor
+             , const unsigned      arg_dep_capacity = ~0u ) const
+    {
+      typedef typename FunctorType::value_type  value_type ;
+
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >
+        task_type ;
+
+      task_type * const task =
+        static_cast<task_type*>(
+          m_policy->allocate_task( sizeof(task_type) , arg_dep_capacity ) );
+
+      if ( task ) {
+        // The root part of the class has been constructed.
+        // Must now construct the functor and result specific part.
+
+        task_type::copy_construct( task , arg_functor );
+
+        // Setting the apply pointer on the device requires code
+        // executing on the GPU.  If this function is called on the
+        // Host then a kernel must be run.
+
+        task->task_root_type::template set_apply_single< task_type , void >();
+      }
+
+      return Future< value_type , execution_space >( task );
+    }
+
+  //----------------------------------------
+  // Create thread-team task
+  // Main process and tasks must use different functions
+  // to work around CUDA limitation where __host__ __device__
+  // functions are not allowed to invoke templated __global__ functions.
+
+  template< class FunctorType >
+  Future< typename FunctorType::value_type , execution_space >
+  proc_create_team( const FunctorType & arg_functor
+                  , const unsigned      arg_dep_capacity = ~0u ) const
+    {
+      typedef typename FunctorType::value_type  value_type ;
+
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >
+        task_type ;
+
+      const unsigned team_shmem_size =
+        Kokkos::Impl::FunctorTeamShmemSize< FunctorType >::value
+           ( arg_functor , m_policy->m_team_size );
+
+      task_type * const task =
+        static_cast<task_type*>(
+          m_policy->allocate_task( sizeof(task_type) , arg_dep_capacity , team_shmem_size ) );
+
+      if ( task ) {
+        // The root part of the class has been constructed.
+        // Must now construct the functor and result specific part.
+
+        task_type::copy_construct( task , arg_functor );
+
+        // Setting the apply pointer on the device requires code
+        // executing on the GPU.  This function is called on the
+        // host process so a kernel must be run.
+
+        // Launching a kernel will cause the allocated task in
+        // UVM memory to be copied to the GPU.
+        // Synchronize to guarantee non-concurrent access
+        // between host and device.
+
+        CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+
+        Impl::cuda_set_apply_team<task_type,void><<<1,1>>>( task );
+
+        CUDA_SAFE_CALL( cudaGetLastError() );
+        CUDA_SAFE_CALL( cudaDeviceSynchronize() );
+      }
+
+      return Future< value_type , execution_space >( task );
+    }
+
+  template< class FunctorType >
+  __device__
+  Future< typename FunctorType::value_type , execution_space >
+  task_create_team( const FunctorType & arg_functor
+                  , const unsigned      arg_dep_capacity = ~0u ) const
+    {
+      typedef typename FunctorType::value_type  value_type ;
+
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >
+        task_type ;
+
+      const unsigned team_shmem_size =
+        Kokkos::Impl::FunctorTeamShmemSize< FunctorType >::value
+           ( arg_functor , m_policy->m_team_size );
+
+      task_type * const task =
+        static_cast<task_type*>(
+          m_policy->allocate_task( sizeof(task_type) , arg_dep_capacity , team_shmem_size ) );
+
+      if ( task ) {
+        // The root part of the class has been constructed.
+        // Must now construct the functor and result specific part.
+
+        task_type::copy_construct( task , arg_functor );
+
+        // Setting the apply pointer on the device requires code
+        // executing on the GPU.  If this function is called on the
+        // Host then a kernel must be run.
+
+        task->task_root_type::template set_apply_team< task_type , void >();
+      }
+
+      return Future< value_type , execution_space >( task );
+    }
+
+  //----------------------------------------
+
+  Future< Latch , execution_space >
+  KOKKOS_INLINE_FUNCTION
+  create_latch( const int N ) const
+    {
+      task_root_type * const task =
+        m_policy->allocate_task( sizeof(task_root_type) , 0 , 0 );
+      task->m_dep_size = N ; // Using m_dep_size for latch counter
+      task->m_state = TASK_STATE_WAITING ;
+      return Future< Latch , execution_space >( task );
+    }
+
+  //----------------------------------------
+
+  template< class A1 , class A2 , class A3 , class A4 >
+  KOKKOS_INLINE_FUNCTION
+  void add_dependence( const Future<A1,A2> & after
+                     , const Future<A3,A4> & before
+                     , typename std::enable_if
+                        < std::is_same< typename Future<A1,A2>::execution_space , execution_space >::value
+                          &&
+                          std::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
+                        >::type * = 0
+                      ) const
+    { m_policy->add_dependence( after.m_task , before.m_task ); }
+
+  template< class FunctorType , class A3 , class A4 >
+  KOKKOS_INLINE_FUNCTION
+  void add_dependence( FunctorType * task_functor
+                     , const Future<A3,A4> & before
+                     , typename std::enable_if
+                        < std::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
+                        >::type * = 0
+                      ) const
+    { m_policy->add_dependence( get_task_root(task_functor) , before.m_task ); }
+
+
+  template< class ValueType >
+  KOKKOS_INLINE_FUNCTION
+  const Future< ValueType , execution_space > &
+    spawn( const Future< ValueType , execution_space > & f 
+         , const bool priority = false ) const
+      {
+        if ( f.m_task ) {
+          f.m_task->m_queue =
+            ( f.m_task->m_team != 0
+            ? & ( m_policy->m_team[   priority ? 0 : 1 ] )
+            : & ( m_policy->m_serial[ priority ? 0 : 1 ] ) );
+          m_policy->schedule_task( f.m_task );
+        }
+        return f ;
+      }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void respawn( FunctorType * task_functor 
+              , const bool priority = false ) const
+    {
+      task_root_type * const t = get_task_root(task_functor);
+      t->m_queue =
+        ( t->m_team != 0 ? & ( m_policy->m_team[   priority ? 0 : 1 ] )
+                         : & ( m_policy->m_serial[ priority ? 0 : 1 ] ) );
+      m_policy->reschedule_task( t );
+    }
+
+  // When a create method fails by returning a null Future
+  // the task that called the create method may respawn
+  // with a dependence on memory becoming available.
+  // This is a race as more than one task may be respawned
+  // with this need.
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void respawn_needing_memory( FunctorType * task_functor ) const
+    {
+      task_root_type * const t = get_task_root(task_functor);
+      t->m_queue =
+        ( t->m_team != 0 ? & ( m_policy->m_team[   2 ] )
+                         : & ( m_policy->m_serial[ 2 ] ) );
+      m_policy->reschedule_task( t );
+    }
+
+  //----------------------------------------
+  // Functions for an executing task functor to query dependences,
+  // set new dependences, and respawn itself.
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< void , execution_space >
+  get_dependence( const FunctorType * task_functor , int i ) const
+    {
+      return Future<void,execution_space>(
+        get_task_root(task_functor)->get_dependence(i)
+      );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  int get_dependence( const FunctorType * task_functor ) const
+    { return get_task_root(task_functor)->get_dependence(); }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void clear_dependence( FunctorType * task_functor ) const
+    { get_task_root(task_functor)->clear_dependence(); }
+
+  //----------------------------------------
+
+  __device__
+  static member_type member_single()
+    {
+      return
+        member_type( 0 /* shared memory pointer */
+                   , 0 /* shared memory begin offset */
+                   , 0 /* shared memory end offset */
+                   , 0 /* scratch level_1 pointer */
+                   , 0 /* scratch level_1 size */
+                   , 0 /* league rank */
+                   , 1 /* league size */ );
+    }
+
+  friend void wait( TaskPolicy< Kokkos::Cuda > & );
+};
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) && defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #ifndef KOKKOS_CUDA_TASKPOLICY_HPP */
+
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Vectorization.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Vectorization.hpp
new file mode 100644
index 0000000000..0b8427cbe1
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_Vectorization.hpp
@@ -0,0 +1,298 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+#ifndef KOKKOS_CUDA_VECTORIZATION_HPP
+#define KOKKOS_CUDA_VECTORIZATION_HPP
+
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#ifdef KOKKOS_HAVE_CUDA
+
+#include <Kokkos_Cuda.hpp>
+
+namespace Kokkos {
+
+
+// Shuffle only makes sense on >= Kepler GPUs; it doesn't work on CPUs
+// or other GPUs.  We provide a generic definition (which is trivial
+// and doesn't do what it claims to do) because we don't actually use
+// this function unless we are on a suitable GPU, with a suitable
+// Scalar type.  (For example, in the mat-vec, the "ThreadsPerRow"
+// internal parameter depends both on the ExecutionSpace and the Scalar type,
+// and it controls whether shfl_down() gets called.)
+namespace Impl {
+
+  template< typename Scalar >
+  struct shfl_union {
+    enum {n = sizeof(Scalar)/4};
+    float fval[n];
+    KOKKOS_INLINE_FUNCTION
+    Scalar value() {
+      return *(Scalar*) fval;
+    }
+    KOKKOS_INLINE_FUNCTION
+    void operator= (Scalar& value_) {
+      float* const val_ptr = (float*) &value_;
+      for(int i=0; i<n ; i++) {
+        fval[i] = val_ptr[i];
+      }
+    }
+    KOKKOS_INLINE_FUNCTION
+    void operator= (const Scalar& value_) {
+      float* const val_ptr = (float*) &value_;
+      for(int i=0; i<n ; i++) {
+        fval[i] = val_ptr[i];
+      }
+    }
+
+  };
+}
+
+#ifdef __CUDA_ARCH__
+  #if (__CUDA_ARCH__ >= 300)
+
+    KOKKOS_INLINE_FUNCTION
+    int shfl(const int &val, const int& srcLane, const int& width ) {
+      return __shfl(val,srcLane,width);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float shfl(const float &val, const int& srcLane, const int& width ) {
+      return __shfl(val,srcLane,width);
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl(const Scalar &val, const int& srcLane, const typename Impl::enable_if< (sizeof(Scalar) == 4) , int >::type& width
+        ) {
+      Scalar tmp1 = val;
+      float tmp = *reinterpret_cast<float*>(&tmp1);
+      tmp = __shfl(tmp,srcLane,width);
+      return *reinterpret_cast<Scalar*>(&tmp);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double shfl(const double &val, const int& srcLane, const int& width) {
+      int lo = __double2loint(val);
+      int hi = __double2hiint(val);
+      lo = __shfl(lo,srcLane,width);
+      hi = __shfl(hi,srcLane,width);
+      return __hiloint2double(hi,lo);
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl(const Scalar &val, const int& srcLane, const typename Impl::enable_if< (sizeof(Scalar) == 8) ,int>::type& width) {
+      int lo = __double2loint(*reinterpret_cast<const double*>(&val));
+      int hi = __double2hiint(*reinterpret_cast<const double*>(&val));
+      lo = __shfl(lo,srcLane,width);
+      hi = __shfl(hi,srcLane,width);
+      const double tmp = __hiloint2double(hi,lo);
+      return *(reinterpret_cast<const Scalar*>(&tmp));
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl(const Scalar &val, const int& srcLane, const typename Impl::enable_if< (sizeof(Scalar) > 8) ,int>::type& width) {
+      Impl::shfl_union<Scalar> s_val;
+      Impl::shfl_union<Scalar> r_val;
+      s_val = val;
+
+      for(int i = 0; i<s_val.n; i++)
+        r_val.fval[i] = __shfl(s_val.fval[i],srcLane,width);
+      return r_val.value();
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int shfl_down(const int &val, const int& delta, const int& width) {
+      return __shfl_down(val,delta,width);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float shfl_down(const float &val, const int& delta, const int& width) {
+      return __shfl_down(val,delta,width);
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl_down(const Scalar &val, const int& delta, const typename Impl::enable_if< (sizeof(Scalar) == 4) , int >::type & width) {
+      Scalar tmp1 = val;
+      float tmp = *reinterpret_cast<float*>(&tmp1);
+      tmp = __shfl_down(tmp,delta,width);
+      return *reinterpret_cast<Scalar*>(&tmp);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double shfl_down(const double &val, const int& delta, const int& width) {
+      int lo = __double2loint(val);
+      int hi = __double2hiint(val);
+      lo = __shfl_down(lo,delta,width);
+      hi = __shfl_down(hi,delta,width);
+      return __hiloint2double(hi,lo);
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl_down(const Scalar &val, const int& delta, const typename Impl::enable_if< (sizeof(Scalar) == 8) , int >::type & width) {
+      int lo = __double2loint(*reinterpret_cast<const double*>(&val));
+      int hi = __double2hiint(*reinterpret_cast<const double*>(&val));
+      lo = __shfl_down(lo,delta,width);
+      hi = __shfl_down(hi,delta,width);
+      const double tmp = __hiloint2double(hi,lo);
+      return *(reinterpret_cast<const Scalar*>(&tmp));
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl_down(const Scalar &val, const int& delta, const typename Impl::enable_if< (sizeof(Scalar) > 8) , int >::type & width) {
+      Impl::shfl_union<Scalar> s_val;
+      Impl::shfl_union<Scalar> r_val;
+      s_val = val;
+
+      for(int i = 0; i<s_val.n; i++)
+        r_val.fval[i] = __shfl_down(s_val.fval[i],delta,width);
+      return r_val.value();
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    int shfl_up(const int &val, const int& delta, const int& width ) {
+      return __shfl_up(val,delta,width);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    float shfl_up(const float &val, const int& delta, const int& width ) {
+      return __shfl_up(val,delta,width);
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl_up(const Scalar &val, const int& delta, const typename Impl::enable_if< (sizeof(Scalar) == 4) , int >::type & width) {
+      Scalar tmp1 = val;
+      float tmp = *reinterpret_cast<float*>(&tmp1);
+      tmp = __shfl_up(tmp,delta,width);
+      return *reinterpret_cast<Scalar*>(&tmp);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    double shfl_up(const double &val, const int& delta, const int& width ) {
+      int lo = __double2loint(val);
+      int hi = __double2hiint(val);
+      lo = __shfl_up(lo,delta,width);
+      hi = __shfl_up(hi,delta,width);
+      return __hiloint2double(hi,lo);
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl_up(const Scalar &val, const int& delta, const typename Impl::enable_if< (sizeof(Scalar) == 8) , int >::type & width) {
+      int lo = __double2loint(*reinterpret_cast<const double*>(&val));
+      int hi = __double2hiint(*reinterpret_cast<const double*>(&val));
+      lo = __shfl_up(lo,delta,width);
+      hi = __shfl_up(hi,delta,width);
+      const double tmp = __hiloint2double(hi,lo);
+      return *(reinterpret_cast<const Scalar*>(&tmp));
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl_up(const Scalar &val, const int& delta, const typename Impl::enable_if< (sizeof(Scalar) > 8) , int >::type & width) {
+      Impl::shfl_union<Scalar> s_val;
+      Impl::shfl_union<Scalar> r_val;
+      s_val = val;
+
+      for(int i = 0; i<s_val.n; i++)
+        r_val.fval[i] = __shfl_up(s_val.fval[i],delta,width);
+      return r_val.value();
+    }
+
+  #else
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl(const Scalar &val, const int& srcLane, const int& width) {
+      if(width > 1) Kokkos::abort("Error: calling shfl from a device with CC<3.0.");
+      return val;
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl_down(const Scalar &val, const int& delta, const int& width) {
+      if(width > 1) Kokkos::abort("Error: calling shfl_down from a device with CC<3.0.");
+      return val;
+    }
+
+    template<typename Scalar>
+    KOKKOS_INLINE_FUNCTION
+    Scalar shfl_up(const Scalar &val, const int& delta, const int& width) {
+      if(width > 1) Kokkos::abort("Error: calling shfl_down from a device with CC<3.0.");
+      return val;
+    }
+  #endif
+#else
+    template<typename Scalar>
+    inline
+    Scalar shfl(const Scalar &val, const int& srcLane, const int& width) {
+      if(width > 1) Kokkos::abort("Error: calling shfl from a device with CC<3.0.");
+      return val;
+    }
+
+    template<typename Scalar>
+    inline
+    Scalar shfl_down(const Scalar &val, const int& delta, const int& width) {
+      if(width > 1) Kokkos::abort("Error: calling shfl_down from a device with CC<3.0.");
+      return val;
+    }
+
+    template<typename Scalar>
+    inline
+    Scalar shfl_up(const Scalar &val, const int& delta, const int& width) {
+      if(width > 1) Kokkos::abort("Error: calling shfl_down from a device with CC<3.0.");
+      return val;
+    }
+#endif
+
+
+
+}
+
+#endif // KOKKOS_HAVE_CUDA
+#endif
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_View.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_View.hpp
new file mode 100644
index 0000000000..92f6fc1f5f
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_View.hpp
@@ -0,0 +1,93 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDA_VIEW_HPP
+#define KOKKOS_CUDA_VIEW_HPP
+
+#include <Kokkos_Macros.hpp>
+
+/* only compile this file if CUDA is enabled for Kokkos */
+#ifdef KOKKOS_HAVE_CUDA
+
+#include <cstring>
+
+#include <Kokkos_HostSpace.hpp>
+#include <Kokkos_CudaSpace.hpp>
+#include <impl/Kokkos_Shape.hpp>
+#include <Kokkos_View.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+struct AssertShapeBoundsAbort< CudaSpace >
+{
+  KOKKOS_INLINE_FUNCTION
+  static void apply( const size_t /* rank */ ,
+                     const size_t /* n0 */ , const size_t /* n1 */ ,
+                     const size_t /* n2 */ , const size_t /* n3 */ ,
+                     const size_t /* n4 */ , const size_t /* n5 */ ,
+                     const size_t /* n6 */ , const size_t /* n7 */ ,
+
+                     const size_t /* arg_rank */ ,
+                     const size_t /* i0 */ , const size_t /* i1 */ ,
+                     const size_t /* i2 */ , const size_t /* i3 */ ,
+                     const size_t /* i4 */ , const size_t /* i5 */ ,
+                     const size_t /* i6 */ , const size_t /* i7 */ )
+    {
+      Kokkos::abort("Kokkos::View array bounds violation");
+    }
+};
+
+}
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif // KOKKOS_HAVE_CUDA
+#endif /* #ifndef KOKKOS_CUDA_VIEW_HPP */
+
diff --git a/lib/kokkos/core/src/Cuda/Kokkos_Cuda_abort.hpp b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_abort.hpp
new file mode 100644
index 0000000000..deb955ccd4
--- /dev/null
+++ b/lib/kokkos/core/src/Cuda/Kokkos_Cuda_abort.hpp
@@ -0,0 +1,119 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDA_ABORT_HPP
+#define KOKKOS_CUDA_ABORT_HPP
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+#include "Kokkos_Macros.hpp"
+#if defined( __CUDACC__ ) && defined( __CUDA_ARCH__ ) && defined( KOKKOS_HAVE_CUDA )
+
+#include <cuda.h>
+
+#if ! defined( CUDA_VERSION ) || ( CUDA_VERSION < 4010 )
+#error "Cuda version 4.1 or greater required"
+#endif
+
+#if ( __CUDA_ARCH__ < 200 )
+#error "Cuda device capability 2.0 or greater required"
+#endif
+
+extern "C" {
+/*  Cuda runtime function, declared in <crt/device_runtime.h>
+ *  Requires capability 2.x or better.
+ */
+extern __device__ void __assertfail(
+  const void  *message,
+  const void  *file,
+  unsigned int line,
+  const void  *function,
+  size_t       charsize);
+}
+
+namespace Kokkos {
+namespace Impl {
+
+__device__ inline
+void cuda_abort( const char * const message )
+{
+#ifndef __APPLE__
+  const char empty[] = "" ;
+
+  __assertfail( (const void *) message ,
+                (const void *) empty ,
+                (unsigned int) 0 ,
+                (const void *) empty ,
+                sizeof(char) );
+#endif
+}
+
+} // namespace Impl
+} // namespace Kokkos
+
+#else
+
+namespace Kokkos {
+namespace Impl {
+KOKKOS_INLINE_FUNCTION
+void cuda_abort( const char * const ) {}
+}
+}
+
+#endif /* #if defined( __CUDACC__ ) && defined( __CUDA_ARCH__ ) */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_CUDA )
+namespace Kokkos {
+__device__ inline
+void abort( const char * const message ) { Kokkos::Impl::cuda_abort(message); }
+}
+#endif /* defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_CUDA ) */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_CUDA_ABORT_HPP */
+
diff --git a/lib/kokkos/core/src/KokkosExp_MDRangePolicy.hpp b/lib/kokkos/core/src/KokkosExp_MDRangePolicy.hpp
new file mode 100644
index 0000000000..e813285fc7
--- /dev/null
+++ b/lib/kokkos/core/src/KokkosExp_MDRangePolicy.hpp
@@ -0,0 +1,611 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CORE_EXP_MD_RANGE_POLICY_HPP
+#define KOKKOS_CORE_EXP_MD_RANGE_POLICY_HPP
+
+#include <Kokkos_ExecPolicy.hpp>
+#include <Kokkos_Parallel.hpp>
+#include <initializer_list>
+
+#if defined(KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION) && defined(KOKKOS_HAVE_PRAGMA_IVDEP) && !defined(__CUDA_ARCH__)
+#define KOKKOS_MDRANGE_IVDEP
+#endif
+
+namespace Kokkos { namespace Experimental {
+
+enum class Iterate
+{
+  Default, // Default for the device
+  Left,    // Left indices stride fastest
+  Right,   // Right indices stride fastest
+  Flat,    // Do not tile, only valid for inner direction
+};
+
+template <typename ExecSpace>
+struct default_outer_direction
+{
+  using type = Iterate;
+  static constexpr Iterate value = Iterate::Right;
+};
+
+template <typename ExecSpace>
+struct default_inner_direction
+{
+  using type = Iterate;
+  static constexpr Iterate value = Iterate::Right;
+};
+
+
+// Iteration Pattern
+template < unsigned N
+         , Iterate OuterDir = Iterate::Default
+         , Iterate InnerDir = Iterate::Default
+         >
+struct Rank
+{
+  static_assert( N != 0u, "Kokkos Error: rank 0 undefined");
+  static_assert( N != 1u, "Kokkos Error: rank 1 is not a multi-dimensional range");
+  static_assert( N < 4u, "Kokkos Error: Unsupported rank...");
+
+  using iteration_pattern = Rank<N, OuterDir, InnerDir>;
+
+  static constexpr int rank = N;
+  static constexpr Iterate outer_direction = OuterDir;
+  static constexpr Iterate inner_direction = InnerDir;
+};
+
+
+
+// multi-dimensional iteration pattern
+template <typename... Properties>
+struct MDRangePolicy
+{
+  using range_policy = RangePolicy<Properties...>;
+
+  static_assert( !std::is_same<range_policy,void>::value
+               , "Kokkos Error: MD iteration pattern not defined" );
+
+  using iteration_pattern   = typename range_policy::iteration_pattern;
+  using work_tag            = typename range_policy::work_tag;
+
+  static constexpr int rank = iteration_pattern::rank;
+
+  static constexpr int outer_direction = static_cast<int> (
+      (iteration_pattern::outer_direction != Iterate::Default && iteration_pattern::outer_direction != Iterate::Flat)
+    ? iteration_pattern::outer_direction
+    : default_outer_direction< typename range_policy::execution_space>::value );
+
+  static constexpr int inner_direction = static_cast<int> (
+      iteration_pattern::inner_direction != Iterate::Default
+    ? iteration_pattern::inner_direction
+    : default_inner_direction< typename range_policy::execution_space>::value ) ;
+
+
+  // Ugly ugly workaround intel 14 not handling scoped enum correctly
+  static constexpr int Flat = static_cast<int>( Iterate::Flat );
+  static constexpr int Right = static_cast<int>( Iterate::Right );
+
+
+  using size_type   = typename range_policy::index_type;
+  using index_type  = typename std::make_signed<size_type>::type;
+
+
+  template <typename I>
+  MDRangePolicy( std::initializer_list<I> upper_corner )
+  {
+    static_assert( std::is_integral<I>::value, "Kokkos Error: corner defined with non-integral type" );
+
+    // TODO check size of lists equal to rank
+    // static_asserts on initializer_list.size() require c++14
+
+    //static_assert( upper_corner.size() == rank, "Kokkos Error: upper_corner has incorrect rank" );
+
+    const auto u = upper_corner.begin();
+
+    m_num_tiles = 1;
+    for (int i=0; i<rank; ++i) {
+      m_offset[i] = static_cast<index_type>(0);
+      m_dim[i]    = static_cast<index_type>(u[i]);
+      if (inner_direction != Flat) {
+        // default tile size to 4
+        m_tile[i] = 4;
+      } else {
+        m_tile[i] = 1;
+      }
+      m_tile_dim[i] = (m_dim[i] + (m_tile[i] - 1)) / m_tile[i];
+      m_num_tiles *= m_tile_dim[i];
+    }
+  }
+
+  template <typename IA, typename IB>
+  MDRangePolicy( std::initializer_list<IA> corner_a
+               , std::initializer_list<IB> corner_b
+               )
+  {
+    static_assert( std::is_integral<IA>::value, "Kokkos Error: corner A defined with non-integral type" );
+    static_assert( std::is_integral<IB>::value, "Kokkos Error: corner B defined with non-integral type" );
+
+    // TODO check size of lists equal to rank
+    // static_asserts on initializer_list.size() require c++14
+    //static_assert( corner_a.size() == rank, "Kokkos Error: corner_a has incorrect rank" );
+    //static_assert( corner_b.size() == rank, "Kokkos Error: corner_b has incorrect rank" );
+
+
+    using A = typename std::make_signed<IA>::type;
+    using B = typename std::make_signed<IB>::type;
+
+    const auto a = [=](int i) { return static_cast<A>(corner_a.begin()[i]); };
+    const auto b = [=](int i) { return static_cast<B>(corner_b.begin()[i]); };
+
+    m_num_tiles = 1;
+    for (int i=0; i<rank; ++i) {
+      m_offset[i] = static_cast<index_type>(a(i) <= b(i) ? a(i) : b(i));
+      m_dim[i]    = static_cast<index_type>(a(i) <= b(i) ? b(i) - a(i) : a(i) - b(i));
+      if (inner_direction != Flat) {
+        // default tile size to 4
+        m_tile[i] = 4;
+      } else {
+        m_tile[i] = 1;
+      }
+      m_tile_dim[i] = (m_dim[i] + (m_tile[i] - 1)) / m_tile[i];
+      m_num_tiles *= m_tile_dim[i];
+    }
+  }
+
+  template <typename IA, typename IB, typename T>
+  MDRangePolicy( std::initializer_list<IA> corner_a
+               , std::initializer_list<IB> corner_b
+               , std::initializer_list<T> tile
+               )
+  {
+    static_assert( std::is_integral<IA>::value, "Kokkos Error: corner A defined with non-integral type" );
+    static_assert( std::is_integral<IB>::value, "Kokkos Error: corner B defined with non-integral type" );
+    static_assert( std::is_integral<T>::value, "Kokkos Error: tile defined with non-integral type" );
+    static_assert( inner_direction != Flat, "Kokkos Error: tiling not support with flat iteration" );
+
+    // TODO check size of lists equal to rank
+    // static_asserts on initializer_list.size() require c++14
+    //static_assert( corner_a.size() == rank, "Kokkos Error: corner_a has incorrect rank" );
+    //static_assert( corner_b.size() == rank, "Kokkos Error: corner_b has incorrect rank" );
+    //static_assert( tile.size() == rank, "Kokkos Error: tile has incorrect rank" );
+
+    using A = typename std::make_signed<IA>::type;
+    using B = typename std::make_signed<IB>::type;
+
+    const auto a = [=](int i) { return static_cast<A>(corner_a.begin()[i]); };
+    const auto b = [=](int i) { return static_cast<B>(corner_b.begin()[i]); };
+    const auto t = tile.begin();
+
+    m_num_tiles = 1;
+    for (int i=0; i<rank; ++i) {
+      m_offset[i] = static_cast<index_type>(a(i) <= b(i) ? a(i) : b(i));
+      m_dim[i]    = static_cast<index_type>(a(i) <= b(i) ? b(i) - a(i) : a(i) - b(i));
+      m_tile[i]   = static_cast<int>(t[i] > (T)0 ? t[i] : (T)1 );
+      m_tile_dim[i] = (m_dim[i] + (m_tile[i] - 1)) / m_tile[i];
+      m_num_tiles *= m_tile_dim[i];
+    }
+  }
+
+  index_type   m_offset[rank];
+  index_type   m_dim[rank];
+  int          m_tile[rank];
+  index_type   m_tile_dim[rank];
+  size_type    m_num_tiles;       // product of tile dims
+};
+
+namespace Impl {
+
+// Serial, Threads, OpenMP
+// use enable_if to overload for Cuda
+template < typename MDRange, typename Functor, typename Enable = void >
+struct MDForFunctor
+{
+  using work_tag   = typename MDRange::work_tag;
+  using index_type = typename MDRange::index_type;
+  using size_type  = typename MDRange::size_type;
+
+  MDRange m_range;
+  Functor m_func;
+
+  KOKKOS_INLINE_FUNCTION
+  MDForFunctor( MDRange const& range, Functor const& f )
+    : m_range(range)
+    , m_func( f )
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  MDForFunctor( MDRange const& range, Functor && f )
+    : m_range(range)
+    , m_func( std::forward<Functor>(f) )
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  MDForFunctor( MDRange && range, Functor const& f )
+    : m_range( std::forward<MDRange>(range) )
+    , m_func( f )
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  MDForFunctor( MDRange && range, Functor && f )
+    : m_range( std::forward<MDRange>(range) )
+    , m_func( std::forward<Functor>(f) )
+  {}
+
+
+  KOKKOS_INLINE_FUNCTION
+  MDForFunctor( MDForFunctor const& ) = default;
+
+  KOKKOS_INLINE_FUNCTION
+  MDForFunctor& operator=( MDForFunctor const& ) = default;
+
+  KOKKOS_INLINE_FUNCTION
+  MDForFunctor( MDForFunctor && ) = default;
+
+  KOKKOS_INLINE_FUNCTION
+  MDForFunctor& operator=( MDForFunctor && ) = default;
+
+  // Rank-2, Flat, No Tag
+  template <typename Idx>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<(  std::is_integral<Idx>::value
+                          && std::is_same<void, work_tag>::value
+                          && MDRange::rank == 2
+                          && MDRange::inner_direction == MDRange::Flat
+                          )>::type
+  operator()(Idx t) const
+  {
+    if (  MDRange::outer_direction == MDRange::Right ) {
+      m_func( m_range.m_offset[0] + ( t / m_range.m_dim[1] )
+            , m_range.m_offset[1] + ( t % m_range.m_dim[1] ) );
+    } else {
+      m_func( m_range.m_offset[0] + ( t % m_range.m_dim[0] )
+            , m_range.m_offset[1] + ( t / m_range.m_dim[0] ) );
+    }
+  }
+
+  // Rank-2, Flat, Tag
+  template <typename Idx>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<(  std::is_integral<Idx>::value
+                          && !std::is_same<void, work_tag>::value
+                          && MDRange::rank == 2
+                          && MDRange::inner_direction == MDRange::Flat
+                          )>::type
+  operator()(Idx t) const
+  {
+    if (  MDRange::outer_direction == MDRange::Right ) {
+      m_func( work_tag{}, m_range.m_offset[0] + ( t / m_range.m_dim[1] )
+            , m_range.m_offset[1] + ( t % m_range.m_dim[1] ) );
+    } else {
+      m_func( work_tag{}, m_range.m_offset[0] + ( t % m_range.m_dim[0] )
+            , m_range.m_offset[1] + ( t / m_range.m_dim[0] ) );
+    }
+  }
+
+  // Rank-2, Not Flat, No Tag
+  template <typename Idx>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<(  std::is_integral<Idx>::value
+                          && std::is_same<void, work_tag>::value
+                          && MDRange::rank == 2
+                          && MDRange::inner_direction != MDRange::Flat
+                          )>::type
+  operator()(Idx t) const
+  {
+    index_type t0, t1;
+    if (  MDRange::outer_direction == MDRange::Right ) {
+      t0 = t / m_range.m_tile_dim[1];
+      t1 = t % m_range.m_tile_dim[1];
+    } else {
+      t0 = t % m_range.m_tile_dim[0];
+      t1 = t / m_range.m_tile_dim[0];
+    }
+
+    const index_type b0 = t0 * m_range.m_tile[0] + m_range.m_offset[0];
+    const index_type b1 = t1 * m_range.m_tile[1] + m_range.m_offset[1];
+
+    const index_type e0 = b0 + m_range.m_tile[0] <= (m_range.m_dim[0] + m_range.m_offset[0] ) ? b0 + m_range.m_tile[0] : ( m_range.m_dim[0] + m_range.m_offset[0] );
+    const index_type e1 = b1 + m_range.m_tile[1] <= (m_range.m_dim[1] + m_range.m_offset[1] ) ? b1 + m_range.m_tile[1] : ( m_range.m_dim[1] + m_range.m_offset[1] );
+
+    if (  MDRange::inner_direction == MDRange::Right ) {
+      for (int i0=b0; i0<e0; ++i0) {
+      #if defined(KOKKOS_MDRANGE_IVDEP)
+      #pragma ivdep
+      #endif
+      for (int i1=b1; i1<e1; ++i1) {
+        m_func( i0, i1 );
+      }}
+    } else {
+      for (int i1=b1; i1<e1; ++i1) {
+      #if defined(KOKKOS_MDRANGE_IVDEP)
+      #pragma ivdep
+      #endif
+      for (int i0=b0; i0<e0; ++i0) {
+        m_func( i0, i1 );
+      }}
+    }
+  }
+
+  // Rank-2, Not Flat, Tag
+  template <typename Idx>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<(  std::is_integral<Idx>::value
+                          && !std::is_same<void, work_tag>::value
+                          && MDRange::rank == 2
+                          && MDRange::inner_direction != MDRange::Flat
+                          )>::type
+  operator()(Idx t) const
+  {
+    work_tag tag;
+
+    index_type t0, t1;
+    if (  MDRange::outer_direction == MDRange::Right ) {
+      t0 = t / m_range.m_tile_dim[1];
+      t1 = t % m_range.m_tile_dim[1];
+    } else {
+      t0 = t % m_range.m_tile_dim[0];
+      t1 = t / m_range.m_tile_dim[0];
+    }
+
+    const index_type b0 = t0 * m_range.m_tile[0] + m_range.m_offset[0];
+    const index_type b1 = t1 * m_range.m_tile[1] + m_range.m_offset[1];
+
+    const index_type e0 = b0 + m_range.m_tile[0] <= (m_range.m_dim[0] + m_range.m_offset[0] ) ? b0 + m_range.m_tile[0] : ( m_range.m_dim[0] + m_range.m_offset[0] );
+    const index_type e1 = b1 + m_range.m_tile[1] <= (m_range.m_dim[1] + m_range.m_offset[1] ) ? b1 + m_range.m_tile[1] : ( m_range.m_dim[1] + m_range.m_offset[1] );
+
+    if (  MDRange::inner_direction == MDRange::Right ) {
+      for (int i0=b0; i0<e0; ++i0) {
+      #if defined(KOKKOS_MDRANGE_IVDEP)
+      #pragma ivdep
+      #endif
+      for (int i1=b1; i1<e1; ++i1) {
+        m_func( tag, i0, i1 );
+      }}
+    } else {
+      for (int i1=b1; i1<e1; ++i1) {
+      #if defined(KOKKOS_MDRANGE_IVDEP)
+      #pragma ivdep
+      #endif
+      for (int i0=b0; i0<e0; ++i0) {
+        m_func( tag, i0, i1 );
+      }}
+    }
+  }
+
+  //---------------------------------------------------------------------------
+
+  // Rank-3, Flat, No Tag
+  template <typename Idx>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<(  std::is_integral<Idx>::value
+                          && std::is_same<void, work_tag>::value
+                          && MDRange::rank == 3
+                          && MDRange::inner_direction == MDRange::Flat
+                          )>::type
+  operator()(Idx t) const
+  {
+    if (  MDRange::outer_direction == MDRange::Right ) {
+    const int64_t tmp_prod = m_range.m_dim[1]*m_range.m_dim[2];
+    m_func( m_range.m_offset[0] + (  t / tmp_prod )
+          , m_range.m_offset[1] + ( (t % tmp_prod) / m_range.m_dim[2] )
+          , m_range.m_offset[2] + ( (t % tmp_prod) % m_range.m_dim[2] )
+          );
+    } else {
+    const int64_t tmp_prod = m_range.m_dim[0]*m_range.m_dim[1];
+    m_func( m_range.m_offset[0] + ( (t % tmp_prod) % m_range.m_dim[0] )
+          , m_range.m_offset[1] + ( (t % tmp_prod) / m_range.m_dim[0] )
+          , m_range.m_offset[2] + (  t / tmp_prod )
+          );
+    }
+  }
+
+  // Rank-3, Flat, Tag
+  template <typename Idx>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<(  std::is_integral<Idx>::value
+                          && !std::is_same<void, work_tag>::value
+                          && MDRange::rank == 3
+                          && MDRange::inner_direction == MDRange::Flat
+                          )>::type
+  operator()(Idx t) const
+  {
+    if (  MDRange::outer_direction == MDRange::Right ) {
+      const int64_t tmp_prod = m_range.m_dim[1]*m_range.m_dim[2];
+      m_func( work_tag{}
+            , m_range.m_offset[0] + (  t / tmp_prod )
+            , m_range.m_offset[1] + ( (t % tmp_prod) / m_range.m_dim[2] )
+            , m_range.m_offset[2] + ( (t % tmp_prod) % m_range.m_dim[2] )
+            );
+    } else {
+      const int64_t tmp_prod = m_range.m_dim[0]*m_range.m_dim[1];
+      m_func( work_tag{}
+            , m_range.m_offset[0] + ( (t % tmp_prod) % m_range.m_dim[0] )
+            , m_range.m_offset[1] + ( (t % tmp_prod) / m_range.m_dim[0] )
+            , m_range.m_offset[2] + (  t / tmp_prod )
+            );
+    }
+  }
+
+  // Rank-3, Not Flat, No Tag
+  template <typename Idx>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<(  std::is_integral<Idx>::value
+                          && std::is_same<void, work_tag>::value
+                          && MDRange::rank == 3
+                          && MDRange::inner_direction != MDRange::Flat
+                          )>::type
+  operator()(Idx t) const
+  {
+    index_type t0, t1, t2;
+    if (  MDRange::outer_direction == MDRange::Right ) {
+      const index_type tmp_prod = ( m_range.m_tile_dim[1]*m_range.m_tile_dim[2]);
+      t0 = t / tmp_prod;
+      t1 = ( t % tmp_prod ) / m_range.m_tile_dim[2];
+      t2 = ( t % tmp_prod ) % m_range.m_tile_dim[2];
+    } else {
+      const index_type tmp_prod = ( m_range.m_tile_dim[0]*m_range.m_tile_dim[1]);
+      t0 = ( t % tmp_prod ) % m_range.m_tile_dim[0];
+      t1 = ( t % tmp_prod ) / m_range.m_tile_dim[0];
+      t2 = t / tmp_prod;
+    }
+
+    const index_type b0 = t0 * m_range.m_tile[0] + m_range.m_offset[0];
+    const index_type b1 = t1 * m_range.m_tile[1] + m_range.m_offset[1];
+    const index_type b2 = t2 * m_range.m_tile[2] + m_range.m_offset[2];
+
+    const index_type e0 = b0 + m_range.m_tile[0] <= (m_range.m_dim[0] + m_range.m_offset[0] ) ? b0 + m_range.m_tile[0] : ( m_range.m_dim[0] + m_range.m_offset[0] );
+    const index_type e1 = b1 + m_range.m_tile[1] <= (m_range.m_dim[1] + m_range.m_offset[1] ) ? b1 + m_range.m_tile[1] : ( m_range.m_dim[1] + m_range.m_offset[1] );
+    const index_type e2 = b2 + m_range.m_tile[2] <= (m_range.m_dim[2] + m_range.m_offset[2] ) ? b2 + m_range.m_tile[2] : ( m_range.m_dim[2] + m_range.m_offset[2] );
+
+    if (  MDRange::inner_direction == MDRange::Right ) {
+      for (int i0=b0; i0<e0; ++i0) {
+      for (int i1=b1; i1<e1; ++i1) {
+      #if defined(KOKKOS_MDRANGE_IVDEP)
+      #pragma ivdep
+      #endif
+      for (int i2=b2; i2<e2; ++i2) {
+        m_func( i0, i1, i2 );
+      }}}
+    } else {
+      for (int i2=b2; i2<e2; ++i2) {
+      for (int i1=b1; i1<e1; ++i1) {
+      #if defined(KOKKOS_MDRANGE_IVDEP)
+      #pragma ivdep
+      #endif
+      for (int i0=b0; i0<e0; ++i0) {
+        m_func( i0, i1, i2 );
+      }}}
+    }
+  }
+
+  // Rank-3, Not Flat, Tag
+  template <typename Idx>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<(  std::is_integral<Idx>::value
+                          && !std::is_same<void, work_tag>::value
+                          && MDRange::rank == 3
+                          && MDRange::inner_direction != MDRange::Flat
+                          )>::type
+  operator()(Idx t) const
+  {
+    work_tag tag;
+
+    index_type t0, t1, t2;
+    if (  MDRange::outer_direction == MDRange::Right ) {
+      const index_type tmp_prod = ( m_range.m_tile_dim[1]*m_range.m_tile_dim[2]);
+      t0 = t / tmp_prod;
+      t1 = ( t % tmp_prod ) / m_range.m_tile_dim[2];
+      t2 = ( t % tmp_prod ) % m_range.m_tile_dim[2];
+    } else {
+      const index_type tmp_prod = ( m_range.m_tile_dim[0]*m_range.m_tile_dim[1]);
+      t0 = ( t % tmp_prod ) % m_range.m_tile_dim[0];
+      t1 = ( t % tmp_prod ) / m_range.m_tile_dim[0];
+      t2 = t / tmp_prod;
+    }
+
+    const index_type b0 = t0 * m_range.m_tile[0] + m_range.m_offset[0];
+    const index_type b1 = t1 * m_range.m_tile[1] + m_range.m_offset[1];
+    const index_type b2 = t2 * m_range.m_tile[2] + m_range.m_offset[2];
+
+    const index_type e0 = b0 + m_range.m_tile[0] <= (m_range.m_dim[0] + m_range.m_offset[0] ) ? b0 + m_range.m_tile[0] : ( m_range.m_dim[0] + m_range.m_offset[0] );
+    const index_type e1 = b1 + m_range.m_tile[1] <= (m_range.m_dim[1] + m_range.m_offset[1] ) ? b1 + m_range.m_tile[1] : ( m_range.m_dim[1] + m_range.m_offset[1] );
+    const index_type e2 = b2 + m_range.m_tile[2] <= (m_range.m_dim[2] + m_range.m_offset[2] ) ? b2 + m_range.m_tile[2] : ( m_range.m_dim[2] + m_range.m_offset[2] );
+
+    if (  MDRange::inner_direction == MDRange::Right ) {
+      for (int i0=b0; i0<e0; ++i0) {
+      for (int i1=b1; i1<e1; ++i1) {
+      #if defined(KOKKOS_MDRANGE_IVDEP)
+      #pragma ivdep
+      #endif
+      for (int i2=b2; i2<e2; ++i2) {
+        m_func( tag, i0, i1, i2 );
+      }}}
+    } else {
+      for (int i2=b2; i2<e2; ++i2) {
+      for (int i1=b1; i1<e1; ++i1) {
+      #if defined(KOKKOS_MDRANGE_IVDEP)
+      #pragma ivdep
+      #endif
+      for (int i0=b0; i0<e0; ++i0) {
+        m_func( tag, i0, i1, i2 );
+      }}}
+    }
+  }
+};
+
+
+
+} // namespace Impl
+
+
+template <typename MDRange, typename Functor>
+void md_parallel_for( MDRange const& range
+                    , Functor const& f
+                    , const std::string& str = ""
+                    )
+{
+  Impl::MDForFunctor<MDRange, Functor> g(range, f);
+
+  using range_policy = typename MDRange::range_policy;
+
+  Kokkos::parallel_for( range_policy(0, range.m_num_tiles).set_chunk_size(1), g, str );
+}
+
+template <typename MDRange, typename Functor>
+void md_parallel_for( const std::string& str
+                    , MDRange const& range
+                    , Functor const& f
+                    )
+{
+  Impl::MDForFunctor<MDRange, Functor> g(range, f);
+
+  using range_policy = typename MDRange::range_policy;
+
+  Kokkos::parallel_for( range_policy(0, range.m_num_tiles).set_chunk_size(1), g, str );
+}
+
+}} // namespace Kokkos::Experimental
+
+#endif //KOKKOS_CORE_EXP_MD_RANGE_POLICY_HPP
+
diff --git a/lib/kokkos/core/src/Kokkos_Array.hpp b/lib/kokkos/core/src/Kokkos_Array.hpp
new file mode 100644
index 0000000000..038eda804f
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Array.hpp
@@ -0,0 +1,302 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_ARRAY
+#define KOKKOS_ARRAY
+
+#include <type_traits>
+#include <algorithm>
+#include <limits>
+#include <cstddef>
+
+namespace Kokkos {
+
+/**\brief  Derived from the C++17 'std::array'.
+ *         Dropping the iterator interface.
+ */
+template< class T      = void
+        , size_t N     = ~size_t(0)
+        , class Proxy  = void
+        >
+struct Array {
+private:
+  T m_elem[N];
+public:
+
+  typedef T &                                 reference ;
+  typedef typename std::add_const<T>::type &  const_reference ;
+  typedef size_t                              size_type ;
+  typedef ptrdiff_t                           difference_type ;
+  typedef T                                   value_type ;
+  typedef T *                                 pointer ;
+  typedef typename std::add_const<T>::type *  const_pointer ;
+
+  KOKKOS_INLINE_FUNCTION static constexpr size_type size() { return N ; }
+  KOKKOS_INLINE_FUNCTION static constexpr bool      empty(){ return false ; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  reference operator[]( const iType & i )
+    {
+      static_assert( std::is_integral<iType>::value , "Must be integral argument" );
+      return m_elem[i];
+    }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  const_reference operator[]( const iType & i ) const
+    {
+      static_assert( std::is_integral<iType>::value , "Must be integral argument" );
+      return m_elem[i];
+    }
+
+  KOKKOS_INLINE_FUNCTION pointer       data()       { return & m_elem[0] ; }
+  KOKKOS_INLINE_FUNCTION const_pointer data() const { return & m_elem[0] ; }
+
+  ~Array() = default ;
+  Array() = default ;
+  Array( const Array & ) = default ;
+  Array & operator = ( const Array & ) = default ;
+
+  // Some supported compilers are not sufficiently C++11 compliant
+  // for default move constructor and move assignment operator.
+  // Array( Array && ) = default ;
+  // Array & operator = ( Array && ) = default ;
+};
+
+
+template< class T , class Proxy >
+struct Array<T,0,Proxy> {
+public:
+
+  typedef typename std::add_const<T>::type &  reference ;
+  typedef typename std::add_const<T>::type &  const_reference ;
+  typedef size_t                              size_type ;
+  typedef ptrdiff_t                           difference_type ;
+  typedef typename std::add_const<T>::type    value_type ;
+  typedef typename std::add_const<T>::type *  pointer ;
+  typedef typename std::add_const<T>::type *  const_pointer ;
+
+  KOKKOS_INLINE_FUNCTION static constexpr size_type size()  { return 0 ; }
+  KOKKOS_INLINE_FUNCTION static constexpr bool      empty() { return true ; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  value_type operator[]( const iType & )
+    {
+      static_assert( std::is_integral<iType>::value , "Must be integer argument" );
+      return value_type();
+    }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  value_type operator[]( const iType & ) const
+    {
+      static_assert( std::is_integral<iType>::value , "Must be integer argument" );
+      return value_type();
+    }
+
+  KOKKOS_INLINE_FUNCTION pointer       data()       { return pointer(0) ; }
+  KOKKOS_INLINE_FUNCTION const_pointer data() const { return const_pointer(0); }
+
+  ~Array() = default ;
+  Array() = default ;
+  Array( const Array & ) = default ;
+  Array & operator = ( const Array & ) = default ;
+
+  // Some supported compilers are not sufficiently C++11 compliant
+  // for default move constructor and move assignment operator.
+  // Array( Array && ) = default ;
+  // Array & operator = ( Array && ) = default ;
+};
+
+
+template<>
+struct Array<void,~size_t(0),void>
+{
+  struct contiguous {};
+  struct strided {};
+};
+
+template< class T >
+struct Array< T , ~size_t(0) , Array<>::contiguous >
+{
+private:
+  T *    m_elem ;
+  size_t m_size ;
+public:
+
+  typedef T &                                 reference ;
+  typedef typename std::add_const<T>::type &  const_reference ;
+  typedef size_t                              size_type ;
+  typedef ptrdiff_t                           difference_type ;
+  typedef T                                   value_type ;
+  typedef T *                                 pointer ;
+  typedef typename std::add_const<T>::type *  const_pointer ;
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type size()  const { return m_size ; }
+  KOKKOS_INLINE_FUNCTION constexpr bool      empty() const { return 0 != m_size ; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  reference operator[]( const iType & i )
+    {
+      static_assert( std::is_integral<iType>::value , "Must be integral argument" );
+      return m_elem[i];
+    }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  const_reference operator[]( const iType & i ) const
+    {
+      static_assert( std::is_integral<iType>::value , "Must be integral argument" );
+      return m_elem[i];
+    }
+
+  KOKKOS_INLINE_FUNCTION pointer       data()       { return m_elem ; }
+  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem ; }
+
+  ~Array() = default ;
+  Array() = delete ;
+  Array( const Array & rhs ) = delete ;
+
+  // Some supported compilers are not sufficiently C++11 compliant
+  // for default move constructor and move assignment operator.
+  // Array( Array && rhs ) = default ;
+  // Array & operator = ( Array && rhs ) = delete ;
+
+  KOKKOS_INLINE_FUNCTION
+  Array & operator = ( const Array & rhs )
+    {
+      const size_t n = std::min( m_size , rhs.size() );
+      for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
+      return *this ;
+    }
+
+  template< size_t N , class P >
+  KOKKOS_INLINE_FUNCTION
+  Array & operator = ( const Array<T,N,P> & rhs )
+    {
+      const size_t n = std::min( m_size , rhs.size() );
+      for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
+      return *this ;
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr Array( pointer arg_ptr , size_type arg_size , size_type = 0 )
+    : m_elem(arg_ptr), m_size(arg_size) {}
+};
+
+template< class T >
+struct Array< T , ~size_t(0) , Array<>::strided >
+{
+private:
+  T *    m_elem ;
+  size_t m_size ;
+  size_t m_stride ;
+public:
+
+  typedef T &                                 reference ;
+  typedef typename std::add_const<T>::type &  const_reference ;
+  typedef size_t                              size_type ;
+  typedef ptrdiff_t                           difference_type ;
+  typedef T                                   value_type ;
+  typedef T *                                 pointer ;
+  typedef typename std::add_const<T>::type *  const_pointer ;
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type size()  const { return m_size ; }
+  KOKKOS_INLINE_FUNCTION constexpr bool      empty() const { return 0 != m_size ; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  reference operator[]( const iType & i )
+    {
+      static_assert( std::is_integral<iType>::value , "Must be integral argument" );
+      return m_elem[i*m_stride];
+    }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  const_reference operator[]( const iType & i ) const
+    {
+      static_assert( std::is_integral<iType>::value , "Must be integral argument" );
+      return m_elem[i*m_stride];
+    }
+
+  KOKKOS_INLINE_FUNCTION pointer       data()       { return m_elem ; }
+  KOKKOS_INLINE_FUNCTION const_pointer data() const { return m_elem ; }
+
+  ~Array() = default ;
+  Array()  = delete ;
+  Array( const Array & ) = delete ;
+
+
+  // Some supported compilers are not sufficiently C++11 compliant
+  // for default move constructor and move assignment operator.
+  // Array( Array && rhs ) = default ;
+  // Array & operator = ( Array && rhs ) = delete ;
+
+  KOKKOS_INLINE_FUNCTION
+  Array & operator = ( const Array & rhs )
+    {
+      const size_t n = std::min( m_size , rhs.size() );
+      for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
+      return *this ;
+    }
+
+  template< size_t N , class P >
+  KOKKOS_INLINE_FUNCTION
+  Array & operator = ( const Array<T,N,P> & rhs )
+    {
+      const size_t n = std::min( m_size , rhs.size() );
+      for ( size_t i = 0 ; i < n ; ++i ) m_elem[i] = rhs[i] ;
+      return *this ;
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr Array( pointer arg_ptr , size_type arg_size , size_type arg_stride )
+    : m_elem(arg_ptr), m_size(arg_size), m_stride(arg_stride) {}
+};
+
+} // namespace Kokkos
+
+#endif /* #ifndef KOKKOS_ARRAY */
+
diff --git a/lib/kokkos/core/src/Kokkos_Atomic.hpp b/lib/kokkos/core/src/Kokkos_Atomic.hpp
new file mode 100644
index 0000000000..6d37d69a63
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Atomic.hpp
@@ -0,0 +1,305 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/// \file Kokkos_Atomic.hpp
+/// \brief Atomic functions
+///
+/// This header file defines prototypes for the following atomic functions:
+///   - exchange
+///   - compare and exchange
+///   - add
+///
+/// Supported types include:
+///   - signed and unsigned 4 and 8 byte integers
+///   - float
+///   - double
+///
+/// They are implemented through GCC compatible intrinsics, OpenMP
+/// directives and native CUDA intrinsics.
+///
+/// Including this header file requires one of the following
+/// compilers:
+///   - NVCC (for CUDA device code only)
+///   - GCC (for host code only)
+///   - Intel (for host code only)
+///   - A compiler that supports OpenMP 3.1 (for host code only)
+
+#ifndef KOKKOS_ATOMIC_HPP
+#define KOKKOS_ATOMIC_HPP
+
+#include <Kokkos_Macros.hpp>
+#include <Kokkos_HostSpace.hpp>
+#include <impl/Kokkos_Traits.hpp>
+
+//----------------------------------------------------------------------------
+#if defined(_WIN32)
+#define KOKKOS_ATOMICS_USE_WINDOWS
+#else
+#if defined( __CUDA_ARCH__ ) && defined( KOKKOS_HAVE_CUDA )
+
+// Compiling NVIDIA device code, must use Cuda atomics:
+
+#define KOKKOS_ATOMICS_USE_CUDA
+
+#elif ! defined( KOKKOS_ATOMICS_USE_GCC ) && \
+      ! defined( KOKKOS_ATOMICS_USE_INTEL ) && \
+      ! defined( KOKKOS_ATOMICS_USE_OMP31 )
+
+// Compiling for non-Cuda atomic implementation has not been pre-selected.
+// Choose the best implementation for the detected compiler.
+// Preference: GCC, INTEL, OMP31
+
+#if defined( KOKKOS_COMPILER_GNU ) || \
+    defined( KOKKOS_COMPILER_CLANG ) || \
+    ( defined ( KOKKOS_COMPILER_NVCC ) && defined ( __GNUC__ ) )
+
+#define KOKKOS_ATOMICS_USE_GCC
+
+#elif defined( KOKKOS_COMPILER_INTEL ) || \
+      defined( KOKKOS_COMPILER_CRAYC )
+
+#define KOKKOS_ATOMICS_USE_INTEL
+
+#elif defined( _OPENMP ) && ( 201107 <= _OPENMP )
+
+#define KOKKOS_ATOMICS_USE_OMP31
+
+#else
+
+#error "KOKKOS_ATOMICS_USE : Unsupported compiler"
+
+#endif
+
+#endif /* Not pre-selected atomic implementation */
+#endif
+
+//----------------------------------------------------------------------------
+
+// Forward decalaration of functions supporting arbitrary sized atomics
+// This is necessary since Kokkos_Atomic.hpp is internally included very early
+// through Kokkos_HostSpace.hpp as well as the allocation tracker.
+#ifdef KOKKOS_HAVE_CUDA
+namespace Kokkos {
+namespace Impl {
+/// \brief Aquire a lock for the address
+///
+/// This function tries to aquire the lock for the hash value derived
+/// from the provided ptr. If the lock is successfully aquired the
+/// function returns true. Otherwise it returns false.
+__device__ inline
+bool lock_address_cuda_space(void* ptr);
+
+/// \brief Release lock for the address
+///
+/// This function releases the lock for the hash value derived
+/// from the provided ptr. This function should only be called
+/// after previously successfully aquiring a lock with
+/// lock_address.
+__device__ inline
+void unlock_address_cuda_space(void* ptr);
+}
+}
+#endif
+
+
+namespace Kokkos {
+template <typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_add(volatile T * const dest, const T src);
+
+// Atomic increment
+template<typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_increment(volatile T* a);
+
+template<typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_decrement(volatile T* a);
+}
+
+namespace Kokkos {
+
+
+inline
+const char * atomic_query_version()
+{
+#if defined( KOKKOS_ATOMICS_USE_CUDA )
+  return "KOKKOS_ATOMICS_USE_CUDA" ;
+#elif defined( KOKKOS_ATOMICS_USE_GCC )
+  return "KOKKOS_ATOMICS_USE_GCC" ;
+#elif defined( KOKKOS_ATOMICS_USE_INTEL )
+  return "KOKKOS_ATOMICS_USE_INTEL" ;
+#elif defined( KOKKOS_ATOMICS_USE_OMP31 )
+  return "KOKKOS_ATOMICS_USE_OMP31" ;
+#elif defined( KOKKOS_ATOMICS_USE_WINDOWS )
+  return "KOKKOS_ATOMICS_USE_WINDOWS";
+#endif
+}
+
+} // namespace Kokkos
+
+#ifdef _WIN32
+#include "impl/Kokkos_Atomic_Windows.hpp"
+#else
+
+//----------------------------------------------------------------------------
+// Atomic Assembly
+//
+// Implements CAS128-bit in assembly
+
+#include "impl/Kokkos_Atomic_Assembly.hpp"
+
+//----------------------------------------------------------------------------
+// Atomic exchange
+//
+// template< typename T >
+// T atomic_exchange( volatile T* const dest , const T val )
+// { T tmp = *dest ; *dest = val ; return tmp ; }
+
+#include "impl/Kokkos_Atomic_Exchange.hpp"
+
+//----------------------------------------------------------------------------
+// Atomic compare-and-exchange
+//
+// template<class T>
+// bool atomic_compare_exchange_strong(volatile T* const dest, const T compare, const T val)
+// { bool equal = compare == *dest ; if ( equal ) { *dest = val ; } return equal ; }
+
+#include "impl/Kokkos_Atomic_Compare_Exchange_Strong.hpp"
+
+//----------------------------------------------------------------------------
+// Atomic fetch and add
+//
+// template<class T>
+// T atomic_fetch_add(volatile T* const dest, const T val)
+// { T tmp = *dest ; *dest += val ; return tmp ; }
+
+#include "impl/Kokkos_Atomic_Fetch_Add.hpp"
+
+//----------------------------------------------------------------------------
+// Atomic increment
+//
+// template<class T>
+// T atomic_increment(volatile T* const dest)
+// { dest++; }
+
+#include "impl/Kokkos_Atomic_Increment.hpp"
+
+//----------------------------------------------------------------------------
+// Atomic Decrement
+//
+// template<class T>
+// T atomic_decrement(volatile T* const dest)
+// { dest--; }
+
+#include "impl/Kokkos_Atomic_Decrement.hpp"
+
+//----------------------------------------------------------------------------
+// Atomic fetch and sub
+//
+// template<class T>
+// T atomic_fetch_sub(volatile T* const dest, const T val)
+// { T tmp = *dest ; *dest -= val ; return tmp ; }
+
+#include "impl/Kokkos_Atomic_Fetch_Sub.hpp"
+
+//----------------------------------------------------------------------------
+// Atomic fetch and or
+//
+// template<class T>
+// T atomic_fetch_or(volatile T* const dest, const T val)
+// { T tmp = *dest ; *dest = tmp | val ; return tmp ; }
+
+#include "impl/Kokkos_Atomic_Fetch_Or.hpp"
+
+//----------------------------------------------------------------------------
+// Atomic fetch and and
+//
+// template<class T>
+// T atomic_fetch_and(volatile T* const dest, const T val)
+// { T tmp = *dest ; *dest = tmp & val ; return tmp ; }
+
+#include "impl/Kokkos_Atomic_Fetch_And.hpp"
+#endif /*Not _WIN32*/
+
+//----------------------------------------------------------------------------
+// Memory fence
+//
+// All loads and stores from this thread will be globally consistent before continuing
+//
+// void memory_fence() {...};
+#include "impl/Kokkos_Memory_Fence.hpp"
+
+//----------------------------------------------------------------------------
+// Provide volatile_load and safe_load
+//
+// T volatile_load(T const volatile * const ptr);
+//
+// T const& safe_load(T const * const ptr);
+// XEON PHI
+// T safe_load(T const * const ptr
+
+#include "impl/Kokkos_Volatile_Load.hpp"
+
+#ifndef _WIN32
+#include "impl/Kokkos_Atomic_Generic.hpp"
+#endif
+//----------------------------------------------------------------------------
+// This atomic-style macro should be an inlined function, not a macro
+
+#if defined( KOKKOS_COMPILER_GNU ) && !defined(__PGIC__)
+
+  #define KOKKOS_NONTEMPORAL_PREFETCH_LOAD(addr) __builtin_prefetch(addr,0,0)
+  #define KOKKOS_NONTEMPORAL_PREFETCH_STORE(addr) __builtin_prefetch(addr,1,0)
+
+#else
+
+  #define KOKKOS_NONTEMPORAL_PREFETCH_LOAD(addr) ((void)0)
+  #define KOKKOS_NONTEMPORAL_PREFETCH_STORE(addr) ((void)0)
+
+#endif
+
+//----------------------------------------------------------------------------
+
+#endif /* KOKKOS_ATOMIC_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_Complex.hpp b/lib/kokkos/core/src/Kokkos_Complex.hpp
new file mode 100644
index 0000000000..cdfa4429f0
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Complex.hpp
@@ -0,0 +1,538 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+#ifndef KOKKOS_COMPLEX_HPP
+#define KOKKOS_COMPLEX_HPP
+
+#include <Kokkos_Atomic.hpp>
+#include <complex>
+#include <iostream>
+
+namespace Kokkos {
+
+/// \class complex
+/// \brief Partial reimplementation of std::complex that works as the
+///   result of a Kokkos::parallel_reduce.
+/// \tparam RealType The type of the real and imaginary parts of the
+///   complex number.  As with std::complex, this is only defined for
+///   \c float, \c double, and <tt>long double</tt>.  The latter is
+///   currently forbidden in CUDA device kernels.
+template<class RealType>
+class complex {
+private:
+  RealType re_, im_;
+
+public:
+  //! The type of the real or imaginary parts of this complex number.
+  typedef RealType value_type;
+
+  //! Default constructor (initializes both real and imaginary parts to zero).
+  KOKKOS_INLINE_FUNCTION complex () :
+    re_ (0.0), im_ (0.0)
+  {}
+
+  //! Copy constructor.
+  KOKKOS_INLINE_FUNCTION complex (const complex<RealType>& src) :
+    re_ (src.re_), im_ (src.im_)
+  {}
+
+  //! Copy constructor from volatile.
+  KOKKOS_INLINE_FUNCTION complex (const volatile complex<RealType>& src) :
+    re_ (src.re_), im_ (src.im_)
+  {}
+
+  /// \brief Conversion constructor from std::complex.
+  ///
+  /// This constructor cannot be called in a CUDA device function,
+  /// because std::complex's methods and nonmember functions are not
+  /// marked as CUDA device functions.
+  template<class InputRealType>
+  complex (const std::complex<InputRealType>& src) :
+    re_ (std::real (src)), im_ (std::imag (src))
+  {}
+
+  /// \brief Conversion operator to std::complex.
+  ///
+  /// This operator cannot be called in a CUDA device function,
+  /// because std::complex's methods and nonmember functions are not
+  /// marked as CUDA device functions.
+  operator std::complex<RealType> () const {
+    return std::complex<RealType> (re_, im_);
+  }
+
+  /// \brief Constructor that takes just the real part, and sets the
+  ///   imaginary part to zero.
+  template<class InputRealType>
+  KOKKOS_INLINE_FUNCTION complex (const InputRealType& val) :
+    re_ (val), im_ (0.0)
+  {}
+
+  //! Constructor that takes the real and imaginary parts.
+  template<class RealType1, class RealType2>
+  KOKKOS_INLINE_FUNCTION complex (const RealType1& re, const RealType2& im) :
+    re_ (re), im_ (im)
+  {}
+
+  //! Assignment operator.
+  template<class InputRealType>
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator= (const complex<InputRealType>& src) {
+    re_ = src.re_;
+    im_ = src.im_;
+    return *this;
+  }
+
+  /// \brief Assignment operator, for volatile <tt>*this</tt> and
+  ///   nonvolatile input.
+  ///
+  /// \param src [in] Input; right-hand side of the assignment.
+  ///
+  /// This operator returns \c void instead of <tt>volatile
+  /// complex<RealType>& </tt>.  See Kokkos Issue #177 for the
+  /// explanation.  In practice, this means that you should not chain
+  /// assignments with volatile lvalues.
+  template<class InputRealType>
+  KOKKOS_INLINE_FUNCTION
+  void operator= (const complex<InputRealType>& src) volatile {
+    re_ = src.re_;
+    im_ = src.im_;
+    // We deliberately do not return anything here.  See explanation
+    // in public documentation above.
+  }
+
+  //! Assignment operator.
+  template<class InputRealType>
+  KOKKOS_INLINE_FUNCTION
+  volatile complex<RealType>& operator= (const volatile complex<InputRealType>& src) volatile {
+    re_ = src.re_;
+    im_ = src.im_;
+    return *this;
+  }
+
+  //! Assignment operator.
+  template<class InputRealType>
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator= (const volatile complex<InputRealType>& src) {
+    re_ = src.re_;
+    im_ = src.im_;
+    return *this;
+  }
+
+  //! Assignment operator (from a real number).
+  template<class InputRealType>
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator= (const InputRealType& val) {
+    re_ = val;
+    im_ = static_cast<RealType> (0.0);
+    return *this;
+  }
+
+  //! Assignment operator (from a real number).
+  template<class InputRealType>
+  KOKKOS_INLINE_FUNCTION
+  void operator= (const InputRealType& val) volatile {
+    re_ = val;
+    im_ = static_cast<RealType> (0.0);
+  }
+
+  /// \brief Assignment operator from std::complex.
+  ///
+  /// This constructor cannot be called in a CUDA device function,
+  /// because std::complex's methods and nonmember functions are not
+  /// marked as CUDA device functions.
+  template<class InputRealType>
+  complex<RealType>& operator= (const std::complex<InputRealType>& src) {
+    re_ = std::real (src);
+    im_ = std::imag (src);
+    return *this;
+  }
+
+  //! The imaginary part of this complex number.
+  KOKKOS_INLINE_FUNCTION RealType& imag () {
+    return im_;
+  }
+
+  //! The real part of this complex number.
+  KOKKOS_INLINE_FUNCTION RealType& real () {
+    return re_;
+  }
+
+  //! The imaginary part of this complex number.
+  KOKKOS_INLINE_FUNCTION const RealType imag () const {
+    return im_;
+  }
+
+  //! The real part of this complex number.
+  KOKKOS_INLINE_FUNCTION const RealType real () const {
+    return re_;
+  }
+
+  //! The imaginary part of this complex number (volatile overload).
+  KOKKOS_INLINE_FUNCTION volatile RealType& imag () volatile {
+    return im_;
+  }
+
+  //! The real part of this complex number (volatile overload).
+  KOKKOS_INLINE_FUNCTION volatile RealType& real () volatile {
+    return re_;
+  }
+
+  //! The imaginary part of this complex number (volatile overload).
+  KOKKOS_INLINE_FUNCTION const RealType imag () const volatile {
+    return im_;
+  }
+
+  //! The real part of this complex number (volatile overload).
+  KOKKOS_INLINE_FUNCTION const RealType real () const volatile {
+    return re_;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator += (const complex<RealType>& src) {
+    re_ += src.re_;
+    im_ += src.im_;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator += (const volatile complex<RealType>& src) volatile {
+    re_ += src.re_;
+    im_ += src.im_;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator += (const RealType& src) {
+    re_ += src;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator += (const volatile RealType& src) volatile {
+    re_ += src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator -= (const complex<RealType>& src) {
+    re_ -= src.re_;
+    im_ -= src.im_;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator -= (const RealType& src) {
+    re_ -= src;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator *= (const complex<RealType>& src) {
+    const RealType realPart = re_ * src.re_ - im_ * src.im_;
+    const RealType imagPart = re_ * src.im_ + im_ * src.re_;
+    re_ = realPart;
+    im_ = imagPart;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator *= (const volatile complex<RealType>& src) volatile {
+    const RealType realPart = re_ * src.re_ - im_ * src.im_;
+    const RealType imagPart = re_ * src.im_ + im_ * src.re_;
+    re_ = realPart;
+    im_ = imagPart;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator *= (const RealType& src) {
+    re_ *= src;
+    im_ *= src;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator *= (const volatile RealType& src) volatile {
+    re_ *= src;
+    im_ *= src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator /= (const complex<RealType>& y) {
+    // Scale (by the "1-norm" of y) to avoid unwarranted overflow.
+    // If the real part is +/-Inf and the imaginary part is -/+Inf,
+    // this won't change the result.
+    const RealType s = ::fabs (y.real ()) + ::fabs (y.imag ());
+
+    // If s is 0, then y is zero, so x/y == real(x)/0 + i*imag(x)/0.
+    // In that case, the relation x/y == (x/s) / (y/s) doesn't hold,
+    // because y/s is NaN.
+    if (s == 0.0) {
+      this->re_ /= s;
+      this->im_ /= s;
+    }
+    else {
+      const complex<RealType> x_scaled (this->re_ / s, this->im_ / s);
+      const complex<RealType> y_conj_scaled (y.re_ / s, -(y.im_) / s);
+      const RealType y_scaled_abs = y_conj_scaled.re_ * y_conj_scaled.re_ +
+        y_conj_scaled.im_ * y_conj_scaled.im_; // abs(y) == abs(conj(y))
+      *this = x_scaled * y_conj_scaled;
+      *this /= y_scaled_abs;
+    }
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  complex<RealType>& operator /= (const RealType& src) {
+    re_ /= src;
+    im_ /= src;
+    return *this;
+  }
+};
+
+//! Binary + operator for complex.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+complex<RealType>
+operator + (const complex<RealType>& x, const complex<RealType>& y) {
+  return complex<RealType> (x.real () + y.real (), x.imag () + y.imag ());
+}
+
+//! Unary + operator for complex.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+complex<RealType>
+operator + (const complex<RealType>& x) {
+  return x;
+}
+
+//! Binary - operator for complex.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+complex<RealType>
+operator - (const complex<RealType>& x, const complex<RealType>& y) {
+  return complex<RealType> (x.real () - y.real (), x.imag () - y.imag ());
+}
+
+//! Unary - operator for complex.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+complex<RealType>
+operator - (const complex<RealType>& x) {
+  return complex<RealType> (-x.real (), -x.imag ());
+}
+
+//! Binary * operator for complex.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+complex<RealType>
+operator * (const complex<RealType>& x, const complex<RealType>& y) {
+  return complex<RealType> (x.real () * y.real () - x.imag () * y.imag (),
+                            x.real () * y.imag () + x.imag () * y.real ());
+}
+
+/// \brief Binary * operator for std::complex and complex.
+///
+/// This function exists because GCC 4.7.2 (and perhaps other
+/// compilers) are not able to deduce that they can multiply
+/// std::complex by Kokkos::complex, by first converting std::complex
+/// to Kokkos::complex.
+///
+/// This function cannot be called in a CUDA device function, because
+/// std::complex's methods and nonmember functions are not marked as
+/// CUDA device functions.
+template<class RealType>
+complex<RealType>
+operator * (const std::complex<RealType>& x, const complex<RealType>& y) {
+  return complex<RealType> (x.real () * y.real () - x.imag () * y.imag (),
+                            x.real () * y.imag () + x.imag () * y.real ());
+}
+
+/// \brief Binary * operator for RealType times complex.
+///
+/// This function exists because the compiler doesn't know that
+/// RealType and complex<RealType> commute with respect to operator*.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+complex<RealType>
+operator * (const RealType& x, const complex<RealType>& y) {
+  return complex<RealType> (x * y.real (), x * y.imag ());
+}
+
+
+//! Imaginary part of a complex number.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+RealType imag (const complex<RealType>& x) {
+  return x.imag ();
+}
+
+//! Real part of a complex number.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+RealType real (const complex<RealType>& x) {
+  return x.real ();
+}
+
+//! Absolute value (magnitude) of a complex number.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+RealType abs (const complex<RealType>& x) {
+  // FIXME (mfh 31 Oct 2014) Scale to avoid unwarranted overflow.
+  return ::sqrt (real (x) * real (x) + imag (x) * imag (x));
+}
+
+//! Conjugate of a complex number.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+complex<RealType> conj (const complex<RealType>& x) {
+  return complex<RealType> (real (x), -imag (x));
+}
+
+
+//! Binary operator / for complex and real numbers
+template<class RealType1, class RealType2>
+KOKKOS_INLINE_FUNCTION
+complex<RealType1>
+operator / (const complex<RealType1>& x, const RealType2& y) {
+  return complex<RealType1> (real (x) / y, imag (x) / y);
+}
+
+//! Binary operator / for complex.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+complex<RealType>
+operator / (const complex<RealType>& x, const complex<RealType>& y) {
+  // Scale (by the "1-norm" of y) to avoid unwarranted overflow.
+  // If the real part is +/-Inf and the imaginary part is -/+Inf,
+  // this won't change the result.
+  const RealType s = ::fabs (real (y)) + ::fabs (imag (y));
+
+  // If s is 0, then y is zero, so x/y == real(x)/0 + i*imag(x)/0.
+  // In that case, the relation x/y == (x/s) / (y/s) doesn't hold,
+  // because y/s is NaN.
+  if (s == 0.0) {
+    return complex<RealType> (real (x) / s, imag (x) / s);
+  }
+  else {
+    const complex<RealType> x_scaled (real (x) / s, imag (x) / s);
+    const complex<RealType> y_conj_scaled (real (y) / s, -imag (y) / s);
+    const RealType y_scaled_abs = real (y_conj_scaled) * real (y_conj_scaled) +
+      imag (y_conj_scaled) * imag (y_conj_scaled); // abs(y) == abs(conj(y))
+    complex<RealType> result = x_scaled * y_conj_scaled;
+    result /= y_scaled_abs;
+    return result;
+  }
+}
+
+//! Equality operator for two complex numbers.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+bool operator == (const complex<RealType>& x, const complex<RealType>& y) {
+  return real (x) == real (y) && imag (x) == imag (y);
+}
+
+//! Equality operator for std::complex and Kokkos::complex.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+bool operator == (const std::complex<RealType>& x, const complex<RealType>& y) {
+  return std::real (x) == real (y) && std::imag (x) == imag (y);
+}
+
+//! Equality operator for complex and real number.
+template<class RealType1, class RealType2>
+KOKKOS_INLINE_FUNCTION
+bool operator == (const complex<RealType1>& x, const RealType2& y) {
+  return real (x) == y && imag (x) == static_cast<RealType1> (0.0);
+}
+
+//! Equality operator for real and complex number.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+bool operator == (const RealType& x, const complex<RealType>& y) {
+  return y == x;
+}
+
+//! Inequality operator for two complex numbers.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+bool operator != (const complex<RealType>& x, const complex<RealType>& y) {
+  return real (x) != real (y) || imag (x) != imag (y);
+}
+
+//! Inequality operator for std::complex and Kokkos::complex.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+bool operator != (const std::complex<RealType>& x, const complex<RealType>& y) {
+  return std::real (x) != real (y) || std::imag (x) != imag (y);
+}
+
+//! Inequality operator for complex and real number.
+template<class RealType1, class RealType2>
+KOKKOS_INLINE_FUNCTION
+bool operator != (const complex<RealType1>& x, const RealType2& y) {
+  return real (x) != y || imag (x) != static_cast<RealType1> (0.0);
+}
+
+//! Inequality operator for real and complex number.
+template<class RealType>
+KOKKOS_INLINE_FUNCTION
+bool operator != (const RealType& x, const complex<RealType>& y) {
+  return y != x;
+}
+
+template<class RealType>
+std::ostream& operator << (std::ostream& os, const complex<RealType>& x) {
+  const std::complex<RealType> x_std (Kokkos::real (x), Kokkos::imag (x));
+  os << x_std;
+  return os;
+}
+
+template<class RealType>
+std::ostream& operator >> (std::ostream& os, complex<RealType>& x) {
+  std::complex<RealType> x_std;
+  os >> x_std;
+  x = x_std; // only assigns on success of above
+  return os;
+}
+
+
+} // namespace Kokkos
+
+#endif // KOKKOS_COMPLEX_HPP
diff --git a/lib/kokkos/core/src/Kokkos_Concepts.hpp b/lib/kokkos/core/src/Kokkos_Concepts.hpp
new file mode 100644
index 0000000000..82a342eec0
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Concepts.hpp
@@ -0,0 +1,78 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CORE_CONCEPTS_HPP
+#define KOKKOS_CORE_CONCEPTS_HPP
+
+#include <type_traits>
+
+namespace Kokkos {
+//Schedules for Execution Policies
+struct Static {};
+struct Dynamic {};
+
+//Schedule Wrapper Type
+template<class T>
+struct Schedule
+{
+  static_assert(  std::is_same<T,Static>::value
+               || std::is_same<T,Dynamic>::value
+               , "Kokkos: Invalid Schedule<> type."
+               );
+  using schedule_type = Schedule<T>;
+  using type = T;
+};
+
+//Specify Iteration Index Type
+template<typename T>
+struct IndexType
+{
+  static_assert(std::is_integral<T>::value,"Kokkos: Invalid IndexType<>.");
+  using index_type = IndexType<T>;
+  using type = T;
+};
+
+} // namespace Kokkos
+
+#endif // KOKKOS_CORE_CONCEPTS_HPP
+
diff --git a/lib/kokkos/core/src/Kokkos_Core.hpp b/lib/kokkos/core/src/Kokkos_Core.hpp
new file mode 100644
index 0000000000..7cde4610ee
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Core.hpp
@@ -0,0 +1,174 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CORE_HPP
+#define KOKKOS_CORE_HPP
+
+//----------------------------------------------------------------------------
+// Include the execution space header files for the enabled execution spaces.
+
+#include <Kokkos_Core_fwd.hpp>
+
+#if defined( KOKKOS_HAVE_SERIAL )
+#include <Kokkos_Serial.hpp>
+#endif
+
+#if defined( KOKKOS_HAVE_OPENMP )
+#include <Kokkos_OpenMP.hpp>
+#endif
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+#include <Kokkos_Threads.hpp>
+#endif
+
+#if defined( KOKKOS_HAVE_CUDA )
+#include <Kokkos_Cuda.hpp>
+#endif
+
+#include <Kokkos_MemoryPool.hpp>
+#include <Kokkos_Pair.hpp>
+#include <Kokkos_Array.hpp>
+#include <Kokkos_View.hpp>
+#include <Kokkos_Vectorization.hpp>
+#include <Kokkos_Atomic.hpp>
+#include <Kokkos_hwloc.hpp>
+
+#ifdef KOKKOS_HAVE_CXX11
+#include <Kokkos_Complex.hpp>
+#endif
+
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+struct InitArguments {
+  int num_threads;
+  int num_numa;
+  int device_id;
+
+  InitArguments() {
+    num_threads = -1;
+    num_numa = -1;
+    device_id = -1;
+  }
+};
+
+void initialize(int& narg, char* arg[]);
+
+void initialize(const InitArguments& args = InitArguments());
+
+/** \brief  Finalize the spaces that were initialized via Kokkos::initialize */
+void finalize();
+
+/** \brief  Finalize all known execution spaces */
+void finalize_all();
+
+void fence();
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+/* Allocate memory from a memory space.
+ * The allocation is tracked in Kokkos memory tracking system, so
+ * leaked memory can be identified.
+ */
+template< class Space = typename Kokkos::DefaultExecutionSpace::memory_space >
+inline
+void * kokkos_malloc( const std::string & arg_alloc_label
+                    , const size_t arg_alloc_size )
+{
+  typedef typename Space::memory_space MemorySpace ;
+  return Impl::SharedAllocationRecord< MemorySpace >::
+    allocate_tracked( MemorySpace() , arg_alloc_label , arg_alloc_size );
+}
+
+template< class Space = typename Kokkos::DefaultExecutionSpace::memory_space >
+inline
+void * kokkos_malloc( const size_t arg_alloc_size )
+{
+  typedef typename Space::memory_space MemorySpace ;
+  return Impl::SharedAllocationRecord< MemorySpace >::
+    allocate_tracked( MemorySpace() , "no-label" , arg_alloc_size );
+}
+
+template< class Space = typename Kokkos::DefaultExecutionSpace::memory_space >
+inline
+void kokkos_free( void * arg_alloc )
+{
+  typedef typename Space::memory_space MemorySpace ;
+  return Impl::SharedAllocationRecord< MemorySpace >::
+    deallocate_tracked( arg_alloc );
+}
+
+template< class Space = typename Kokkos::DefaultExecutionSpace::memory_space >
+inline
+void * kokkos_realloc( void * arg_alloc , const size_t arg_alloc_size )
+{
+  typedef typename Space::memory_space MemorySpace ;
+  return Impl::SharedAllocationRecord< MemorySpace >::
+    reallocate_tracked( arg_alloc , arg_alloc_size );
+}
+
+} // namespace Experimental
+} // namespace Kokkos
+
+
+namespace Kokkos {
+
+using Kokkos::Experimental::kokkos_malloc ;
+using Kokkos::Experimental::kokkos_realloc ;
+using Kokkos::Experimental::kokkos_free ;
+
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif
+
diff --git a/lib/kokkos/core/src/Kokkos_Core_fwd.hpp b/lib/kokkos/core/src/Kokkos_Core_fwd.hpp
new file mode 100644
index 0000000000..e9648b59b8
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Core_fwd.hpp
@@ -0,0 +1,247 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CORE_FWD_HPP
+#define KOKKOS_CORE_FWD_HPP
+
+//----------------------------------------------------------------------------
+// Kokkos_Macros.hpp does introspection on configuration options
+// and compiler environment then sets a collection of #define macros.
+
+#include <Kokkos_Macros.hpp>
+
+//----------------------------------------------------------------------------
+// Have assumed a 64bit build (8byte pointers) throughout the code base.
+
+static_assert( sizeof(void*) == 8
+             , "Kokkos assumes 64-bit build; i.e., 8-byte pointers" );
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+struct AUTO_t {
+  KOKKOS_INLINE_FUNCTION
+  constexpr const AUTO_t & operator()() const { return *this ; }
+};
+
+namespace {
+/**\brief Token to indicate that a parameter's value is to be automatically selected */
+constexpr AUTO_t AUTO = Kokkos::AUTO_t();
+}
+
+struct InvalidType {};
+
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// Forward declarations for class inter-relationships
+
+namespace Kokkos {
+
+class HostSpace ; ///< Memory space for main process and CPU execution spaces
+
+#ifdef KOKKOS_HAVE_HBWSPACE
+namespace Experimental {
+class HBWSpace ; /// Memory space for hbw_malloc from memkind (e.g. for KNL processor)
+}
+#endif
+
+#if defined( KOKKOS_HAVE_SERIAL )
+class Serial ;    ///< Execution space main process on CPU
+#endif // defined( KOKKOS_HAVE_SERIAL )
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+class Threads ;  ///< Execution space with pthreads back-end
+#endif
+
+#if defined( KOKKOS_HAVE_OPENMP )
+class OpenMP ; ///< OpenMP execution space
+#endif
+
+#if defined( KOKKOS_HAVE_CUDA )
+class CudaSpace ;            ///< Memory space on Cuda GPU
+class CudaUVMSpace ;         ///< Memory space on Cuda GPU with UVM
+class CudaHostPinnedSpace ;  ///< Memory space on Host accessible to Cuda GPU
+class Cuda ;                 ///< Execution space for Cuda GPU
+#endif
+
+template<class ExecutionSpace, class MemorySpace>
+struct Device;
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// Set the default execution space.
+
+/// Define Kokkos::DefaultExecutionSpace as per configuration option
+/// or chosen from the enabled execution spaces in the following order:
+/// Kokkos::Cuda, Kokkos::OpenMP, Kokkos::Threads, Kokkos::Serial
+
+namespace Kokkos {
+
+#if   defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_CUDA )
+  typedef Cuda DefaultExecutionSpace ;
+#elif defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_OPENMP )
+  typedef OpenMP DefaultExecutionSpace ;
+#elif defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS )
+  typedef Threads DefaultExecutionSpace ;
+#elif defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_SERIAL )
+  typedef Serial DefaultExecutionSpace ;
+#else
+#  error "At least one of the following execution spaces must be defined in order to use Kokkos: Kokkos::Cuda, Kokkos::OpenMP, Kokkos::Serial, or Kokkos::Threads."
+#endif
+
+#if defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_OPENMP )
+  typedef OpenMP DefaultHostExecutionSpace ;
+#elif defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS )
+  typedef Threads DefaultHostExecutionSpace ;
+#elif defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_SERIAL )
+  typedef Serial DefaultHostExecutionSpace ;
+#elif defined ( KOKKOS_HAVE_OPENMP )
+  typedef OpenMP DefaultHostExecutionSpace ;
+#elif defined ( KOKKOS_HAVE_PTHREAD )
+  typedef Threads DefaultHostExecutionSpace ;
+#elif defined ( KOKKOS_HAVE_SERIAL )
+  typedef Serial DefaultHostExecutionSpace ;
+#else
+#  error "At least one of the following execution spaces must be defined in order to use Kokkos: Kokkos::OpenMP, Kokkos::Serial, or Kokkos::Threads."
+#endif
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// Detect the active execution space and define its memory space.
+// This is used to verify whether a running kernel can access
+// a given memory space.
+
+namespace Kokkos {
+namespace Impl {
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_CUDA ) && defined (KOKKOS_HAVE_CUDA)
+typedef Kokkos::CudaSpace  ActiveExecutionMemorySpace ;
+#elif defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+typedef Kokkos::HostSpace  ActiveExecutionMemorySpace ;
+#else
+typedef void ActiveExecutionMemorySpace ;
+#endif
+
+template< class ActiveSpace , class MemorySpace >
+struct VerifyExecutionCanAccessMemorySpace {
+  enum {value = 0};
+};
+
+template< class Space >
+struct VerifyExecutionCanAccessMemorySpace< Space , Space >
+{
+  enum {value = 1};
+  KOKKOS_INLINE_FUNCTION static void verify(void) {}
+  KOKKOS_INLINE_FUNCTION static void verify(const void *) {}
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+#define KOKKOS_RESTRICT_EXECUTION_TO_DATA( DATA_SPACE , DATA_PTR ) \
+  Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< \
+    Kokkos::Impl::ActiveExecutionMemorySpace , DATA_SPACE >::verify( DATA_PTR )
+
+#define KOKKOS_RESTRICT_EXECUTION_TO_( DATA_SPACE ) \
+  Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< \
+    Kokkos::Impl::ActiveExecutionMemorySpace , DATA_SPACE >::verify()
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+  void fence();
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class Functor
+        , class Policy
+        , class EnableFunctor = void 
+	      , class EnablePolicy = void
+        >
+struct FunctorPolicyExecutionSpace;
+
+//----------------------------------------------------------------------------
+/// \class ParallelFor
+/// \brief Implementation of the ParallelFor operator that has a
+///   partial specialization for the device.
+///
+/// This is an implementation detail of parallel_for.  Users should
+/// skip this and go directly to the nonmember function parallel_for.
+template< class FunctorType , class ExecPolicy , class ExecutionSpace =
+          typename Impl::FunctorPolicyExecutionSpace< FunctorType , ExecPolicy >::execution_space 
+        > class ParallelFor ;
+
+/// \class ParallelReduce
+/// \brief Implementation detail of parallel_reduce.
+///
+/// This is an implementation detail of parallel_reduce.  Users should
+/// skip this and go directly to the nonmember function parallel_reduce.
+template< class FunctorType , class ExecPolicy , class ReducerType = InvalidType, class ExecutionSpace =
+          typename Impl::FunctorPolicyExecutionSpace< FunctorType , ExecPolicy >::execution_space 
+        > class ParallelReduce ;
+
+/// \class ParallelScan
+/// \brief Implementation detail of parallel_scan.
+///
+/// This is an implementation detail of parallel_scan.  Users should
+/// skip this and go directly to the documentation of the nonmember
+/// template function Kokkos::parallel_scan.
+template< class FunctorType , class ExecPolicy , class ExecutionSapce = 
+          typename Impl::FunctorPolicyExecutionSpace< FunctorType , ExecPolicy >::execution_space 
+        > class ParallelScan ;
+
+}}
+#endif /* #ifndef KOKKOS_CORE_FWD_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_Cuda.hpp b/lib/kokkos/core/src/Kokkos_Cuda.hpp
new file mode 100644
index 0000000000..3130ee3198
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Cuda.hpp
@@ -0,0 +1,274 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDA_HPP
+#define KOKKOS_CUDA_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+
+// If CUDA execution space is enabled then use this header file.
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+#include <iosfwd>
+#include <vector>
+
+#include <Kokkos_CudaSpace.hpp>
+
+#include <Kokkos_Parallel.hpp>
+#include <Kokkos_TaskPolicy.hpp>
+#include <Kokkos_Layout.hpp>
+#include <Kokkos_ScratchSpace.hpp>
+#include <Kokkos_MemoryTraits.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+#include <KokkosExp_MDRangePolicy.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+class CudaExec ;
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/// \class Cuda
+/// \brief Kokkos Execution Space that uses CUDA to run on GPUs.
+///
+/// An "execution space" represents a parallel execution model.  It tells Kokkos
+/// how to parallelize the execution of kernels in a parallel_for or
+/// parallel_reduce.  For example, the Threads execution space uses Pthreads or
+/// C++11 threads on a CPU, the OpenMP execution space uses the OpenMP language
+/// extensions, and the Serial execution space executes "parallel" kernels
+/// sequentially.  The Cuda execution space uses NVIDIA's CUDA programming
+/// model to execute kernels in parallel on GPUs.
+class Cuda {
+public:
+  //! \name Type declarations that all Kokkos execution spaces must provide.
+  //@{
+
+  //! Tag this class as a kokkos execution space
+  typedef Cuda                  execution_space ;
+
+#if defined( KOKKOS_USE_CUDA_UVM )
+  //! This execution space's preferred memory space.
+  typedef CudaUVMSpace          memory_space ;
+#else
+  //! This execution space's preferred memory space.
+  typedef CudaSpace             memory_space ;
+#endif
+
+  //! This execution space preferred device_type
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  //! The size_type best suited for this execution space.
+  typedef memory_space::size_type  size_type ;
+
+  //! This execution space's preferred array layout.
+  typedef LayoutLeft            array_layout ;
+
+  //!
+  typedef ScratchMemorySpace< Cuda >  scratch_memory_space ;
+
+  //@}
+  //--------------------------------------------------
+  //! \name Functions that all Kokkos devices must implement.
+  //@{
+
+  /// \brief True if and only if this method is being called in a
+  ///   thread-parallel function.
+  KOKKOS_INLINE_FUNCTION static int in_parallel() {
+#if defined( __CUDA_ARCH__ )
+    return true;
+#else
+    return false;
+#endif
+  }
+
+  /** \brief  Set the device in a "sleep" state.
+   *
+   * This function sets the device in a "sleep" state in which it is
+   * not ready for work.  This may consume less resources than if the
+   * device were in an "awake" state, but it may also take time to
+   * bring the device from a sleep state to be ready for work.
+   *
+   * \return True if the device is in the "sleep" state, else false if
+   *   the device is actively working and could not enter the "sleep"
+   *   state.
+   */
+  static bool sleep();
+
+  /// \brief Wake the device from the 'sleep' state so it is ready for work.
+  ///
+  /// \return True if the device is in the "ready" state, else "false"
+  ///  if the device is actively working (which also means that it's
+  ///  awake).
+  static bool wake();
+
+  /// \brief Wait until all dispatched functors complete.
+  ///
+  /// The parallel_for or parallel_reduce dispatch of a functor may
+  /// return asynchronously, before the functor completes.  This
+  /// method does not return until all dispatched functors on this
+  /// device have completed.
+  static void fence();
+
+  //! Free any resources being consumed by the device.
+  static void finalize();
+
+  //! Has been initialized
+  static int is_initialized();
+
+  /** \brief  Return the maximum amount of concurrency.  */
+  static int concurrency();
+
+  //! Print configuration information to the given output stream.
+  static void print_configuration( std::ostream & , const bool detail = false );
+
+  //@}
+  //--------------------------------------------------
+  //! \name  Cuda space instances
+
+  ~Cuda() {}
+  Cuda();
+  explicit Cuda( const int instance_id );
+
+  Cuda( Cuda && ) = default ;
+  Cuda( const Cuda & ) = default ;
+  Cuda & operator = ( Cuda && ) = default ;
+  Cuda & operator = ( const Cuda & ) = default ;
+
+  //--------------------------------------------------------------------------
+  //! \name Device-specific functions
+  //@{
+
+  struct SelectDevice {
+    int cuda_device_id ;
+    SelectDevice() : cuda_device_id(0) {}
+    explicit SelectDevice( int id ) : cuda_device_id( id ) {}
+  };
+
+  //! Initialize, telling the CUDA run-time library which device to use.
+  static void initialize( const SelectDevice = SelectDevice()
+                        , const size_t num_instances = 1 );
+
+  /// \brief Cuda device architecture of the selected device.
+  ///
+  /// This matches the __CUDA_ARCH__ specification.
+  static size_type device_arch();
+
+  //! Query device count.
+  static size_type detect_device_count();
+
+  /** \brief  Detect the available devices and their architecture
+   *          as defined by the __CUDA_ARCH__ specification.
+   */
+  static std::vector<unsigned> detect_device_arch();
+
+  cudaStream_t cuda_stream() const { return m_stream ; }
+  int          cuda_device() const { return m_device ; }
+
+  //@}
+  //--------------------------------------------------------------------------
+
+private:
+
+  cudaStream_t m_stream ;
+  int          m_device ;
+};
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+struct VerifyExecutionCanAccessMemorySpace
+  < Kokkos::CudaSpace
+  , Kokkos::Cuda::scratch_memory_space
+  >
+{
+  enum { value = true };
+  KOKKOS_INLINE_FUNCTION static void verify( void ) { }
+  KOKKOS_INLINE_FUNCTION static void verify( const void * ) { }
+};
+
+template<>
+struct VerifyExecutionCanAccessMemorySpace
+  < Kokkos::HostSpace
+  , Kokkos::Cuda::scratch_memory_space
+  >
+{
+  enum { value = false };
+  inline static void verify( void ) { CudaSpace::access_error(); }
+  inline static void verify( const void * p ) { CudaSpace::access_error(p); }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#include <Cuda/Kokkos_CudaExec.hpp>
+#include <Cuda/Kokkos_Cuda_View.hpp>
+
+#include <Cuda/KokkosExp_Cuda_View.hpp>
+
+#include <Cuda/Kokkos_Cuda_Parallel.hpp>
+#include <Cuda/Kokkos_Cuda_Task.hpp>
+
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) */
+#endif /* #ifndef KOKKOS_CUDA_HPP */
+
+
+
diff --git a/lib/kokkos/core/src/Kokkos_CudaSpace.hpp b/lib/kokkos/core/src/Kokkos_CudaSpace.hpp
new file mode 100644
index 0000000000..cd728895d0
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_CudaSpace.hpp
@@ -0,0 +1,802 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_CUDASPACE_HPP
+#define KOKKOS_CUDASPACE_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+#include <iosfwd>
+#include <typeinfo>
+#include <string>
+
+#include <Kokkos_HostSpace.hpp>
+
+#include <Cuda/Kokkos_Cuda_abort.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/** \brief  Cuda on-device memory management */
+
+class CudaSpace {
+public:
+
+  //! Tag this class as a kokkos memory space
+  typedef CudaSpace             memory_space ;
+  typedef Kokkos::Cuda          execution_space ;
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  typedef unsigned int          size_type ;
+
+  /*--------------------------------*/
+
+  CudaSpace();
+  CudaSpace( CudaSpace && rhs ) = default ;
+  CudaSpace( const CudaSpace & rhs ) = default ;
+  CudaSpace & operator = ( CudaSpace && rhs ) = default ;
+  CudaSpace & operator = ( const CudaSpace & rhs ) = default ;
+  ~CudaSpace() = default ;
+
+  /**\brief  Allocate untracked memory in the cuda space */
+  void * allocate( const size_t arg_alloc_size ) const ;
+
+  /**\brief  Deallocate untracked memory in the cuda space */
+  void deallocate( void * const arg_alloc_ptr
+                 , const size_t arg_alloc_size ) const ;
+
+  /*--------------------------------*/
+  /** \brief  Error reporting for HostSpace attempt to access CudaSpace */
+  static void access_error();
+  static void access_error( const void * const );
+
+private:
+
+  int  m_device ; ///< Which Cuda device
+
+  // friend class Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::CudaSpace , void > ;
+};
+
+namespace Impl {
+/// \brief Initialize lock array for arbitrary size atomics.
+///
+/// Arbitrary atomics are implemented using a hash table of locks
+/// where the hash value is derived from the address of the
+/// object for which an atomic operation is performed.
+/// This function initializes the locks to zero (unset).
+void init_lock_arrays_cuda_space();
+
+/// \brief Retrieve the pointer to the lock array for arbitrary size atomics.
+///
+/// Arbitrary atomics are implemented using a hash table of locks
+/// where the hash value is derived from the address of the
+/// object for which an atomic operation is performed.
+/// This function retrieves the lock array pointer.
+/// If the array is not yet allocated it will do so.
+int* atomic_lock_array_cuda_space_ptr(bool deallocate = false);
+
+/// \brief Retrieve the pointer to the scratch array for team and thread private global memory.
+///
+/// Team and Thread private scratch allocations in
+/// global memory are aquired via locks.
+/// This function retrieves the lock array pointer.
+/// If the array is not yet allocated it will do so.
+int* scratch_lock_array_cuda_space_ptr(bool deallocate = false);
+
+/// \brief Retrieve the pointer to the scratch array for unique identifiers.
+///
+/// Unique identifiers in the range 0-Cuda::concurrency
+/// are provided via locks.
+/// This function retrieves the lock array pointer.
+/// If the array is not yet allocated it will do so.
+int* threadid_lock_array_cuda_space_ptr(bool deallocate = false);
+}
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/** \brief  Cuda memory that is accessible to Host execution space
+ *          through Cuda's unified virtual memory (UVM) runtime.
+ */
+class CudaUVMSpace {
+public:
+
+  //! Tag this class as a kokkos memory space
+  typedef CudaUVMSpace          memory_space ;
+  typedef Cuda                  execution_space ;
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+  typedef unsigned int          size_type ;
+
+  /** \brief  If UVM capability is available */
+  static bool available();
+
+  /*--------------------------------*/
+
+  CudaUVMSpace();
+  CudaUVMSpace( CudaUVMSpace && rhs ) = default ;
+  CudaUVMSpace( const CudaUVMSpace & rhs ) = default ;
+  CudaUVMSpace & operator = ( CudaUVMSpace && rhs ) = default ;
+  CudaUVMSpace & operator = ( const CudaUVMSpace & rhs ) = default ;
+  ~CudaUVMSpace() = default ;
+
+  /**\brief  Allocate untracked memory in the cuda space */
+  void * allocate( const size_t arg_alloc_size ) const ;
+
+  /**\brief  Deallocate untracked memory in the cuda space */
+  void deallocate( void * const arg_alloc_ptr
+                 , const size_t arg_alloc_size ) const ;
+
+  /*--------------------------------*/
+
+private:
+
+  int  m_device ; ///< Which Cuda device
+};
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/** \brief  Host memory that is accessible to Cuda execution space
+ *          through Cuda's host-pinned memory allocation.
+ */
+class CudaHostPinnedSpace {
+public:
+
+  //! Tag this class as a kokkos memory space
+  /** \brief  Memory is in HostSpace so use the HostSpace::execution_space */
+  typedef HostSpace::execution_space  execution_space ;
+  typedef CudaHostPinnedSpace         memory_space ;
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+  typedef unsigned int                size_type ;
+
+  /*--------------------------------*/
+
+  CudaHostPinnedSpace();
+  CudaHostPinnedSpace( CudaHostPinnedSpace && rhs ) = default ;
+  CudaHostPinnedSpace( const CudaHostPinnedSpace & rhs ) = default ;
+  CudaHostPinnedSpace & operator = ( CudaHostPinnedSpace && rhs ) = default ;
+  CudaHostPinnedSpace & operator = ( const CudaHostPinnedSpace & rhs ) = default ;
+  ~CudaHostPinnedSpace() = default ;
+
+  /**\brief  Allocate untracked memory in the space */
+  void * allocate( const size_t arg_alloc_size ) const ;
+
+  /**\brief  Deallocate untracked memory in the space */
+  void deallocate( void * const arg_alloc_ptr
+                 , const size_t arg_alloc_size ) const ;
+
+  /*--------------------------------*/
+};
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+void DeepCopyAsyncCuda( void * dst , const void * src , size_t n);
+
+template<> struct DeepCopy< CudaSpace , CudaSpace , Cuda>
+{
+  DeepCopy( void * dst , const void * src , size_t );
+  DeepCopy( const Cuda & , void * dst , const void * src , size_t );
+};
+
+template<> struct DeepCopy< CudaSpace , HostSpace , Cuda >
+{
+  DeepCopy( void * dst , const void * src , size_t );
+  DeepCopy( const Cuda & , void * dst , const void * src , size_t );
+};
+
+template<> struct DeepCopy< HostSpace , CudaSpace , Cuda >
+{
+  DeepCopy( void * dst , const void * src , size_t );
+  DeepCopy( const Cuda & , void * dst , const void * src , size_t );
+};
+
+template<class ExecutionSpace> struct DeepCopy< CudaSpace , CudaSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< CudaSpace , CudaSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace> struct DeepCopy< CudaSpace , HostSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< CudaSpace , HostSpace , Cuda>( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace>
+struct DeepCopy< HostSpace , CudaSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< HostSpace , CudaSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace>
+struct DeepCopy< CudaSpace , CudaUVMSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< CudaSpace , CudaSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace>
+struct DeepCopy< CudaSpace , CudaHostPinnedSpace , ExecutionSpace>
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< CudaSpace , HostSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+
+template<class ExecutionSpace>
+struct DeepCopy< CudaUVMSpace , CudaSpace , ExecutionSpace>
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< CudaSpace , CudaSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace>
+struct DeepCopy< CudaUVMSpace , CudaUVMSpace , ExecutionSpace>
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< CudaSpace , CudaSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace>
+struct DeepCopy< CudaUVMSpace , CudaHostPinnedSpace , ExecutionSpace>
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< CudaSpace , HostSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace> struct DeepCopy< CudaUVMSpace , HostSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< CudaSpace , HostSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+
+template<class ExecutionSpace> struct DeepCopy< CudaHostPinnedSpace , CudaSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< HostSpace , CudaSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace> struct DeepCopy< CudaHostPinnedSpace , CudaUVMSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< HostSpace , CudaSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace> struct DeepCopy< CudaHostPinnedSpace , CudaHostPinnedSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< HostSpace , HostSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace> struct DeepCopy< CudaHostPinnedSpace , HostSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< HostSpace , HostSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+
+template<class ExecutionSpace> struct DeepCopy< HostSpace , CudaUVMSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< HostSpace , CudaSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+template<class ExecutionSpace> struct DeepCopy< HostSpace , CudaHostPinnedSpace , ExecutionSpace >
+{
+  inline
+  DeepCopy( void * dst , const void * src , size_t n )
+  { (void) DeepCopy< HostSpace , HostSpace , Cuda >( dst , src , n ); }
+
+  inline
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n )
+  {
+    exec.fence();
+    DeepCopyAsyncCuda (dst,src,n);
+  }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+/** Running in CudaSpace attempting to access HostSpace: error */
+template<>
+struct VerifyExecutionCanAccessMemorySpace< Kokkos::CudaSpace , Kokkos::HostSpace >
+{
+  enum { value = false };
+  KOKKOS_INLINE_FUNCTION static void verify( void )
+    { Kokkos::abort("Cuda code attempted to access HostSpace memory"); }
+
+  KOKKOS_INLINE_FUNCTION static void verify( const void * )
+    { Kokkos::abort("Cuda code attempted to access HostSpace memory"); }
+};
+
+/** Running in CudaSpace accessing CudaUVMSpace: ok */
+template<>
+struct VerifyExecutionCanAccessMemorySpace< Kokkos::CudaSpace , Kokkos::CudaUVMSpace >
+{
+  enum { value = true };
+  KOKKOS_INLINE_FUNCTION static void verify( void ) { }
+  KOKKOS_INLINE_FUNCTION static void verify( const void * ) { }
+};
+
+/** Running in CudaSpace accessing CudaHostPinnedSpace: ok */
+template<>
+struct VerifyExecutionCanAccessMemorySpace< Kokkos::CudaSpace , Kokkos::CudaHostPinnedSpace >
+{
+  enum { value = true };
+  KOKKOS_INLINE_FUNCTION static void verify( void ) { }
+  KOKKOS_INLINE_FUNCTION static void verify( const void * ) { }
+};
+
+/** Running in CudaSpace attempting to access an unknown space: error */
+template< class OtherSpace >
+struct VerifyExecutionCanAccessMemorySpace<
+  typename enable_if< ! is_same<Kokkos::CudaSpace,OtherSpace>::value , Kokkos::CudaSpace >::type ,
+  OtherSpace >
+{
+  enum { value = false };
+  KOKKOS_INLINE_FUNCTION static void verify( void )
+    { Kokkos::abort("Cuda code attempted to access unknown Space memory"); }
+
+  KOKKOS_INLINE_FUNCTION static void verify( const void * )
+    { Kokkos::abort("Cuda code attempted to access unknown Space memory"); }
+};
+
+//----------------------------------------------------------------------------
+/** Running in HostSpace attempting to access CudaSpace */
+template<>
+struct VerifyExecutionCanAccessMemorySpace< Kokkos::HostSpace , Kokkos::CudaSpace >
+{
+  enum { value = false };
+  inline static void verify( void ) { CudaSpace::access_error(); }
+  inline static void verify( const void * p ) { CudaSpace::access_error(p); }
+};
+
+/** Running in HostSpace accessing CudaUVMSpace is OK */
+template<>
+struct VerifyExecutionCanAccessMemorySpace< Kokkos::HostSpace , Kokkos::CudaUVMSpace >
+{
+  enum { value = true };
+  inline static void verify( void ) { }
+  inline static void verify( const void * ) { }
+};
+
+/** Running in HostSpace accessing CudaHostPinnedSpace is OK */
+template<>
+struct VerifyExecutionCanAccessMemorySpace< Kokkos::HostSpace , Kokkos::CudaHostPinnedSpace >
+{
+  enum { value = true };
+  KOKKOS_INLINE_FUNCTION static void verify( void ) {}
+  KOKKOS_INLINE_FUNCTION static void verify( const void * ) {}
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template<>
+class SharedAllocationRecord< Kokkos::CudaSpace , void >
+  : public SharedAllocationRecord< void , void >
+{
+private:
+
+  friend class SharedAllocationRecord< Kokkos::CudaUVMSpace , void > ;
+
+  typedef SharedAllocationRecord< void , void >  RecordBase ;
+
+  SharedAllocationRecord( const SharedAllocationRecord & ) = delete ;
+  SharedAllocationRecord & operator = ( const SharedAllocationRecord & ) = delete ;
+
+  static void deallocate( RecordBase * );
+
+  static ::cudaTextureObject_t
+  attach_texture_object( const unsigned sizeof_alias
+                       , void * const   alloc_ptr
+                       , const size_t   alloc_size ); 
+
+  static RecordBase s_root_record ;
+
+  ::cudaTextureObject_t   m_tex_obj ;
+  const Kokkos::CudaSpace m_space ;
+
+protected:
+
+  ~SharedAllocationRecord();
+  SharedAllocationRecord() : RecordBase(), m_tex_obj(0), m_space() {}
+
+  SharedAllocationRecord( const Kokkos::CudaSpace        & arg_space
+                        , const std::string              & arg_label
+                        , const size_t                     arg_alloc_size
+                        , const RecordBase::function_type  arg_dealloc = & deallocate
+                        );
+
+public:
+
+  std::string get_label() const ;
+
+  static SharedAllocationRecord * allocate( const Kokkos::CudaSpace &  arg_space
+                                          , const std::string       &  arg_label
+                                          , const size_t               arg_alloc_size );
+
+  /**\brief  Allocate tracked memory in the space */
+  static
+  void * allocate_tracked( const Kokkos::CudaSpace & arg_space
+                         , const std::string & arg_label
+                         , const size_t arg_alloc_size );
+
+  /**\brief  Reallocate tracked memory in the space */
+  static
+  void * reallocate_tracked( void * const arg_alloc_ptr
+                           , const size_t arg_alloc_size );
+
+  /**\brief  Deallocate tracked memory in the space */
+  static
+  void deallocate_tracked( void * const arg_alloc_ptr );
+
+  static SharedAllocationRecord * get_record( void * arg_alloc_ptr );
+
+  template< typename AliasType >
+  inline
+  ::cudaTextureObject_t attach_texture_object()
+    {
+      static_assert( ( std::is_same< AliasType , int >::value ||
+                       std::is_same< AliasType , ::int2 >::value ||
+                       std::is_same< AliasType , ::int4 >::value )
+                   , "Cuda texture fetch only supported for alias types of int, ::int2, or ::int4" );
+
+      if ( m_tex_obj == 0 ) {
+        m_tex_obj = attach_texture_object( sizeof(AliasType)
+                                         , (void*) RecordBase::m_alloc_ptr
+                                         , RecordBase::m_alloc_size );
+      }
+
+      return m_tex_obj ;
+    }
+
+  template< typename AliasType >
+  inline
+  int attach_texture_object_offset( const AliasType * const ptr )
+    {
+      // Texture object is attached to the entire allocation range
+      return ptr - reinterpret_cast<AliasType*>( RecordBase::m_alloc_ptr );
+    }
+
+  static void print_records( std::ostream & , const Kokkos::CudaSpace & , bool detail = false );
+};
+
+
+template<>
+class SharedAllocationRecord< Kokkos::CudaUVMSpace , void >
+  : public SharedAllocationRecord< void , void >
+{
+private:
+
+  typedef SharedAllocationRecord< void , void >  RecordBase ;
+
+  SharedAllocationRecord( const SharedAllocationRecord & ) = delete ;
+  SharedAllocationRecord & operator = ( const SharedAllocationRecord & ) = delete ;
+
+  static void deallocate( RecordBase * );
+
+  static RecordBase s_root_record ;
+
+  ::cudaTextureObject_t      m_tex_obj ;
+  const Kokkos::CudaUVMSpace m_space ;
+
+protected:
+
+  ~SharedAllocationRecord();
+  SharedAllocationRecord() : RecordBase(), m_tex_obj(0), m_space() {}
+
+  SharedAllocationRecord( const Kokkos::CudaUVMSpace     & arg_space
+                        , const std::string              & arg_label
+                        , const size_t                     arg_alloc_size
+                        , const RecordBase::function_type  arg_dealloc = & deallocate
+                        );
+
+public:
+
+  std::string get_label() const ;
+
+  static SharedAllocationRecord * allocate( const Kokkos::CudaUVMSpace &  arg_space
+                                          , const std::string          &  arg_label
+                                          , const size_t                  arg_alloc_size
+                                          );
+
+  /**\brief  Allocate tracked memory in the space */
+  static
+  void * allocate_tracked( const Kokkos::CudaUVMSpace & arg_space
+                         , const std::string & arg_label
+                         , const size_t arg_alloc_size );
+
+  /**\brief  Reallocate tracked memory in the space */
+  static
+  void * reallocate_tracked( void * const arg_alloc_ptr
+                           , const size_t arg_alloc_size );
+
+  /**\brief  Deallocate tracked memory in the space */
+  static
+  void deallocate_tracked( void * const arg_alloc_ptr );
+
+  static SharedAllocationRecord * get_record( void * arg_alloc_ptr );
+
+
+  template< typename AliasType >
+  inline
+  ::cudaTextureObject_t attach_texture_object()
+    {
+      static_assert( ( std::is_same< AliasType , int >::value ||
+                       std::is_same< AliasType , ::int2 >::value ||
+                       std::is_same< AliasType , ::int4 >::value )
+                   , "Cuda texture fetch only supported for alias types of int, ::int2, or ::int4" );
+
+      if ( m_tex_obj == 0 ) {
+        m_tex_obj = SharedAllocationRecord< Kokkos::CudaSpace , void >::
+          attach_texture_object( sizeof(AliasType)
+                               , (void*) RecordBase::m_alloc_ptr
+                               , RecordBase::m_alloc_size );
+      }
+
+      return m_tex_obj ;
+    }
+
+  template< typename AliasType >
+  inline
+  int attach_texture_object_offset( const AliasType * const ptr )
+    {
+      // Texture object is attached to the entire allocation range
+      return ptr - reinterpret_cast<AliasType*>( RecordBase::m_alloc_ptr );
+    }
+
+  static void print_records( std::ostream & , const Kokkos::CudaUVMSpace & , bool detail = false );
+};
+
+template<>
+class SharedAllocationRecord< Kokkos::CudaHostPinnedSpace , void >
+  : public SharedAllocationRecord< void , void >
+{
+private:
+
+  typedef SharedAllocationRecord< void , void >  RecordBase ;
+
+  SharedAllocationRecord( const SharedAllocationRecord & ) = delete ;
+  SharedAllocationRecord & operator = ( const SharedAllocationRecord & ) = delete ;
+
+  static void deallocate( RecordBase * );
+
+  static RecordBase s_root_record ;
+
+  const Kokkos::CudaHostPinnedSpace m_space ;
+
+protected:
+
+  ~SharedAllocationRecord();
+  SharedAllocationRecord() : RecordBase(), m_space() {}
+
+  SharedAllocationRecord( const Kokkos::CudaHostPinnedSpace     & arg_space
+                        , const std::string              & arg_label
+                        , const size_t                     arg_alloc_size
+                        , const RecordBase::function_type  arg_dealloc = & deallocate
+                        );
+
+public:
+
+  std::string get_label() const ;
+
+  static SharedAllocationRecord * allocate( const Kokkos::CudaHostPinnedSpace &  arg_space
+                                          , const std::string          &  arg_label
+                                          , const size_t                  arg_alloc_size
+                                          );
+  /**\brief  Allocate tracked memory in the space */
+  static
+  void * allocate_tracked( const Kokkos::CudaHostPinnedSpace & arg_space
+                         , const std::string & arg_label
+                         , const size_t arg_alloc_size );
+
+  /**\brief  Reallocate tracked memory in the space */
+  static
+  void * reallocate_tracked( void * const arg_alloc_ptr
+                           , const size_t arg_alloc_size );
+
+  /**\brief  Deallocate tracked memory in the space */
+  static
+  void deallocate_tracked( void * const arg_alloc_ptr );
+
+
+  static SharedAllocationRecord * get_record( void * arg_alloc_ptr );
+
+  static void print_records( std::ostream & , const Kokkos::CudaHostPinnedSpace & , bool detail = false );
+};
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) */
+#endif /* #define KOKKOS_CUDASPACE_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_ExecPolicy.hpp b/lib/kokkos/core/src/Kokkos_ExecPolicy.hpp
new file mode 100644
index 0000000000..5834fc04db
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_ExecPolicy.hpp
@@ -0,0 +1,570 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXECPOLICY_HPP
+#define KOKKOS_EXECPOLICY_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_StaticAssert.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <impl/Kokkos_Tags.hpp>
+#include <impl/Kokkos_AnalyzePolicy.hpp>
+#include <Kokkos_Concepts.hpp>
+#include <iostream>
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+/** \brief  Execution policy for work over a range of an integral type.
+ *
+ * Valid template argument options:
+ *
+ *  With a specified execution space:
+ *    < ExecSpace , WorkTag , { IntConst | IntType } >
+ *    < ExecSpace , WorkTag , void >
+ *    < ExecSpace , { IntConst | IntType } , void >
+ *    < ExecSpace , void , void >
+ *
+ *  With the default execution space:
+ *    < WorkTag , { IntConst | IntType } , void >
+ *    < WorkTag , void , void >
+ *    < { IntConst | IntType } , void , void >
+ *    < void , void , void >
+ *
+ *  IntType  is a fundamental integral type
+ *  IntConst is an Impl::integral_constant< IntType , Blocking >
+ *
+ *  Blocking is the granularity of partitioning the range among threads.
+ */
+template<class ... Properties>
+class RangePolicy
+  : public Impl::PolicyTraits<Properties ... >
+{
+private:
+
+  typedef Impl::PolicyTraits<Properties ... > traits;
+
+  typename traits::execution_space m_space ;
+  typename traits::index_type  m_begin ;
+  typename traits::index_type  m_end ;
+  typename traits::index_type  m_granularity ;
+  typename traits::index_type  m_granularity_mask ;
+public:
+
+  //! Tag this class as an execution policy
+  typedef RangePolicy execution_policy;
+  typedef typename traits::index_type member_type ;
+
+  KOKKOS_INLINE_FUNCTION const typename traits::execution_space & space() const { return m_space ; }
+  KOKKOS_INLINE_FUNCTION member_type begin() const { return m_begin ; }
+  KOKKOS_INLINE_FUNCTION member_type end()   const { return m_end ; }
+
+
+  //TODO: find a better workaround for Clangs weird instantiation order
+  // This thing is here because of an instantiation error, where the RangePolicy is inserted into FunctorValue Traits, which
+  // tries decltype on the operator. It tries to do this even though the first argument of parallel for clearly doesn't match.
+  void operator()(const int&) const {}
+
+  RangePolicy(const RangePolicy&) = default;
+  RangePolicy(RangePolicy&&) = default;
+
+  inline RangePolicy() : m_space(), m_begin(0), m_end(0) {}
+
+  /** \brief  Total range */
+  inline
+  RangePolicy( const typename traits::execution_space & work_space
+             , const member_type work_begin
+             , const member_type work_end
+             )
+    : m_space( work_space )
+    , m_begin( work_begin < work_end ? work_begin : 0 )
+    , m_end(   work_begin < work_end ? work_end : 0 )
+    , m_granularity(0)
+    , m_granularity_mask(0)
+    {
+      set_auto_chunk_size();
+    }
+
+  /** \brief  Total range */
+  inline
+  RangePolicy( const member_type work_begin
+             , const member_type work_end
+             )
+    : RangePolicy( typename traits::execution_space()
+                 , work_begin , work_end )
+    {}
+
+  public:
+
+     /** \brief return chunk_size */
+     inline member_type chunk_size() const {
+       return m_granularity;
+     }
+
+     /** \brief set chunk_size to a discrete value*/
+     inline RangePolicy set_chunk_size(int chunk_size_) const {
+       RangePolicy p = *this;
+       p.m_granularity = chunk_size_;
+       p.m_granularity_mask = p.m_granularity - 1;
+       return p;
+     }
+
+  private:
+     /** \brief finalize chunk_size if it was set to AUTO*/
+     inline void set_auto_chunk_size() {
+
+       typename traits::index_type concurrency = traits::execution_space::concurrency();
+       if( concurrency==0 ) concurrency=1;
+
+       if(m_granularity > 0) {
+         if(!Impl::is_integral_power_of_two( m_granularity ))
+           Kokkos::abort("RangePolicy blocking granularity must be power of two" );
+       }
+
+
+       member_type new_chunk_size = 1;
+       while(new_chunk_size*100*concurrency < m_end-m_begin)
+         new_chunk_size *= 2;
+       if(new_chunk_size < 128) {
+         new_chunk_size = 1;
+         while( (new_chunk_size*40*concurrency < m_end-m_begin ) && (new_chunk_size<128) )
+           new_chunk_size*=2;
+       }
+       m_granularity = new_chunk_size;
+       m_granularity_mask = m_granularity - 1;
+     }
+
+  public:
+  /** \brief  Subrange for a partition's rank and size.
+   *
+   *  Typically used to partition a range over a group of threads.
+   */
+  struct WorkRange {
+    typedef typename RangePolicy::work_tag     work_tag ;
+    typedef typename RangePolicy::member_type  member_type ;
+
+    KOKKOS_INLINE_FUNCTION member_type begin() const { return m_begin ; }
+    KOKKOS_INLINE_FUNCTION member_type end()   const { return m_end ; }
+
+    /** \brief  Subrange for a partition's rank and size.
+     *
+     *  Typically used to partition a range over a group of threads.
+     */
+    KOKKOS_INLINE_FUNCTION
+    WorkRange( const RangePolicy & range
+             , const int part_rank
+             , const int part_size
+             )
+      : m_begin(0), m_end(0)
+      {
+        if ( part_size ) {
+
+          // Split evenly among partitions, then round up to the granularity.
+          const member_type work_part =
+            ( ( ( ( range.end() - range.begin() ) + ( part_size - 1 ) ) / part_size )
+              + range.m_granularity_mask ) & ~member_type(range.m_granularity_mask);
+
+          m_begin = range.begin() + work_part * part_rank ;
+          m_end   = m_begin       + work_part ;
+
+          if ( range.end() < m_begin ) m_begin = range.end() ;
+          if ( range.end() < m_end )   m_end   = range.end() ;
+        }
+      }
+  private:
+     member_type m_begin ;
+     member_type m_end ;
+     WorkRange();
+     WorkRange & operator = ( const WorkRange & );
+
+  };
+};
+
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+namespace Impl {
+
+
+template< class ExecSpace, class ... Properties>
+class TeamPolicyInternal: public Impl::PolicyTraits<Properties ... > {
+private:
+  typedef Impl::PolicyTraits<Properties ... > traits;
+
+public:
+
+  //----------------------------------------
+  /** \brief  Query maximum team size for a given functor.
+   *
+   *  This size takes into account execution space concurrency limitations and
+   *  scratch memory space limitations for reductions, team reduce/scan, and
+   *  team shared memory.
+   */
+  template< class FunctorType >
+  static int team_size_max( const FunctorType & );
+
+  /** \brief  Query recommended team size for a given functor.
+   *
+   *  This size takes into account execution space concurrency limitations and
+   *  scratch memory space limitations for reductions, team reduce/scan, and
+   *  team shared memory.
+   */
+  template< class FunctorType >
+  static int team_size_recommended( const FunctorType & );
+
+  template< class FunctorType >
+  static int team_size_recommended( const FunctorType & , const int&);
+  //----------------------------------------
+  /** \brief  Construct policy with the given instance of the execution space */
+  TeamPolicyInternal( const typename traits::execution_space & , int league_size_request , int team_size_request , int vector_length_request = 1 );
+
+  TeamPolicyInternal( const typename traits::execution_space & , int league_size_request , const Kokkos::AUTO_t & , int vector_length_request = 1 );
+
+  /** \brief  Construct policy with the default instance of the execution space */
+  TeamPolicyInternal( int league_size_request , int team_size_request , int vector_length_request = 1 );
+
+  TeamPolicyInternal( int league_size_request , const Kokkos::AUTO_t & , int vector_length_request = 1 );
+
+/*  TeamPolicyInternal( int league_size_request , int team_size_request );
+
+  TeamPolicyInternal( int league_size_request , const Kokkos::AUTO_t & );*/
+
+  /** \brief  The actual league size (number of teams) of the policy.
+   *
+   *  This may be smaller than the requested league size due to limitations
+   *  of the execution space.
+   */
+  KOKKOS_INLINE_FUNCTION int league_size() const ;
+
+  /** \brief  The actual team size (number of threads per team) of the policy.
+   *
+   *  This may be smaller than the requested team size due to limitations
+   *  of the execution space.
+   */
+  KOKKOS_INLINE_FUNCTION int team_size() const ;
+
+  inline typename traits::index_type chunk_size() const ;
+
+  inline TeamPolicyInternal set_chunk_size(int chunk_size) const ;
+
+  /** \brief  Parallel execution of a functor calls the functor once with
+   *          each member of the execution policy.
+   */
+  struct member_type {
+
+    /** \brief  Handle to the currently executing team shared scratch memory */
+    KOKKOS_INLINE_FUNCTION
+    typename traits::execution_space::scratch_memory_space team_shmem() const ;
+
+    /** \brief  Rank of this team within the league of teams */
+    KOKKOS_INLINE_FUNCTION int league_rank() const ;
+
+    /** \brief  Number of teams in the league */
+    KOKKOS_INLINE_FUNCTION int league_size() const ;
+
+    /** \brief  Rank of this thread within this team */
+    KOKKOS_INLINE_FUNCTION int team_rank() const ;
+
+    /** \brief  Number of threads in this team */
+    KOKKOS_INLINE_FUNCTION int team_size() const ;
+
+    /** \brief  Barrier among the threads of this team */
+    KOKKOS_INLINE_FUNCTION void team_barrier() const ;
+
+    /** \brief  Intra-team reduction. Returns join of all values of the team members. */
+    template< class JoinOp >
+    KOKKOS_INLINE_FUNCTION
+    typename JoinOp::value_type team_reduce( const typename JoinOp::value_type
+                                           , const JoinOp & ) const ;
+
+    /** \brief  Intra-team exclusive prefix sum with team_rank() ordering.
+     *
+     *  The highest rank thread can compute the reduction total as
+     *    reduction_total = dev.team_scan( value ) + value ;
+     */
+    template< typename Type >
+    KOKKOS_INLINE_FUNCTION Type team_scan( const Type & value ) const ;
+
+    /** \brief  Intra-team exclusive prefix sum with team_rank() ordering
+     *          with intra-team non-deterministic ordering accumulation.
+     *
+     *  The global inter-team accumulation value will, at the end of the
+     *  league's parallel execution, be the scan's total.
+     *  Parallel execution ordering of the league's teams is non-deterministic.
+     *  As such the base value for each team's scan operation is similarly
+     *  non-deterministic.
+     */
+    template< typename Type >
+    KOKKOS_INLINE_FUNCTION Type team_scan( const Type & value , Type * const global_accum ) const ;
+  };
+};
+}
+
+namespace Impl {
+  struct PerTeamValue {
+    int value;
+    PerTeamValue(int arg);
+  };
+
+  struct PerThreadValue {
+    int value;
+    PerThreadValue(int arg);
+  };
+}
+
+Impl::PerTeamValue PerTeam(const int& arg);
+Impl::PerThreadValue PerThread(const int& arg);
+
+
+/** \brief  Execution policy for parallel work over a league of teams of threads.
+ *
+ *  The work functor is called for each thread of each team such that
+ *  the team's member threads are guaranteed to be concurrent.
+ *
+ *  The team's threads have access to team shared scratch memory and
+ *  team collective operations.
+ *
+ *  If the WorkTag is non-void then the first calling argument of the
+ *  work functor's parentheses operator is 'const WorkTag &'.
+ *  This allows a functor to have multiple work member functions.
+ *
+ *  Order of template arguments does not matter, since the implementation
+ *  uses variadic templates. Each and any of the template arguments can
+ *  be omitted.
+ *
+ *  Possible Template arguments and there default values:
+ *    ExecutionSpace (DefaultExecutionSpace): where to execute code. Must be enabled.
+ *    WorkTag (none): Tag which is used as the first argument for the functor operator.
+ *    Schedule<Type> (Schedule<Static>): Scheduling Policy (Dynamic, or Static).
+ *    IndexType<Type> (IndexType<ExecutionSpace::size_type>: Integer Index type used to iterate over the Index space.
+ */
+template< class ... Properties>
+class TeamPolicy: public
+  Impl::TeamPolicyInternal<
+     typename Impl::PolicyTraits<Properties ... >::execution_space,
+     Properties ...> {
+  typedef Impl::TeamPolicyInternal<
+       typename Impl::PolicyTraits<Properties ... >::execution_space,
+       Properties ...> internal_policy;
+
+  typedef Impl::PolicyTraits<Properties ... > traits;
+
+public:
+  typedef TeamPolicy execution_policy;
+
+  TeamPolicy& operator = (const TeamPolicy&) = default;
+
+  /** \brief  Construct policy with the given instance of the execution space */
+  TeamPolicy( const typename traits::execution_space & , int league_size_request , int team_size_request , int vector_length_request = 1 )
+    : internal_policy(typename traits::execution_space(),league_size_request,team_size_request, vector_length_request) {}
+
+  TeamPolicy( const typename traits::execution_space & , int league_size_request , const Kokkos::AUTO_t & , int vector_length_request = 1 )
+    : internal_policy(typename traits::execution_space(),league_size_request,Kokkos::AUTO(), vector_length_request) {}
+
+  /** \brief  Construct policy with the default instance of the execution space */
+  TeamPolicy( int league_size_request , int team_size_request , int vector_length_request = 1 )
+    : internal_policy(league_size_request,team_size_request, vector_length_request) {}
+
+  TeamPolicy( int league_size_request , const Kokkos::AUTO_t & , int vector_length_request = 1 )
+    : internal_policy(league_size_request,Kokkos::AUTO(), vector_length_request) {}
+
+/*  TeamPolicy( int league_size_request , int team_size_request  )
+    : internal_policy(league_size_request,team_size_request) {}
+
+  TeamPolicy( int league_size_request , const Kokkos::AUTO_t &  )
+    : internal_policy(league_size_request,Kokkos::AUTO()) {}*/
+
+private:
+  TeamPolicy(const internal_policy& p):internal_policy(p) {}
+public:
+
+  inline TeamPolicy set_chunk_size(int chunk) const {
+    return TeamPolicy(internal_policy::set_chunk_size(chunk));
+  };
+
+  inline TeamPolicy set_scratch_size(const int& level, const Impl::PerTeamValue& per_team) const {
+    return TeamPolicy(internal_policy::set_scratch_size(level,per_team));
+  };
+  inline TeamPolicy set_scratch_size(const int& level, const Impl::PerThreadValue& per_thread) const {
+    return TeamPolicy(internal_policy::set_scratch_size(level,per_thread));
+  };
+  inline TeamPolicy set_scratch_size(const int& level, const Impl::PerTeamValue& per_team, const Impl::PerThreadValue& per_thread) const {
+    return TeamPolicy(internal_policy::set_scratch_size(level, per_team, per_thread));
+  };
+  inline TeamPolicy set_scratch_size(const int& level, const Impl::PerThreadValue& per_thread, const Impl::PerTeamValue& per_team) const {
+    return TeamPolicy(internal_policy::set_scratch_size(level, per_team, per_thread));
+  };
+
+};
+
+} // namespace Kokkos
+
+namespace Kokkos {
+
+namespace Impl {
+
+template<typename iType, class TeamMemberType>
+struct TeamThreadRangeBoundariesStruct {
+private:
+
+  KOKKOS_INLINE_FUNCTION static
+  iType ibegin( const iType & arg_begin
+              , const iType & arg_end
+              , const iType & arg_rank
+              , const iType & arg_size
+              )
+    {
+      return arg_begin + ( ( arg_end - arg_begin + arg_size - 1 ) / arg_size ) * arg_rank ;
+    }
+
+  KOKKOS_INLINE_FUNCTION static
+  iType iend( const iType & arg_begin
+            , const iType & arg_end
+            , const iType & arg_rank
+            , const iType & arg_size
+            )
+    {
+      const iType end_ = arg_begin + ( ( arg_end - arg_begin + arg_size - 1 ) / arg_size ) * ( arg_rank + 1 );
+      return end_ < arg_end ? end_ : arg_end ;
+    }
+
+public:
+
+  typedef iType index_type;
+  const iType start;
+  const iType end;
+  enum {increment = 1};
+  const TeamMemberType& thread;
+
+  KOKKOS_INLINE_FUNCTION
+  TeamThreadRangeBoundariesStruct( const TeamMemberType& arg_thread
+                                , const iType& arg_end
+                                )
+    : start( ibegin( 0 , arg_end , arg_thread.team_rank() , arg_thread.team_size() ) )
+    , end(   iend(   0 , arg_end , arg_thread.team_rank() , arg_thread.team_size() ) )
+    , thread( arg_thread )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  TeamThreadRangeBoundariesStruct( const TeamMemberType& arg_thread
+                                , const iType& arg_begin
+                                , const iType& arg_end
+                                )
+    : start( ibegin( arg_begin , arg_end , arg_thread.team_rank() , arg_thread.team_size() ) )
+    , end(   iend(   arg_begin , arg_end , arg_thread.team_rank() , arg_thread.team_size() ) )
+    , thread( arg_thread )
+    {}
+};
+
+  template<typename iType, class TeamMemberType>
+  struct ThreadVectorRangeBoundariesStruct {
+    typedef iType index_type;
+    enum {start = 0};
+    const iType end;
+    enum {increment = 1};
+
+    KOKKOS_INLINE_FUNCTION
+    ThreadVectorRangeBoundariesStruct (const TeamMemberType& thread, const iType& count):
+      end( count )
+    {}
+  };
+
+  template<class TeamMemberType>
+  struct ThreadSingleStruct {
+    const TeamMemberType& team_member;
+    KOKKOS_INLINE_FUNCTION
+    ThreadSingleStruct(const TeamMemberType& team_member_):team_member(team_member_){}
+  };
+
+  template<class TeamMemberType>
+  struct VectorSingleStruct {
+    const TeamMemberType& team_member;
+    KOKKOS_INLINE_FUNCTION
+    VectorSingleStruct(const TeamMemberType& team_member_):team_member(team_member_){}
+  };
+} // namespace Impl
+
+/** \brief  Execution policy for parallel work over a threads within a team.
+ *
+ *  The range is split over all threads in a team. The Mapping scheme depends on the architecture.
+ *  This policy is used together with a parallel pattern as a nested layer within a kernel launched
+ *  with the TeamPolicy. This variant expects a single count. So the range is (0,count].
+ */
+template<typename iType, class TeamMemberType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,TeamMemberType> TeamThreadRange(const TeamMemberType&, const iType& count);
+
+/** \brief  Execution policy for parallel work over a threads within a team.
+ *
+ *  The range is split over all threads in a team. The Mapping scheme depends on the architecture.
+ *  This policy is used together with a parallel pattern as a nested layer within a kernel launched
+ *  with the TeamPolicy. This variant expects a begin and end. So the range is (begin,end].
+ */
+template<typename iType, class TeamMemberType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,TeamMemberType> TeamThreadRange(const TeamMemberType&, const iType& begin, const iType& end);
+
+/** \brief  Execution policy for a vector parallel loop.
+ *
+ *  The range is split over all vector lanes in a thread. The Mapping scheme depends on the architecture.
+ *  This policy is used together with a parallel pattern as a nested layer within a kernel launched
+ *  with the TeamPolicy. This variant expects a single count. So the range is (0,count].
+ */
+template<typename iType, class TeamMemberType>
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadVectorRangeBoundariesStruct<iType,TeamMemberType> ThreadVectorRange(const TeamMemberType&, const iType& count);
+
+} // namespace Kokkos
+
+
+#endif /* #define KOKKOS_EXECPOLICY_HPP */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/core/src/Kokkos_HBWSpace.hpp b/lib/kokkos/core/src/Kokkos_HBWSpace.hpp
new file mode 100644
index 0000000000..e02689b0f9
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_HBWSpace.hpp
@@ -0,0 +1,312 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_HBWSPACE_HPP
+#define KOKKOS_HBWSPACE_HPP
+
+
+#include <Kokkos_HostSpace.hpp>
+#include <impl/Kokkos_HBWAllocators.hpp>
+
+/*--------------------------------------------------------------------------*/
+#ifdef KOKKOS_HAVE_HBWSPACE
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+/// \brief Initialize lock array for arbitrary size atomics.
+///
+/// Arbitrary atomics are implemented using a hash table of locks
+/// where the hash value is derived from the address of the
+/// object for which an atomic operation is performed.
+/// This function initializes the locks to zero (unset).
+void init_lock_array_hbw_space();
+
+/// \brief Aquire a lock for the address
+///
+/// This function tries to aquire the lock for the hash value derived
+/// from the provided ptr. If the lock is successfully aquired the
+/// function returns true. Otherwise it returns false.
+bool lock_address_hbw_space(void* ptr);
+
+/// \brief Release lock for the address
+///
+/// This function releases the lock for the hash value derived
+/// from the provided ptr. This function should only be called
+/// after previously successfully aquiring a lock with
+/// lock_address.
+void unlock_address_hbw_space(void* ptr);
+
+} // namespace Impl
+} // neamspace Experimental
+} // namespace Kokkos
+
+namespace Kokkos {
+namespace Experimental {
+
+/// \class HBWSpace
+/// \brief Memory management for host memory.
+///
+/// HBWSpace is a memory space that governs host memory.  "Host"
+/// memory means the usual CPU-accessible memory.
+class HBWSpace {
+public:
+
+  //! Tag this class as a kokkos memory space
+  typedef HBWSpace  memory_space ;
+  typedef size_t     size_type ;
+
+  /// \typedef execution_space
+  /// \brief Default execution space for this memory space.
+  ///
+  /// Every memory space has a default execution space.  This is
+  /// useful for things like initializing a View (which happens in
+  /// parallel using the View's default execution space).
+#if defined( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_OPENMP )
+  typedef Kokkos::OpenMP   execution_space ;
+#elif defined( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS )
+  typedef Kokkos::Threads  execution_space ;
+#elif defined( KOKKOS_HAVE_OPENMP )
+  typedef Kokkos::OpenMP   execution_space ;
+#elif defined( KOKKOS_HAVE_PTHREAD )
+  typedef Kokkos::Threads  execution_space ;
+#elif defined( KOKKOS_HAVE_SERIAL )
+  typedef Kokkos::Serial   execution_space ;
+#else
+#  error "At least one of the following host execution spaces must be defined: Kokkos::OpenMP, Kokkos::Serial, or Kokkos::Threads.  You might be seeing this message if you disabled the Kokkos::Serial device explicitly using the Kokkos_ENABLE_Serial:BOOL=OFF CMake option, but did not enable any of the other host execution space devices."
+#endif
+
+  //! This memory space preferred device_type
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  /*--------------------------------*/
+  /* Functions unique to the HBWSpace */
+  static int in_parallel();
+
+  static void register_in_parallel( int (*)() );
+
+  /*--------------------------------*/
+
+  /**\brief  Default memory space instance */
+  HBWSpace();
+  HBWSpace( const HBWSpace & rhs ) = default ;
+  HBWSpace & operator = ( const HBWSpace & ) = default ;
+  ~HBWSpace() = default ;
+
+  /**\brief  Non-default memory space instance to choose allocation mechansim, if available */
+
+  enum AllocationMechanism { STD_MALLOC , POSIX_MEMALIGN , POSIX_MMAP , INTEL_MM_ALLOC };
+
+  explicit
+  HBWSpace( const AllocationMechanism & );
+
+  /**\brief  Allocate untracked memory in the space */
+  void * allocate( const size_t arg_alloc_size ) const ;
+
+  /**\brief  Deallocate untracked memory in the space */
+  void deallocate( void * const arg_alloc_ptr 
+                 , const size_t arg_alloc_size ) const ;
+
+private:
+
+  AllocationMechanism  m_alloc_mech ;
+
+  friend class Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void > ;
+};
+
+} // namespace Experimental
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template<>
+class SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >
+  : public SharedAllocationRecord< void , void >
+{
+private:
+
+  friend Kokkos::Experimental::HBWSpace ;
+
+  typedef SharedAllocationRecord< void , void >  RecordBase ;
+
+  SharedAllocationRecord( const SharedAllocationRecord & ) = delete ;
+  SharedAllocationRecord & operator = ( const SharedAllocationRecord & ) = delete ;
+
+  static void deallocate( RecordBase * );
+
+  /**\brief  Root record for tracked allocations from this HBWSpace instance */
+  static RecordBase s_root_record ;
+
+  const Kokkos::Experimental::HBWSpace m_space ;
+
+protected:
+
+  ~SharedAllocationRecord();
+  SharedAllocationRecord() = default ;
+
+  SharedAllocationRecord( const Kokkos::Experimental::HBWSpace        & arg_space
+                        , const std::string              & arg_label
+                        , const size_t                     arg_alloc_size
+                        , const RecordBase::function_type  arg_dealloc = & deallocate
+                        );
+
+public:
+
+  inline
+  std::string get_label() const
+    {
+      return std::string( RecordBase::head()->m_label );
+    }
+
+  KOKKOS_INLINE_FUNCTION static
+  SharedAllocationRecord * allocate( const Kokkos::Experimental::HBWSpace &  arg_space
+                                   , const std::string       &  arg_label
+                                   , const size_t               arg_alloc_size
+                                   )
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      return new SharedAllocationRecord( arg_space , arg_label , arg_alloc_size );
+#else
+      return (SharedAllocationRecord *) 0 ;
+#endif
+    }
+
+  /**\brief  Allocate tracked memory in the space */
+  static
+  void * allocate_tracked( const Kokkos::Experimental::HBWSpace & arg_space
+                         , const std::string & arg_label
+                         , const size_t arg_alloc_size );
+
+  /**\brief  Reallocate tracked memory in the space */
+  static
+  void * reallocate_tracked( void * const arg_alloc_ptr
+                           , const size_t arg_alloc_size );
+
+  /**\brief  Deallocate tracked memory in the space */
+  static
+  void deallocate_tracked( void * const arg_alloc_ptr );
+
+
+  static SharedAllocationRecord * get_record( void * arg_alloc_ptr );
+
+  static void print_records( std::ostream & , const Kokkos::Experimental::HBWSpace & , bool detail = false );
+};
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+
+template<class ExecutionSpace>
+struct DeepCopy<Experimental::HBWSpace,Experimental::HBWSpace,ExecutionSpace> {
+  DeepCopy( void * dst , const void * src , size_t n ) {
+    memcpy( dst , src , n );
+  }
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n ) {
+    exec.fence();
+    memcpy( dst , src , n );
+  }
+};
+
+template<class ExecutionSpace>
+struct DeepCopy<HostSpace,Experimental::HBWSpace,ExecutionSpace> {
+  DeepCopy( void * dst , const void * src , size_t n ) {
+    memcpy( dst , src , n );
+  }
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n ) {
+    exec.fence();
+    memcpy( dst , src , n );
+  }
+};
+
+template<class ExecutionSpace>
+struct DeepCopy<Experimental::HBWSpace,HostSpace,ExecutionSpace> {
+  DeepCopy( void * dst , const void * src , size_t n ) {
+    memcpy( dst , src , n );
+  }
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n ) {
+    exec.fence();
+    memcpy( dst , src , n );
+  }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+struct VerifyExecutionCanAccessMemorySpace< Kokkos::HostSpace , Kokkos::Experimental::HBWSpace >
+{
+  enum { value = true };
+  inline static void verify( void ) { }
+  inline static void verify( const void * ) { }
+};
+
+template<>
+struct VerifyExecutionCanAccessMemorySpace< Kokkos::Experimental::HBWSpace , Kokkos::HostSpace >
+{
+  enum { value = true };
+  inline static void verify( void ) { }
+  inline static void verify( const void * ) { }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+#endif
+#endif /* #define KOKKOS_HBWSPACE_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_HostSpace.hpp b/lib/kokkos/core/src/Kokkos_HostSpace.hpp
new file mode 100644
index 0000000000..5fe686559a
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_HostSpace.hpp
@@ -0,0 +1,275 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_HOSTSPACE_HPP
+#define KOKKOS_HOSTSPACE_HPP
+
+#include <cstring>
+#include <string>
+#include <iosfwd>
+#include <typeinfo>
+
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_MemoryTraits.hpp>
+
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_Error.hpp>
+
+#include <impl/KokkosExp_SharedAlloc.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+/// \brief Initialize lock array for arbitrary size atomics.
+///
+/// Arbitrary atomics are implemented using a hash table of locks
+/// where the hash value is derived from the address of the
+/// object for which an atomic operation is performed.
+/// This function initializes the locks to zero (unset).
+void init_lock_array_host_space();
+
+/// \brief Aquire a lock for the address
+///
+/// This function tries to aquire the lock for the hash value derived
+/// from the provided ptr. If the lock is successfully aquired the
+/// function returns true. Otherwise it returns false.
+bool lock_address_host_space(void* ptr);
+
+/// \brief Release lock for the address
+///
+/// This function releases the lock for the hash value derived
+/// from the provided ptr. This function should only be called
+/// after previously successfully aquiring a lock with
+/// lock_address.
+void unlock_address_host_space(void* ptr);
+
+} // namespace Impl
+} // namespace Kokkos
+
+namespace Kokkos {
+
+/// \class HostSpace
+/// \brief Memory management for host memory.
+///
+/// HostSpace is a memory space that governs host memory.  "Host"
+/// memory means the usual CPU-accessible memory.
+class HostSpace {
+public:
+
+  //! Tag this class as a kokkos memory space
+  typedef HostSpace  memory_space ;
+  typedef size_t     size_type ;
+
+  /// \typedef execution_space
+  /// \brief Default execution space for this memory space.
+  ///
+  /// Every memory space has a default execution space.  This is
+  /// useful for things like initializing a View (which happens in
+  /// parallel using the View's default execution space).
+#if defined( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_OPENMP )
+  typedef Kokkos::OpenMP   execution_space ;
+#elif defined( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS )
+  typedef Kokkos::Threads  execution_space ;
+#elif defined( KOKKOS_HAVE_OPENMP )
+  typedef Kokkos::OpenMP   execution_space ;
+#elif defined( KOKKOS_HAVE_PTHREAD )
+  typedef Kokkos::Threads  execution_space ;
+#elif defined( KOKKOS_HAVE_SERIAL )
+  typedef Kokkos::Serial   execution_space ;
+#else
+#  error "At least one of the following host execution spaces must be defined: Kokkos::OpenMP, Kokkos::Serial, or Kokkos::Threads.  You might be seeing this message if you disabled the Kokkos::Serial device explicitly using the Kokkos_ENABLE_Serial:BOOL=OFF CMake option, but did not enable any of the other host execution space devices."
+#endif
+
+  //! This memory space preferred device_type
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  /*--------------------------------*/
+  /* Functions unique to the HostSpace */
+  static int in_parallel();
+
+  static void register_in_parallel( int (*)() );
+
+  /*--------------------------------*/
+
+  /**\brief  Default memory space instance */
+  HostSpace();
+  HostSpace( HostSpace && rhs ) = default ;
+  HostSpace( const HostSpace & rhs ) = default ;
+  HostSpace & operator = ( HostSpace && ) = default ;
+  HostSpace & operator = ( const HostSpace & ) = default ;
+  ~HostSpace() = default ;
+
+  /**\brief  Non-default memory space instance to choose allocation mechansim, if available */
+
+  enum AllocationMechanism { STD_MALLOC , POSIX_MEMALIGN , POSIX_MMAP , INTEL_MM_ALLOC };
+
+  explicit
+  HostSpace( const AllocationMechanism & );
+
+  /**\brief  Allocate untracked memory in the space */
+  void * allocate( const size_t arg_alloc_size ) const ;
+
+  /**\brief  Deallocate untracked memory in the space */
+  void deallocate( void * const arg_alloc_ptr 
+                 , const size_t arg_alloc_size ) const ;
+
+private:
+
+  AllocationMechanism  m_alloc_mech ;
+
+  friend class Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::HostSpace , void > ;
+};
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template<>
+class SharedAllocationRecord< Kokkos::HostSpace , void >
+  : public SharedAllocationRecord< void , void >
+{
+private:
+
+  friend Kokkos::HostSpace ;
+
+  typedef SharedAllocationRecord< void , void >  RecordBase ;
+
+  SharedAllocationRecord( const SharedAllocationRecord & ) = delete ;
+  SharedAllocationRecord & operator = ( const SharedAllocationRecord & ) = delete ;
+
+  static void deallocate( RecordBase * );
+
+  /**\brief  Root record for tracked allocations from this HostSpace instance */
+  static RecordBase s_root_record ;
+
+  const Kokkos::HostSpace m_space ;
+
+protected:
+
+  ~SharedAllocationRecord();
+  SharedAllocationRecord() = default ;
+
+  SharedAllocationRecord( const Kokkos::HostSpace        & arg_space
+                        , const std::string              & arg_label
+                        , const size_t                     arg_alloc_size
+                        , const RecordBase::function_type  arg_dealloc = & deallocate
+                        );
+
+public:
+
+  inline
+  std::string get_label() const
+    {
+      return std::string( RecordBase::head()->m_label );
+    }
+
+  KOKKOS_INLINE_FUNCTION static
+  SharedAllocationRecord * allocate( const Kokkos::HostSpace &  arg_space
+                                   , const std::string       &  arg_label
+                                   , const size_t               arg_alloc_size
+                                   )
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      return new SharedAllocationRecord( arg_space , arg_label , arg_alloc_size );
+#else
+      return (SharedAllocationRecord *) 0 ;
+#endif
+    }
+
+  /**\brief  Allocate tracked memory in the space */
+  static
+  void * allocate_tracked( const Kokkos::HostSpace & arg_space
+                         , const std::string & arg_label
+                         , const size_t arg_alloc_size );
+
+  /**\brief  Reallocate tracked memory in the space */
+  static
+  void * reallocate_tracked( void * const arg_alloc_ptr
+                           , const size_t arg_alloc_size );
+
+  /**\brief  Deallocate tracked memory in the space */
+  static
+  void deallocate_tracked( void * const arg_alloc_ptr );
+
+
+  static SharedAllocationRecord * get_record( void * arg_alloc_ptr );
+
+  static void print_records( std::ostream & , const Kokkos::HostSpace & , bool detail = false );
+};
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class DstSpace, class SrcSpace, class ExecutionSpace = typename DstSpace::execution_space> struct DeepCopy ;
+
+template<class ExecutionSpace>
+struct DeepCopy<HostSpace,HostSpace,ExecutionSpace> {
+  DeepCopy( void * dst , const void * src , size_t n ) {
+    memcpy( dst , src , n );
+  }
+  DeepCopy( const ExecutionSpace& exec, void * dst , const void * src , size_t n ) {
+    exec.fence();
+    memcpy( dst , src , n );
+  }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+
+#endif /* #define KOKKOS_HOSTSPACE_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_Layout.hpp b/lib/kokkos/core/src/Kokkos_Layout.hpp
new file mode 100644
index 0000000000..c77c33703b
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Layout.hpp
@@ -0,0 +1,233 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/// \file Kokkos_Layout.hpp
+/// \brief Declaration of various \c MemoryLayout options.
+
+#ifndef KOKKOS_LAYOUT_HPP
+#define KOKKOS_LAYOUT_HPP
+
+#include <stddef.h>
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+namespace Kokkos {
+
+enum { ARRAY_LAYOUT_MAX_RANK = 8 };
+
+//----------------------------------------------------------------------------
+/// \struct LayoutLeft
+/// \brief Memory layout tag indicating left-to-right (Fortran scheme)
+///   striding of multi-indices.
+///
+/// This is an example of a \c MemoryLayout template parameter of
+/// View.  The memory layout describes how View maps from a
+/// multi-index (i0, i1, ..., ik) to a memory location.  
+///
+/// "Layout left" indicates a mapping where the leftmost index i0
+/// refers to contiguous access, and strides increase for dimensions
+/// going right from there (i1, i2, ...).  This layout imitates how
+/// Fortran stores multi-dimensional arrays.  For the special case of
+/// a two-dimensional array, "layout left" is also called "column
+/// major."
+struct LayoutLeft {
+  //! Tag this class as a kokkos array layout
+  typedef LayoutLeft array_layout ;
+
+  size_t dimension[ ARRAY_LAYOUT_MAX_RANK ];
+
+  LayoutLeft( LayoutLeft const & ) = default ;
+  LayoutLeft( LayoutLeft && ) = default ;
+  LayoutLeft & operator = ( LayoutLeft const & ) = default ;
+  LayoutLeft & operator = ( LayoutLeft && ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr
+  LayoutLeft( size_t N0 = 0 , size_t N1 = 0 , size_t N2 = 0 , size_t N3 = 0
+            , size_t N4 = 0 , size_t N5 = 0 , size_t N6 = 0 , size_t N7 = 0 )
+    : dimension { N0 , N1 , N2 , N3 , N4 , N5 , N6 , N7 } {}
+};
+
+//----------------------------------------------------------------------------
+/// \struct LayoutRight
+/// \brief Memory layout tag indicating right-to-left (C or
+///   lexigraphical scheme) striding of multi-indices.
+///
+/// This is an example of a \c MemoryLayout template parameter of
+/// View.  The memory layout describes how View maps from a
+/// multi-index (i0, i1, ..., ik) to a memory location.  
+///
+/// "Right layout" indicates a mapping where the rightmost index ik
+/// refers to contiguous access, and strides increase for dimensions
+/// going left from there.  This layout imitates how C stores
+/// multi-dimensional arrays.  For the special case of a
+/// two-dimensional array, "layout right" is also called "row major."
+struct LayoutRight {
+  //! Tag this class as a kokkos array layout
+  typedef LayoutRight array_layout ;
+
+  size_t dimension[ ARRAY_LAYOUT_MAX_RANK ];
+
+  LayoutRight( LayoutRight const & ) = default ;
+  LayoutRight( LayoutRight && ) = default ;
+  LayoutRight & operator = ( LayoutRight const & ) = default ;
+  LayoutRight & operator = ( LayoutRight && ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr
+  LayoutRight( size_t N0 = 0 , size_t N1 = 0 , size_t N2 = 0 , size_t N3 = 0
+             , size_t N4 = 0 , size_t N5 = 0 , size_t N6 = 0 , size_t N7 = 0 )
+    : dimension { N0 , N1 , N2 , N3 , N4 , N5 , N6 , N7 } {}
+};
+
+//----------------------------------------------------------------------------
+/// \struct LayoutStride
+/// \brief  Memory layout tag indicated arbitrarily strided
+///         multi-index mapping into contiguous memory.
+struct LayoutStride {
+
+  //! Tag this class as a kokkos array layout
+  typedef LayoutStride array_layout ;
+
+  size_t dimension[ ARRAY_LAYOUT_MAX_RANK ] ;
+  size_t stride[ ARRAY_LAYOUT_MAX_RANK ] ; 
+
+  /** \brief  Compute strides from ordered dimensions.
+   *
+   *  Values of order uniquely form the set [0..rank)
+   *  and specify ordering of the dimensions.
+   *  Order = {0,1,2,...} is LayoutLeft
+   *  Order = {...,2,1,0} is LayoutRight
+   */
+  template< typename iTypeOrder , typename iTypeDimen >
+  KOKKOS_INLINE_FUNCTION static
+  LayoutStride order_dimensions( int const rank
+                               , iTypeOrder const * const order
+                               , iTypeDimen const * const dimen )
+    {
+      LayoutStride tmp ;
+      // Verify valid rank order:
+      int check_input = ARRAY_LAYOUT_MAX_RANK < rank ? 0 : int( 1 << rank ) - 1 ;
+      for ( int r = 0 ; r < ARRAY_LAYOUT_MAX_RANK ; ++r ) {
+        tmp.dimension[r] = 0 ;
+        tmp.stride[r]    = 0 ;
+        check_input &= ~int( 1 << order[r] );
+      }
+      if ( 0 == check_input ) {
+        size_t n = 1 ;
+        for ( int r = 0 ; r < rank ; ++r ) {
+          tmp.stride[ order[r] ] = n ;
+          n *= ( dimen[order[r]] );
+          tmp.dimension[r] = dimen[r];
+        }
+      }
+      return tmp ;
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr
+  LayoutStride( size_t N0 = 0 , size_t S0 = 0
+              , size_t N1 = 0 , size_t S1 = 0
+              , size_t N2 = 0 , size_t S2 = 0
+              , size_t N3 = 0 , size_t S3 = 0
+              , size_t N4 = 0 , size_t S4 = 0
+              , size_t N5 = 0 , size_t S5 = 0
+              , size_t N6 = 0 , size_t S6 = 0
+              , size_t N7 = 0 , size_t S7 = 0
+              )
+    : dimension { N0 , N1 , N2 , N3 , N4 , N5 , N6 , N7 }
+    , stride    { S0 , S1 , S2 , S3 , S4 , S5 , S6 , S7 }
+    {}
+};
+
+//----------------------------------------------------------------------------
+/// \struct LayoutTileLeft
+/// \brief Memory layout tag indicating left-to-right (Fortran scheme)
+///   striding of multi-indices by tiles.
+///
+/// This is an example of a \c MemoryLayout template parameter of
+/// View.  The memory layout describes how View maps from a
+/// multi-index (i0, i1, ..., ik) to a memory location.  
+///
+/// "Tiled layout" indicates a mapping to contiguously stored
+/// <tt>ArgN0</tt> by <tt>ArgN1</tt> tiles for the rightmost two
+/// dimensions.  Indices are LayoutLeft within each tile, and the
+/// tiles themselves are arranged using LayoutLeft.  Note that the
+/// dimensions <tt>ArgN0</tt> and <tt>ArgN1</tt> of the tiles must be
+/// compile-time constants.  This speeds up index calculations.  If
+/// both tile dimensions are powers of two, Kokkos can optimize
+/// further.
+template < unsigned ArgN0 , unsigned ArgN1 ,
+           bool IsPowerOfTwo = ( Impl::is_integral_power_of_two(ArgN0) &&
+                                 Impl::is_integral_power_of_two(ArgN1) )
+         >
+struct LayoutTileLeft {
+
+  static_assert( Impl::is_integral_power_of_two(ArgN0) &&
+                 Impl::is_integral_power_of_two(ArgN1)
+               , "LayoutTileLeft must be given power-of-two tile dimensions" );
+
+  //! Tag this class as a kokkos array layout
+  typedef LayoutTileLeft<ArgN0,ArgN1,IsPowerOfTwo> array_layout ;
+
+  enum { N0 = ArgN0 };
+  enum { N1 = ArgN1 };
+
+  size_t dimension[ ARRAY_LAYOUT_MAX_RANK ] ;
+
+  LayoutTileLeft( LayoutTileLeft const & ) = default ;
+  LayoutTileLeft( LayoutTileLeft && ) = default ;
+  LayoutTileLeft & operator = ( LayoutTileLeft const & ) = default ;
+  LayoutTileLeft & operator = ( LayoutTileLeft && ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr
+  LayoutTileLeft( size_t argN0 = 0 , size_t argN1 = 0 , size_t argN2 = 0 , size_t argN3 = 0
+                , size_t argN4 = 0 , size_t argN5 = 0 , size_t argN6 = 0 , size_t argN7 = 0
+                )
+    : dimension { argN0 , argN1 , argN2 , argN3 , argN4 , argN5 , argN6 , argN7 } {}
+};
+
+} // namespace Kokkos
+
+#endif // #ifndef KOKKOS_LAYOUT_HPP
+
diff --git a/lib/kokkos/core/src/Kokkos_Macros.hpp b/lib/kokkos/core/src/Kokkos_Macros.hpp
new file mode 100644
index 0000000000..7d1e59af5e
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Macros.hpp
@@ -0,0 +1,470 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_MACROS_HPP
+#define KOKKOS_MACROS_HPP
+
+//----------------------------------------------------------------------------
+/** Pick up configure/build options via #define macros:
+ *
+ *  KOKKOS_HAVE_CUDA                Kokkos::Cuda execution and memory spaces
+ *  KOKKOS_HAVE_PTHREAD             Kokkos::Threads execution space
+ *  KOKKOS_HAVE_QTHREAD             Kokkos::Qthread execution space
+ *  KOKKOS_HAVE_OPENMP              Kokkos::OpenMP  execution space
+ *  KOKKOS_HAVE_HWLOC               HWLOC library is available
+ *  KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK    insert array bounds checks, is expensive!
+ *  KOKKOS_HAVE_CXX11               enable C++11 features
+ *
+ *  KOKKOS_HAVE_MPI                 negotiate MPI/execution space interactions
+ *
+ *  KOKKOS_USE_CUDA_UVM             Use CUDA UVM for Cuda memory space
+ */
+
+#ifndef KOKKOS_DONT_INCLUDE_CORE_CONFIG_H
+#include <KokkosCore_config.h>
+#endif
+
+//----------------------------------------------------------------------------
+/** Pick up compiler specific #define macros:
+ *
+ *  Macros for known compilers evaluate to an integral version value
+ *
+ *  KOKKOS_COMPILER_NVCC
+ *  KOKKOS_COMPILER_GNU
+ *  KOKKOS_COMPILER_INTEL
+ *  KOKKOS_COMPILER_IBM
+ *  KOKKOS_COMPILER_CRAYC
+ *  KOKKOS_COMPILER_APPLECC
+ *  KOKKOS_COMPILER_CLANG
+ *  KOKKOS_COMPILER_PGI
+ *
+ *  Macros for which compiler extension to use for atomics on intrinsice types
+ *
+ *  KOKKOS_ATOMICS_USE_CUDA
+ *  KOKKOS_ATOMICS_USE_GNU
+ *  KOKKOS_ATOMICS_USE_INTEL
+ *  KOKKOS_ATOMICS_USE_OPENMP31
+ *
+ *  A suite of 'KOKKOS_HAVE_PRAGMA_...' are defined for internal use.
+ *
+ *  Macros for marking functions to run in an execution space:
+ *
+ *  KOKKOS_FUNCTION
+ *  KOKKOS_INLINE_FUNCTION        request compiler to inline
+ *  KOKKOS_FORCEINLINE_FUNCTION   force compiler to inline, use with care!
+ */
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_CUDA ) && defined( __CUDACC__ )
+
+/*  Compiling with a CUDA compiler.
+ *
+ *  Include <cuda.h> to pick up the CUDA_VERSION macro defined as:
+ *    CUDA_VERSION = ( MAJOR_VERSION * 1000 ) + ( MINOR_VERSION * 10 )
+ *
+ *  When generating device code the __CUDA_ARCH__ macro is defined as:
+ *    __CUDA_ARCH__ = ( MAJOR_CAPABILITY * 100 ) + ( MINOR_CAPABILITY * 10 )
+ */
+
+#include <cuda_runtime.h>
+#include <cuda.h>
+
+#if ! defined( CUDA_VERSION )
+#error "#include <cuda.h> did not define CUDA_VERSION"
+#endif
+
+#if ( CUDA_VERSION < 6050 )
+// CUDA supports (inofficially) C++11 in device code starting with
+// version 6.5. This includes auto type and device code internal
+// lambdas.
+#error "Cuda version 6.5 or greater required"
+#endif
+
+#if defined( __CUDA_ARCH__ ) && ( __CUDA_ARCH__ < 300 )
+/*  Compiling with CUDA compiler for device code. */
+#error "Cuda device capability >= 3.0 is required"
+#endif
+
+#ifdef KOKKOS_CUDA_USE_LAMBDA
+#if ( CUDA_VERSION < 7000 )
+// CUDA supports C++11 lambdas generated in host code to be given
+// to the device starting with version 7.5. But the release candidate (7.5.6)
+// still identifies as 7.0
+#error "Cuda version 7.5 or greater required for host-to-device Lambda support"
+#endif
+#if ( CUDA_VERSION < 8000 )
+#define KOKKOS_LAMBDA [=]__device__
+#else
+#define KOKKOS_LAMBDA [=]__host__ __device__
+#endif
+#define KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA 1
+#endif
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) && defined( __CUDACC__ ) */
+
+
+#if defined(KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+   // Cuda version 8.0 still needs the functor wrapper
+   #if (KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA /* && (CUDA_VERSION < 8000) */ )
+      #define KOKKOS_IMPL_NEED_FUNCTOR_WRAPPER
+   #endif
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* Language info: C++, CUDA, OPENMP */
+
+#if defined( __CUDA_ARCH__ ) && defined( KOKKOS_HAVE_CUDA )
+  // Compiling Cuda code to 'ptx'
+
+  #define KOKKOS_FORCEINLINE_FUNCTION  __device__  __host__  __forceinline__
+  #define KOKKOS_INLINE_FUNCTION       __device__  __host__  inline
+  #define KOKKOS_FUNCTION              __device__  __host__
+
+#endif /* #if defined( __CUDA_ARCH__ ) */
+
+#if defined( _OPENMP )
+
+  /*  Compiling with OpenMP.
+   *  The value of _OPENMP is an integer value YYYYMM
+   *  where YYYY and MM are the year and month designation
+   *  of the supported OpenMP API version.
+   */
+
+#endif /* #if defined( _OPENMP ) */
+
+/*--------------------------------------------------------------------------*/
+/* Mapping compiler built-ins to KOKKOS_COMPILER_*** macros */
+
+#if defined( __NVCC__ )
+  // NVIDIA compiler is being used.
+  // Code is parsed and separated into host and device code.
+  // Host code is compiled again with another compiler.
+  // Device code is compile to 'ptx'.
+  #define KOKKOS_COMPILER_NVCC __NVCC__
+
+#else
+#if defined( KOKKOS_HAVE_CXX11 ) && ! defined( KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA )
+    // CUDA (including version 6.5) does not support giving lambdas as
+    // arguments to global functions. Thus its not currently possible
+    // to dispatch lambdas from the host.
+    #define KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA 1
+  #endif
+#endif /* #if defined( __NVCC__ ) */
+
+#if defined( KOKKOS_HAVE_CXX11 ) && !defined (KOKKOS_LAMBDA)
+  #define KOKKOS_LAMBDA [=]
+#endif
+
+#if ! defined( __CUDA_ARCH__ ) /* Not compiling Cuda code to 'ptx'. */
+
+/* Intel compiler for host code */
+
+#if defined( __INTEL_COMPILER )
+  #define KOKKOS_COMPILER_INTEL __INTEL_COMPILER
+#elif defined( __ICC )
+  // Old define
+  #define KOKKOS_COMPILER_INTEL __ICC
+#elif defined( __ECC )
+  // Very old define
+  #define KOKKOS_COMPILER_INTEL __ECC
+#endif
+
+/* CRAY compiler for host code */
+#if defined( _CRAYC )
+  #define KOKKOS_COMPILER_CRAYC _CRAYC
+#endif
+
+#if defined( __IBMCPP__ )
+  // IBM C++
+  #define KOKKOS_COMPILER_IBM __IBMCPP__
+#elif defined( __IBMC__ )
+  #define KOKKOS_COMPILER_IBM __IBMC__
+#endif
+
+#if defined( __APPLE_CC__ )
+  #define KOKKOS_COMPILER_APPLECC __APPLE_CC__
+#endif
+
+#if defined (__clang__) && !defined (KOKKOS_COMPILER_INTEL)
+  #define KOKKOS_COMPILER_CLANG __clang_major__*100+__clang_minor__*10+__clang_patchlevel__
+#endif
+
+#if ! defined( __clang__ ) && ! defined( KOKKOS_COMPILER_INTEL ) &&defined( __GNUC__ )
+  #define KOKKOS_COMPILER_GNU __GNUC__*100+__GNUC_MINOR__*10+__GNUC_PATCHLEVEL__
+  #if ( 472 > KOKKOS_COMPILER_GNU )
+    #error "Compiling with GCC version earlier than 4.7.2 is not supported."
+  #endif
+#endif
+
+#if defined( __PGIC__ ) && ! defined( __GNUC__ )
+  #define KOKKOS_COMPILER_PGI __PGIC__*100+__PGIC_MINOR__*10+__PGIC_PATCHLEVEL__
+  #if ( 1540 > KOKKOS_COMPILER_PGI )
+    #error "Compiling with PGI version earlier than 15.4 is not supported."
+  #endif
+#endif
+
+#endif /* #if ! defined( __CUDA_ARCH__ ) */
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/* Intel compiler macros */
+
+#if defined( KOKKOS_COMPILER_INTEL )
+
+  #define KOKKOS_HAVE_PRAGMA_UNROLL 1
+  #define KOKKOS_HAVE_PRAGMA_IVDEP 1
+  #define KOKKOS_HAVE_PRAGMA_LOOPCOUNT 1
+  #define KOKKOS_HAVE_PRAGMA_VECTOR 1
+  #define KOKKOS_HAVE_PRAGMA_SIMD 1
+
+  #if ( 1400 > KOKKOS_COMPILER_INTEL )
+    #if ( 1300 > KOKKOS_COMPILER_INTEL )
+      #error "Compiling with Intel version earlier than 13.0 is not supported. Official minimal version is 14.0."
+    #else
+      #warning "Compiling with Intel version 13.x probably works but is not officially supported. Official minimal version is 14.0."
+    #endif
+  #endif
+  #if ( 1200 <= KOKKOS_COMPILER_INTEL ) && ! defined( KOKKOS_ENABLE_ASM ) && ! defined( _WIN32 )
+    #define KOKKOS_ENABLE_ASM 1
+  #endif
+
+  #if ( 1200 <= KOKKOS_COMPILER_INTEL ) && ! defined( KOKKOS_FORCEINLINE_FUNCTION )
+    #if !defined (_WIN32)
+      #define KOKKOS_FORCEINLINE_FUNCTION  inline __attribute__((always_inline))
+    #else
+      #define KOKKOS_FORCEINLINE_FUNCTION inline
+    #endif
+  #endif
+
+  #if defined( __MIC__ )
+    // Compiling for Xeon Phi
+  #endif
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* Cray compiler macros */
+
+#if defined( KOKKOS_COMPILER_CRAYC )
+
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* IBM Compiler macros */
+
+#if defined( KOKKOS_COMPILER_IBM )
+
+  #define KOKKOS_HAVE_PRAGMA_UNROLL 1
+  //#define KOKKOS_HAVE_PRAGMA_IVDEP 1
+  //#define KOKKOS_HAVE_PRAGMA_LOOPCOUNT 1
+  //#define KOKKOS_HAVE_PRAGMA_VECTOR 1
+  //#define KOKKOS_HAVE_PRAGMA_SIMD 1
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* CLANG compiler macros */
+
+#if defined( KOKKOS_COMPILER_CLANG )
+
+  //#define KOKKOS_HAVE_PRAGMA_UNROLL 1
+  //#define KOKKOS_HAVE_PRAGMA_IVDEP 1
+  //#define KOKKOS_HAVE_PRAGMA_LOOPCOUNT 1
+  //#define KOKKOS_HAVE_PRAGMA_VECTOR 1
+  //#define KOKKOS_HAVE_PRAGMA_SIMD 1
+
+  #if ! defined( KOKKOS_FORCEINLINE_FUNCTION )
+    #define KOKKOS_FORCEINLINE_FUNCTION  inline __attribute__((always_inline))
+  #endif
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+/* GNU Compiler macros */
+
+#if defined( KOKKOS_COMPILER_GNU )
+
+  //#define KOKKOS_HAVE_PRAGMA_UNROLL 1
+  //#define KOKKOS_HAVE_PRAGMA_IVDEP 1
+  //#define KOKKOS_HAVE_PRAGMA_LOOPCOUNT 1
+  //#define KOKKOS_HAVE_PRAGMA_VECTOR 1
+  //#define KOKKOS_HAVE_PRAGMA_SIMD 1
+
+  #if ! defined( KOKKOS_FORCEINLINE_FUNCTION )
+    #define KOKKOS_FORCEINLINE_FUNCTION inline __attribute__((always_inline))
+  #endif
+
+  #if ! defined( KOKKOS_ENABLE_ASM ) && \
+      ! ( defined( __powerpc) || \
+          defined(__powerpc__) || \
+          defined(__powerpc64__) || \
+          defined(__POWERPC__) || \
+          defined(__ppc__) || \
+          defined(__ppc64__) || \
+          defined(__PGIC__) )
+    #define KOKKOS_ENABLE_ASM 1
+  #endif
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#if defined( KOKKOS_COMPILER_PGI )
+
+  #define KOKKOS_HAVE_PRAGMA_UNROLL 1
+  #define KOKKOS_HAVE_PRAGMA_IVDEP 1
+  //#define KOKKOS_HAVE_PRAGMA_LOOPCOUNT 1
+  #define KOKKOS_HAVE_PRAGMA_VECTOR 1
+  //#define KOKKOS_HAVE_PRAGMA_SIMD 1
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#if defined( KOKKOS_COMPILER_NVCC )
+
+  #if defined(__CUDA_ARCH__ )
+    #define KOKKOS_HAVE_PRAGMA_UNROLL 1
+  #endif
+
+#endif
+
+//----------------------------------------------------------------------------
+/** Define function marking macros if compiler specific macros are undefined: */
+
+#if ! defined( KOKKOS_FORCEINLINE_FUNCTION )
+#define KOKKOS_FORCEINLINE_FUNCTION  inline
+#endif
+
+#if ! defined( KOKKOS_INLINE_FUNCTION )
+#define KOKKOS_INLINE_FUNCTION  inline
+#endif
+
+#if ! defined( KOKKOS_FUNCTION )
+#define KOKKOS_FUNCTION /**/
+#endif
+
+//----------------------------------------------------------------------------
+/** Define Macro for alignment: */
+#if ! defined(KOKKOS_ALIGN_16)
+#define KOKKOS_ALIGN_16 __attribute__((aligned(16)))
+#endif
+
+//----------------------------------------------------------------------------
+/** Determine the default execution space for parallel dispatch.
+ *  There is zero or one default execution space specified.
+ */
+
+#if 1 < ( ( defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_CUDA ) ? 1 : 0 ) + \
+          ( defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_OPENMP ) ? 1 : 0 ) + \
+          ( defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS ) ? 1 : 0 ) + \
+          ( defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_SERIAL ) ? 1 : 0 ) )
+
+#error "More than one KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_* specified" ;
+
+#endif
+
+/** If default is not specified then chose from enabled execution spaces.
+ *  Priority: CUDA, OPENMP, THREADS, SERIAL
+ */
+#if   defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_CUDA )
+#elif defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_OPENMP )
+#elif defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS )
+#elif defined ( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_SERIAL )
+#elif defined ( KOKKOS_HAVE_CUDA )
+#define KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_CUDA
+#elif defined ( KOKKOS_HAVE_OPENMP )
+#define KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_OPENMP
+#elif defined ( KOKKOS_HAVE_PTHREAD )
+#define KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS
+#else
+#define KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_SERIAL
+#endif
+
+//----------------------------------------------------------------------------
+/** Determine for what space the code is being compiled: */
+
+#if defined( __CUDACC__ ) && defined( __CUDA_ARCH__ ) && defined (KOKKOS_HAVE_CUDA)
+#define KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_CUDA
+#else
+#define KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+#endif
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if ( defined( _POSIX_C_SOURCE ) && _POSIX_C_SOURCE >= 200112L ) || \
+    ( defined( _XOPEN_SOURCE )   && _XOPEN_SOURCE   >= 600 )
+#if defined(KOKKOS_ENABLE_PERFORMANCE_POSIX_MEMALIGN)
+#define KOKKOS_POSIX_MEMALIGN_AVAILABLE 1
+#endif
+#endif
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+/**Enable Profiling by default**/
+
+#ifndef KOKKOS_ENABLE_PROFILING
+#define KOKKOS_ENABLE_PROFILING 1
+#endif
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+/* Transitional macro to change between old and new View
+ * are no longer supported.
+ */
+
+#if defined( KOKKOS_USING_DEPRECATED_VIEW )
+#error "Kokkos deprecated View has been removed"
+#endif
+
+#define KOKKOS_USING_EXP_VIEW 1
+#define KOKKOS_USING_EXPERIMENTAL_VIEW
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_MACROS_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_MemoryPool.hpp b/lib/kokkos/core/src/Kokkos_MemoryPool.hpp
new file mode 100644
index 0000000000..d843f7c9a1
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_MemoryPool.hpp
@@ -0,0 +1,1523 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_MEMORYPOOL_HPP
+#define KOKKOS_MEMORYPOOL_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_Parallel.hpp>
+#include <Kokkos_Atomic.hpp>
+#include <impl/Kokkos_BitOps.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <impl/KokkosExp_SharedAlloc.hpp>
+
+#include <limits>
+#include <algorithm>
+#include <chrono>
+
+// How should errors be handled?  In general, production code should return a
+// value indicating failure so the user can decide how the error is handled.
+// While experimental, code can abort instead.  If KOKKOS_MEMPOOL_PRINTERR is
+// defined, the code will abort with an error message.  Otherwise, the code will
+// return with a value indicating failure when possible, or do nothing instead.
+//#define KOKKOS_MEMPOOL_PRINTERR
+
+//#define KOKKOS_MEMPOOL_PRINT_INFO
+//#define KOKKOS_MEMPOOL_PRINT_CONSTRUCTOR_INFO
+//#define KOKKOS_MEMPOOL_PRINT_BLOCKSIZE_INFO
+//#define KOKKOS_MEMPOOL_PRINT_SUPERBLOCK_INFO
+//#define KOKKOS_MEMPOOL_PRINT_ACTIVE_SUPERBLOCKS
+//#define KOKKOS_MEMPOOL_PRINT_PAGE_INFO
+//#define KOKKOS_MEMPOOL_PRINT_INDIVIDUAL_PAGE_INFO
+
+// A superblock is considered full when this percentage of its pages are full.
+#define KOKKOS_MEMPOOL_SB_FULL_FRACTION 0.80
+
+// A page is considered full when this percentage of its blocks are full.
+#define KOKKOS_MEMPOOL_PAGE_FULL_FRACTION 0.875  // 28 / 32
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+namespace MempoolImpl {
+
+template < typename T, typename ExecutionSpace >
+struct initialize_array {
+  typedef ExecutionSpace                      execution_space;
+  typedef typename ExecutionSpace::size_type  size_type;
+
+  T *  m_data;
+  T    m_value;
+
+  initialize_array( T * d, size_t size, T v ) : m_data( d ), m_value( v )
+  {
+    Kokkos::parallel_for( size, *this );
+
+    execution_space::fence();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const { m_data[i] = m_value; }
+};
+
+template <typename Bitset>
+struct bitset_count
+{
+  typedef typename Bitset::execution_space     execution_space;
+  typedef typename execution_space::size_type  size_type;
+  typedef typename Bitset::size_type           value_type;
+  typedef typename Bitset::word_type           word_type;
+
+  word_type *   m_words;
+  value_type &  m_result;
+
+  bitset_count( word_type * w, value_type num_words, value_type & r )
+    : m_words( w ), m_result( r )
+  {
+    parallel_reduce( num_words, *this, m_result );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & v ) const
+  { v = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst, volatile value_type const & src ) const
+  { dst += src; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i, value_type & count) const
+  {
+    count += Kokkos::Impl::bit_count( m_words[i] );
+  }
+};
+
+template < typename Device >
+class Bitset {
+public:
+  typedef typename Device::execution_space  execution_space;
+  typedef typename Device::memory_space     memory_space;
+  typedef unsigned                          word_type;
+  typedef unsigned                          size_type;
+
+  typedef Kokkos::Impl::DeepCopy< memory_space, Kokkos::HostSpace > raw_deep_copy;
+
+  // Define some constants.
+  enum {
+    // Size of bitset word.  Should be 32.
+    WORD_SIZE    = sizeof(word_type) * CHAR_BIT,
+    LG_WORD_SIZE = Kokkos::Impl::integral_power_of_two( WORD_SIZE ),
+    WORD_MASK    = WORD_SIZE - 1
+  };
+
+private:
+  word_type *  m_words;
+  size_type    m_size;
+  size_type    m_num_words;
+  word_type    m_last_word_mask;
+
+public:
+  ~Bitset() = default;
+  Bitset() = default;
+  Bitset( Bitset && ) = default;
+  Bitset( const Bitset & ) = default;
+  Bitset & operator = ( Bitset && ) = default;
+  Bitset & operator = ( const Bitset & ) = default;
+
+  void init( void * w, size_type s )
+  {
+    // Assumption: The size of the memory pointed to by w is a multiple of
+    //             sizeof(word_type).
+
+    m_words = reinterpret_cast<word_type*>( w );
+    m_size = s;
+    m_num_words = ( s + WORD_SIZE - 1 ) >> LG_WORD_SIZE;
+    m_last_word_mask = m_size & WORD_MASK ? ( word_type(1) << ( m_size & WORD_MASK ) ) - 1 : 0;
+
+    reset();
+  }
+
+  size_type size() const { return m_size; }
+
+  size_type count() const
+  {
+    size_type val;
+    bitset_count< Bitset > bc( m_words, m_num_words, val );
+    return val;
+  }
+
+  void set()
+  {
+    // Set all the bits.
+    initialize_array< word_type, execution_space > ia( m_words, m_num_words, ~word_type(0) );
+
+    if ( m_last_word_mask ) {
+      // Clear the unused bits in the last block.
+      raw_deep_copy( m_words + ( m_num_words - 1 ), &m_last_word_mask, sizeof(word_type) );
+    }
+  }
+
+  void reset()
+  {
+    initialize_array< word_type, execution_space > ia( m_words, m_num_words, word_type(0) );
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool test( size_type i ) const
+  {
+    size_type word_pos = i >> LG_WORD_SIZE;
+    word_type word = volatile_load( &m_words[ word_pos ] );
+    word_type mask = word_type(1) << ( i & WORD_MASK );
+
+    return word & mask;
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool set( size_type i ) const
+  {
+    size_type word_pos = i >> LG_WORD_SIZE;
+    word_type mask = word_type(1) << ( i & WORD_MASK );
+
+    return !( atomic_fetch_or( &m_words[ word_pos ], mask ) & mask );
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool reset( size_type i ) const
+  {
+    size_type word_pos = i >> LG_WORD_SIZE;
+    word_type mask = word_type(1) << ( i & WORD_MASK );
+
+    return atomic_fetch_and( &m_words[ word_pos ], ~mask ) & mask;
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  Kokkos::pair< bool, word_type >
+  fetch_word_reset( size_type i ) const
+  {
+    size_type word_pos = i >> LG_WORD_SIZE;
+    word_type mask = word_type(1) << ( i & WORD_MASK );
+
+    Kokkos::pair<bool, word_type> result;
+    result.second = atomic_fetch_and( &m_words[ word_pos ], ~mask );
+    result.first = result.second & mask;
+
+    return result;
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  Kokkos::pair< bool, size_type >
+  set_any_in_word( size_type i, word_type & prev_val ) const
+  {
+    prev_val = 0;
+
+    size_type word_pos = i >> LG_WORD_SIZE;
+    word_type word = volatile_load( &m_words[ word_pos ] );
+
+    // Loop until there are no more unset bits in the word.
+    while ( ~word ) {
+      // Find the first unset bit in the word.
+      size_type bit = Kokkos::Impl::bit_scan_forward( ~word );
+
+      // Try to set the bit.
+			word_type mask = word_type(1) << bit;
+      word = atomic_fetch_or( &m_words[ word_pos ], mask );
+
+      if ( !( word & mask ) ) {
+        // Successfully set the bit.
+        prev_val = word;
+
+        return Kokkos::pair<bool, size_type>( true, ( word_pos << LG_WORD_SIZE ) + bit );
+      }
+    }
+
+    // Didn't find a free bit in this word.
+    return Kokkos::pair<bool, size_type>( false, i );
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  Kokkos::pair< bool, size_type >
+  set_any_in_word( size_type i, word_type & prev_val, word_type word_mask ) const
+  {
+    prev_val = 0;
+
+    size_type word_pos = i >> LG_WORD_SIZE;
+    word_type word = volatile_load( &m_words[ word_pos ] );
+    word = ( ~word ) & word_mask;
+
+    // Loop until there are no more unset bits in the word.
+    while ( word ) {
+      // Find the first unset bit in the word.
+      size_type bit = Kokkos::Impl::bit_scan_forward( word );
+
+      // Try to set the bit.
+			word_type mask = word_type(1) << bit;
+      word = atomic_fetch_or( &m_words[ word_pos ], mask );
+
+      if ( !( word & mask ) ) {
+        // Successfully set the bit.
+        prev_val = word;
+
+        return Kokkos::pair<bool, size_type>( true, ( word_pos << LG_WORD_SIZE ) + bit );
+      }
+
+      word = ( ~word ) & word_mask;
+    }
+
+    // Didn't find a free bit in this word.
+    return Kokkos::pair<bool, size_type>( false, i );
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  Kokkos::pair< bool, size_type >
+  reset_any_in_word( size_type i, word_type & prev_val ) const
+  {
+    prev_val = 0;
+
+    size_type word_pos = i >> LG_WORD_SIZE;
+    word_type word = volatile_load( &m_words[ word_pos ] );
+
+    // Loop until there are no more set bits in the word.
+    while ( word ) {
+      // Find the first unset bit in the word.
+      size_type bit = Kokkos::Impl::bit_scan_forward( word );
+
+      // Try to reset the bit.
+			word_type mask = word_type(1) << bit;
+      word = atomic_fetch_and( &m_words[ word_pos ], ~mask );
+
+      if ( word & mask ) {
+        // Successfully reset the bit.
+        prev_val = word;
+
+        return Kokkos::pair<bool, size_type>( true, ( word_pos << LG_WORD_SIZE ) + bit );
+      }
+    }
+
+    // Didn't find a free bit in this word.
+    return Kokkos::pair<bool, size_type>( false, i );
+  }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  Kokkos::pair< bool, size_type >
+  reset_any_in_word( size_type i, word_type & prev_val, word_type word_mask ) const
+  {
+    prev_val = 0;
+
+    size_type word_pos = i >> LG_WORD_SIZE;
+    word_type word = volatile_load( &m_words[ word_pos ] );
+    word = word & word_mask;
+
+    // Loop until there are no more set bits in the word.
+    while ( word ) {
+      // Find the first unset bit in the word.
+      size_type bit = Kokkos::Impl::bit_scan_forward( word );
+
+      // Try to reset the bit.
+			word_type mask = word_type(1) << bit;
+      word = atomic_fetch_and( &m_words[ word_pos ], ~mask );
+
+      if ( word & mask ) {
+        // Successfully reset the bit.
+        prev_val = word;
+
+        return Kokkos::pair<bool, size_type>( true, ( word_pos << LG_WORD_SIZE ) + bit );
+      }
+
+      word = word & word_mask;
+    }
+
+    // Didn't find a free bit in this word.
+    return Kokkos::pair<bool, size_type>( false, i );
+  }
+};
+
+template < typename UInt32View, typename BSHeaderView, typename SBHeaderView,
+           typename MempoolBitset >
+struct create_histogram {
+  typedef typename UInt32View::execution_space  execution_space;
+  typedef typename execution_space::size_type   size_type;
+  typedef Kokkos::pair< double, uint32_t >      value_type;
+
+  size_t         m_start;
+  UInt32View     m_page_histogram;
+  BSHeaderView   m_blocksize_info;
+  SBHeaderView   m_sb_header;
+  MempoolBitset  m_sb_blocks;
+  size_t         m_lg_max_sb_blocks;
+  uint32_t       m_lg_min_block_size;
+  uint32_t       m_blocks_per_page;
+  value_type &   m_result;
+
+  create_histogram( size_t start, size_t end, UInt32View ph, BSHeaderView bsi,
+                    SBHeaderView sbh, MempoolBitset sbb, size_t lmsb,
+                    uint32_t lmbs, uint32_t bpp, value_type & r )
+    : m_start( start ), m_page_histogram( ph ), m_blocksize_info( bsi ),
+      m_sb_header( sbh ), m_sb_blocks( sbb ), m_lg_max_sb_blocks( lmsb ),
+      m_lg_min_block_size( lmbs ), m_blocks_per_page( bpp ), m_result( r )
+  {
+    Kokkos::parallel_reduce( end - start, *this, m_result );
+
+    execution_space::fence();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & v ) const
+  {
+    v.first  = 0.0;
+    v.second = 0;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst, volatile value_type const & src ) const
+  {
+    dst.first += src.first;
+    dst.second += src.second;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i, value_type & r ) const
+  {
+    size_type i2 = i + m_start;
+
+    uint32_t lg_block_size = m_sb_header(i2).m_lg_block_size;
+
+    // A superblock only has a block size of 0 when it is empty.
+    if ( lg_block_size != 0 ) {
+      uint32_t block_size_id = lg_block_size - m_lg_min_block_size;
+      uint32_t blocks_per_sb = m_blocksize_info[block_size_id].m_blocks_per_sb;
+      uint32_t pages_per_sb = m_blocksize_info[block_size_id].m_pages_per_sb;
+
+      uint32_t total_allocated_blocks = 0;
+
+      for ( uint32_t j = 0; j < pages_per_sb; ++j ) {
+        unsigned start_pos = ( i2 << m_lg_max_sb_blocks ) + j * m_blocks_per_page;
+        unsigned end_pos = start_pos + m_blocks_per_page;
+        uint32_t page_allocated_blocks = 0;
+
+        for ( unsigned k = start_pos; k < end_pos; ++k ) {
+          page_allocated_blocks += m_sb_blocks.test( k );
+        }
+
+        total_allocated_blocks += page_allocated_blocks;
+
+        atomic_fetch_add( &m_page_histogram(page_allocated_blocks), 1 );
+      }
+
+      r.first += double(total_allocated_blocks) / blocks_per_sb;
+      r.second += blocks_per_sb;
+    }
+  }
+};
+
+#ifdef KOKKOS_MEMPOOL_PRINT_SUPERBLOCK_INFO
+template < typename UInt32View, typename SBHeaderView, typename MempoolBitset >
+struct count_allocated_blocks {
+  typedef typename UInt32View::execution_space  execution_space;
+  typedef typename execution_space::size_type   size_type;
+
+  UInt32View     m_num_allocated_blocks;
+  SBHeaderView   m_sb_header;
+  MempoolBitset  m_sb_blocks;
+  size_t         m_sb_size;
+  size_t         m_lg_max_sb_blocks;
+
+  count_allocated_blocks( size_t num_sb, UInt32View nab, SBHeaderView sbh,
+                          MempoolBitset sbb, size_t sbs, size_t lmsb )
+    : m_num_allocated_blocks( nab ), m_sb_header( sbh ),
+      m_sb_blocks( sbb ), m_sb_size( sbs ), m_lg_max_sb_blocks( lmsb )
+  {
+    Kokkos::parallel_for( num_sb, *this );
+
+    execution_space::fence();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const
+  {
+    uint32_t lg_block_size = m_sb_header(i).m_lg_block_size;
+
+    // A superblock only has a block size of 0 when it is empty.
+    if ( lg_block_size != 0 ) {
+      // Count the allocated blocks in the superblock.
+      uint32_t blocks_per_sb = lg_block_size > 0 ? m_sb_size >> lg_block_size : 0;
+      unsigned start_pos = i << m_lg_max_sb_blocks;
+      unsigned end_pos = start_pos + blocks_per_sb;
+      uint32_t count = 0;
+
+      for ( unsigned j = start_pos; j < end_pos; ++j ) {
+        count += m_sb_blocks.test( j );
+      }
+
+      m_num_allocated_blocks(i) = count;
+    }
+  }
+};
+#endif
+
+}
+
+/// \class MemoryPool
+/// \brief Bitset based memory manager for pools of same-sized chunks of memory.
+/// \tparam Device Kokkos device that gives the execution and memory space the
+///                allocator will be used in.
+///
+/// MemoryPool is a memory space that can be on host or device.  It provides a
+/// pool memory allocator for fast allocation of same-sized chunks of memory.
+/// The memory is only accessible on the host / device this allocator is
+/// associated with.
+///
+/// This allocator is based on ideas from the following GPU allocators:
+///   Halloc (https://github.com/canonizer/halloc).
+///   ScatterAlloc (https://github.com/ComputationalRadiationPhysics/scatteralloc)
+template < typename Device >
+class MemoryPool {
+private:
+  // The allocator uses superblocks.  A superblock is divided into pages, and a
+  // page is divided into blocks.  A block is the chunk of memory that is given
+  // out by the allocator.  A page always has a number of blocks equal to the
+  // size of the word used by the bitset.  Thus, the pagesize can vary between
+  // superblocks as it is based on the block size of the superblock.  The
+  // allocator supports all powers of 2 from MIN_BLOCK_SIZE to the size of a
+  // superblock as block sizes.
+
+  // Superblocks are divided into 4 categories:
+  //   1. empty    - is completely empty; there are no active allocations
+  //   2. partfull - partially full; there are some active allocations
+  //   3. full     - full enough with active allocations that new allocations
+  //                 will likely fail
+  //   4. active   - is currently the active superblock for a block size
+  //
+  // An inactive superblock is one that is empty, partfull, or full.
+  //
+  // New allocations occur only from an active superblock.  If a superblock is
+  // made inactive after an allocation request is made to it but before the
+  // allocation request is fulfilled, the allocation will still be attempted
+  // from that superblock.  Deallocations can  occur to partfull, full, or
+  // active superblocks.  Superblocks move between categories as allocations
+  // and deallocations happen.  Superblocks all start empty.
+  //
+  // Here are the possible moves between categories:
+  //   empty    -> active    During allocation, there is no active superblock
+  //                         or the active superblock is full.
+  //   active   -> full      During allocation, the full threshold of the
+  //                         superblock is reached when increasing the fill
+  //                         level.
+  //   full     -> partfull  During deallocation, the full threshold of the
+  //                         superblock is crossed when decreasing the fill
+  //                         level.
+  //   partfull -> empty     Deallocation of the last allocated block of an
+  //                         inactive superblock.
+  //   partfull -> active    During allocation, the active superblock is full.
+  //
+  // When a new active superblock is needed, partfull superblocks of the same
+  // block size are chosen over empty superblocks.
+  //
+  // The empty and partfull superblocks are tracked using bitsets that represent
+  // the superblocks in those repsective categories.  Empty superblocks use a
+  // single bitset, while partfull superblocks use a bitset per block size
+  // (contained sequentially in a single bitset).  Active superblocks are
+  // tracked by the active superblocks array.  Full superblocks aren't tracked
+  // at all.
+
+  typedef typename Device::execution_space    execution_space;
+  typedef typename Device::memory_space       backend_memory_space;
+  typedef Device                              device_type;
+  typedef MempoolImpl::Bitset< device_type >  MempoolBitset;
+
+  // Define some constants.
+  enum {
+    MIN_BLOCK_SIZE     = 64,
+    LG_MIN_BLOCK_SIZE  = Kokkos::Impl::integral_power_of_two( MIN_BLOCK_SIZE ),
+    MAX_BLOCK_SIZES    = 31 - LG_MIN_BLOCK_SIZE + 1,
+
+    // Size of bitset word.
+    BLOCKS_PER_PAGE    = MempoolBitset::WORD_SIZE,
+    LG_BLOCKS_PER_PAGE = MempoolBitset::LG_WORD_SIZE,
+
+    INVALID_SUPERBLOCK = ~uint32_t(0),
+    SUPERBLOCK_LOCK    = ~uint32_t(0) - 1,
+
+    MAX_TRIES          = 32             // Cap on the number of pages searched
+                                        // before an allocation returns empty.
+  };
+
+public:
+  // Stores information about each superblock.
+  struct SuperblockHeader {
+    uint32_t  m_full_pages;
+    uint32_t  m_empty_pages;
+    uint32_t  m_lg_block_size;
+    uint32_t  m_is_active;
+
+    KOKKOS_FUNCTION
+    SuperblockHeader() :
+      m_full_pages(0), m_empty_pages(0), m_lg_block_size(0), m_is_active(false) {}
+  };
+
+  // Stores information about each block size.
+  struct BlockSizeHeader {
+    uint32_t  m_blocks_per_sb;
+    uint32_t  m_pages_per_sb;
+    uint32_t  m_sb_full_level;
+    uint32_t  m_page_full_level;
+
+    KOKKOS_FUNCTION
+    BlockSizeHeader() :
+      m_blocks_per_sb(0), m_pages_per_sb(0), m_sb_full_level(0), m_page_full_level(0) {}
+  };
+
+private:
+  typedef Impl::SharedAllocationTracker            Tracker;
+  typedef View< uint32_t *, device_type >          UInt32View;
+  typedef View< SuperblockHeader *, device_type >  SBHeaderView;
+
+  // The letters 'sb' used in any variable name mean superblock.
+
+  size_t           m_lg_sb_size;        // Log2 of superblock size.
+  size_t           m_sb_size;           // Superblock size.
+  size_t           m_lg_max_sb_blocks;  // Log2 of the number of blocks of the
+                                        // minimum block size in a superblock.
+  size_t           m_num_sb;            // Number of superblocks.
+  size_t           m_ceil_num_sb;       // Number of superblocks rounded up to the smallest
+                                        // multiple of the bitset word size.  Used by
+                                        // bitsets representing superblock categories to
+                                        // ensure different block sizes never share a word
+                                        // in the bitset.
+  size_t           m_num_block_size;    // Number of block sizes supported.
+  size_t           m_data_size;         // Amount of memory available to the allocator.
+  size_t           m_sb_blocks_size;    // Amount of memory for free / empty blocks bitset.
+  size_t           m_empty_sb_size;     // Amount of memory for empty superblocks bitset.
+  size_t           m_partfull_sb_size;  // Amount of memory for partfull superblocks bitset.
+  size_t           m_total_size;        // Total amount of memory allocated.
+  char *           m_data;              // Beginning device memory location used for
+                                        // superblocks.
+  UInt32View       m_active;            // Active superblocks IDs.
+  SBHeaderView     m_sb_header;         // Header info for superblocks.
+  MempoolBitset    m_sb_blocks;         // Bitsets representing free / allocated status
+                                        // of blocks in superblocks.
+  MempoolBitset    m_empty_sb;          // Bitset representing empty superblocks.
+  MempoolBitset    m_partfull_sb;       // Bitsets representing partially full superblocks.
+  Tracker          m_track;             // Tracker for superblock memory.
+  BlockSizeHeader  m_blocksize_info[MAX_BLOCK_SIZES];  // Header info for block sizes.
+
+  // There were several methods tried for storing the block size header info: in a View,
+  // in a View of const data, and in a RandomAccess View.  All of these were slower than
+  // storing it in a static array that is a member variable to the class.  In the latter
+  // case, the block size info gets copied into the constant memory on the GPU along with
+  // the class when it is copied there for exeucting a parallel loop.  Instead of storing
+  // the values, computing the values every time they were needed was also tried.  This
+  // method was slightly slower than storing them in the static array.
+
+public:
+  //! Tag this class as a kokkos memory space
+  typedef MemoryPool  memory_space;
+
+  ~MemoryPool() = default;
+  MemoryPool() = default;
+  MemoryPool( MemoryPool && ) = default;
+  MemoryPool( const MemoryPool & ) = default;
+  MemoryPool & operator = ( MemoryPool && ) = default;
+  MemoryPool & operator = ( const MemoryPool & ) = default;
+
+  /// \brief Initializes the memory pool.
+  /// \param memspace The memory space from which the memory pool will allocate memory.
+  /// \param total_size The requested memory amount controlled by the allocator.  The
+  ///                   actual amount is rounded up to the smallest multiple of the
+  ///                   superblock size >= the requested size.
+  /// \param log2_superblock_size Log2 of the size of superblocks used by the allocator.
+  ///                             In most use cases, the default value should work.
+  inline
+  MemoryPool( const backend_memory_space & memspace,
+              size_t total_size, size_t log2_superblock_size = 20 )
+    : m_lg_sb_size( log2_superblock_size ),
+      m_sb_size( size_t(1) << m_lg_sb_size ),
+      m_lg_max_sb_blocks( m_lg_sb_size - LG_MIN_BLOCK_SIZE ),
+      m_num_sb( ( total_size + m_sb_size - 1 ) >> m_lg_sb_size ),
+      m_ceil_num_sb( ( ( m_num_sb + BLOCKS_PER_PAGE - 1 ) >> LG_BLOCKS_PER_PAGE ) <<
+                     LG_BLOCKS_PER_PAGE ),
+      m_num_block_size( m_lg_sb_size - LG_MIN_BLOCK_SIZE + 1 ),
+      m_data_size( m_num_sb * m_sb_size ),
+      m_sb_blocks_size( ( m_num_sb << m_lg_max_sb_blocks ) / CHAR_BIT ),
+      m_empty_sb_size( m_ceil_num_sb / CHAR_BIT ),
+      m_partfull_sb_size( m_ceil_num_sb * m_num_block_size / CHAR_BIT ),
+      m_total_size( m_data_size +  m_sb_blocks_size + m_empty_sb_size + m_partfull_sb_size ),
+      m_data(0),
+      m_active( "Active superblocks" ),
+      m_sb_header( "Superblock headers" ),
+      m_track()
+  {
+    // Assumption.  The minimum block size must be a power of 2.
+    static_assert( Kokkos::Impl::is_integral_power_of_two( MIN_BLOCK_SIZE ), "" );
+
+    // Assumption.  Require a superblock be large enough so it takes at least 1
+    // whole bitset word to represent it using the minimum blocksize.
+    if ( m_sb_size < MIN_BLOCK_SIZE * BLOCKS_PER_PAGE ) {
+      printf( "\n** MemoryPool::MemoryPool() Superblock size must be >= %u **\n",
+              MIN_BLOCK_SIZE * BLOCKS_PER_PAGE );
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+      fflush( stdout );
+#endif
+      Kokkos::abort( "" );
+    }
+
+    // Assumption.  A superblock's size can be at most 2^31.  Verify this.
+    if ( m_lg_sb_size > 31 ) {
+      printf( "\n** MemoryPool::MemoryPool() Superblock size must be < %u **\n",
+              ( uint32_t(1) << 31 ) );
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+      fflush( stdout );
+#endif
+      Kokkos::abort( "" );
+    }
+
+    // Assumption.  The Bitset only uses unsigned for size types which limits
+    // the amount of memory the allocator can manage.  Verify the memory size
+    // is below this limit.
+    if ( m_data_size > size_t(MIN_BLOCK_SIZE) * std::numeric_limits<unsigned>::max() ) {
+      printf( "\n** MemoryPool::MemoryPool() Allocator can only manage %lu bytes of memory; requested %lu **\n",
+              size_t(MIN_BLOCK_SIZE) * std::numeric_limits<unsigned>::max(), total_size );
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+      fflush( stdout );
+#endif
+      Kokkos::abort( "" );
+    }
+
+    // Allocate memory for Views.  This is done here instead of at construction
+    // so that the runtime checks can be performed before allocating memory.
+    resize(m_active, m_num_block_size );
+    resize(m_sb_header, m_num_sb );
+
+    // Allocate superblock memory.
+    typedef Impl::SharedAllocationRecord< backend_memory_space, void >  SharedRecord;
+    SharedRecord * rec =
+      SharedRecord::allocate( memspace, "mempool", m_total_size );
+
+    m_track.assign_allocated_record_to_uninitialized( rec );
+    m_data = reinterpret_cast<char *>( rec->data() );
+
+    // Set and initialize the free / empty block bitset memory.
+    m_sb_blocks.init( m_data + m_data_size, m_num_sb << m_lg_max_sb_blocks );
+
+    // Set and initialize the empty superblock block bitset memory.
+    m_empty_sb.init( m_data + m_data_size + m_sb_blocks_size, m_num_sb );
+
+    // Start with all superblocks in the empty category.
+    m_empty_sb.set();
+
+    // Set and initialize the partfull superblock block bitset memory.
+    m_partfull_sb.init( m_data + m_data_size + m_sb_blocks_size + m_empty_sb_size,
+                        m_ceil_num_sb * m_num_block_size );
+
+    // Initialize all active superblocks to be invalid.
+    typename UInt32View::HostMirror host_active = create_mirror_view(m_active);
+    for (size_t i = 0; i < m_num_block_size; ++i) host_active(i) = INVALID_SUPERBLOCK;
+
+    deep_copy(m_active, host_active);
+
+    // Initialize the blocksize info.
+    for ( size_t i = 0; i < m_num_block_size; ++i ) {
+      uint32_t lg_block_size = i + LG_MIN_BLOCK_SIZE;
+      uint32_t blocks_per_sb = m_sb_size >> lg_block_size;
+      uint32_t pages_per_sb = ( blocks_per_sb + BLOCKS_PER_PAGE - 1 ) >> LG_BLOCKS_PER_PAGE;
+
+      m_blocksize_info[i].m_blocks_per_sb = blocks_per_sb;
+      m_blocksize_info[i].m_pages_per_sb = pages_per_sb;
+
+      // Set the full level for the superblock.
+      m_blocksize_info[i].m_sb_full_level =
+        static_cast<uint32_t>( pages_per_sb * KOKKOS_MEMPOOL_SB_FULL_FRACTION );
+
+      if ( m_blocksize_info[i].m_sb_full_level == 0 ) {
+        m_blocksize_info[i].m_sb_full_level = 1;
+      }
+
+      // Set the full level for the page.
+      uint32_t blocks_per_page =
+        blocks_per_sb < BLOCKS_PER_PAGE ? blocks_per_sb : BLOCKS_PER_PAGE;
+
+      m_blocksize_info[i].m_page_full_level =
+        static_cast<uint32_t>( blocks_per_page * KOKKOS_MEMPOOL_PAGE_FULL_FRACTION );
+
+      if ( m_blocksize_info[i].m_page_full_level == 0 ) {
+        m_blocksize_info[i].m_page_full_level = 1;
+      }
+    }
+
+#ifdef KOKKOS_MEMPOOL_PRINT_CONSTRUCTOR_INFO
+    printf( "\n" );
+    printf( "      m_lg_sb_size: %12lu\n", m_lg_sb_size );
+    printf( "         m_sb_size: %12lu\n", m_sb_size );
+    printf( "   m_max_sb_blocks: %12lu\n", size_t(1) << m_lg_max_sb_blocks );
+    printf( "m_lg_max_sb_blocks: %12lu\n", m_lg_max_sb_blocks );
+    printf( "          m_num_sb: %12lu\n", m_num_sb );
+    printf( "     m_ceil_num_sb: %12lu\n", m_ceil_num_sb );
+    printf( "  m_num_block_size: %12lu\n", m_num_block_size );
+    printf( "        data bytes: %12lu\n", m_data_size );
+    printf( "   sb_blocks bytes: %12lu\n", m_sb_blocks_size );
+    printf( "    empty_sb bytes: %12lu\n", m_empty_sb_size );
+    printf( " partfull_sb bytes: %12lu\n", m_partfull_sb_size );
+    printf( "       total bytes: %12lu\n", m_total_size );
+    printf( "   m_empty_sb size: %12u\n", m_empty_sb.size() );
+    printf( "m_partfull_sb size: %12u\n", m_partfull_sb.size() );
+    printf( "\n" );
+    fflush( stdout );
+#endif
+
+#ifdef KOKKOS_MEMPOOL_PRINT_BLOCKSIZE_INFO
+    // Print the blocksize info for all the block sizes.
+    printf( "SIZE    BLOCKS_PER_SB    PAGES_PER_SB    SB_FULL_LEVEL    PAGE_FULL_LEVEL\n" );
+    for ( size_t i = 0; i < m_num_block_size; ++i ) {
+      printf( "%4zu    %13u    %12u    %13u    %15u\n", i + LG_MIN_BLOCK_SIZE,
+              m_blocksize_info[i].m_blocks_per_sb, m_blocksize_info[i].m_pages_per_sb,
+              m_blocksize_info[i].m_sb_full_level, m_blocksize_info[i].m_page_full_level );
+    }
+    printf( "\n" );
+#endif
+  }
+
+  /// \brief  The actual block size allocated given alloc_size.
+  KOKKOS_INLINE_FUNCTION
+  size_t allocate_block_size( const size_t alloc_size ) const
+  { return size_t(1) << ( get_block_size_index( alloc_size ) + LG_MIN_BLOCK_SIZE); }
+
+  /// \brief Allocate a chunk of memory.
+  /// \param alloc_size Size of the requested allocated in number of bytes.
+  ///
+  /// The function returns a void pointer to a memory location on success and
+  /// NULL on failure.
+  KOKKOS_FUNCTION
+  void * allocate( size_t alloc_size ) const
+  {
+    void * p = 0;
+
+    // Only support allocations up to the superblock size.  Just return 0
+    // (failed allocation) for any size above this.
+    if (alloc_size <= m_sb_size )
+    {
+      int block_size_id = get_block_size_index( alloc_size );
+      uint32_t blocks_per_sb = m_blocksize_info[block_size_id].m_blocks_per_sb;
+      uint32_t pages_per_sb = m_blocksize_info[block_size_id].m_pages_per_sb;
+      unsigned word_size = blocks_per_sb > 32 ? 32 : blocks_per_sb;
+      unsigned word_mask = ( uint64_t(1) << word_size ) - 1;
+
+      uint32_t sb_id = volatile_load( &m_active(block_size_id) );
+
+      // If the active is locked, keep reading it until the lock is released.
+      while ( sb_id == SUPERBLOCK_LOCK ) {
+        sb_id = volatile_load( &m_active(block_size_id) );
+      }
+
+      bool allocation_done = false;
+
+      while (!allocation_done) {
+        bool need_new_sb = false;
+
+        if (sb_id != INVALID_SUPERBLOCK) {
+          // Use the value from the clock register as the hash value.
+          uint64_t hash_val = get_clock_register();
+
+          // Get the starting position for this superblock's bits in the bitset.
+          uint32_t pos_base = sb_id << m_lg_max_sb_blocks;
+
+          // Mod the hash value to choose a page in the superblock.  The
+          // initial block searched is the first block of that page.
+          uint32_t pos_rel = uint32_t( hash_val & ( pages_per_sb - 1 ) ) << LG_BLOCKS_PER_PAGE;
+
+          // Get the absolute starting position for this superblock's bits in the bitset.
+          uint32_t pos = pos_base + pos_rel;
+
+          // Keep track of the number of pages searched.  Pages in the superblock are
+          // searched linearly from the starting page.  All pages in the superblock are
+          // searched until either a location is found, or it is proven empty.
+          uint32_t pages_searched = 0;
+
+          bool search_done = false;
+
+          while (!search_done) {
+            bool success;
+            unsigned prev_val;
+
+            Kokkos::tie( success, pos ) =
+              m_sb_blocks.set_any_in_word( pos, prev_val, word_mask );
+
+            if ( !success ) {
+              if ( ++pages_searched >= pages_per_sb ) {
+                // Searched all the pages in this superblock.  Look for a new superblock.
+                //
+                // The previous method tried limiting the number of pages searched, but
+                // that caused a huge performance issue in CUDA where the outer loop
+                // executed massive numbers of times.  Threads weren't able to find a
+                // free location when the superblock wasn't full and were able to execute
+                // the outer loop many times before the superblock was switched for a new
+                // one.  Switching to an exhaustive search eliminated this possiblity and
+                // didn't slow anything down for the tests.
+                need_new_sb = true;
+                search_done = true;
+              }
+              else {
+                // Move to the next page making sure the new search position
+                // doesn't go past this superblock's bits.
+                pos += BLOCKS_PER_PAGE;
+                pos = ( pos < pos_base + blocks_per_sb ) ? pos : pos_base;
+              }
+            }
+            else {
+              // Reserved a memory location to allocate.
+              search_done = true;
+              allocation_done = true;
+
+              uint32_t lg_block_size = block_size_id + LG_MIN_BLOCK_SIZE;
+
+              p = m_data + ( size_t(sb_id) << m_lg_sb_size ) +
+                  ( ( pos - pos_base ) << lg_block_size );
+
+              uint32_t used_bits = Kokkos::Impl::bit_count( prev_val );
+
+              if ( used_bits == 0 ) {
+                // This page was empty.  Decrement the number of empty pages for
+                // the superblock.
+                atomic_fetch_sub( &m_sb_header(sb_id).m_empty_pages, 1 );
+              }
+              else if ( used_bits == m_blocksize_info[block_size_id].m_page_full_level - 1 )
+              {
+                // This page is full.  Increment the number of full pages for
+                // the superblock.
+                uint32_t full_pages = atomic_fetch_add( &m_sb_header(sb_id).m_full_pages, 1 );
+
+                // This allocation made the superblock full, so a new one needs to be found.
+                if ( full_pages == m_blocksize_info[block_size_id].m_sb_full_level - 1 ) {
+                  need_new_sb = true;
+                }
+              }
+            }
+          }
+        }
+        else {
+          // This is the first allocation for this block size.  A superblock needs
+          // to be set as the active one.  If this point is reached any other time,
+          // it is an error.
+          need_new_sb = true;
+        }
+
+        if ( need_new_sb ) {
+          uint32_t new_sb_id = find_superblock( block_size_id, sb_id );
+
+          if ( new_sb_id == sb_id ) {
+            allocation_done = true;
+#ifdef KOKKOS_MEMPOOL_PRINT_INFO
+            printf( "** No superblocks available. **\n" );
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+            fflush( stdout );
+#endif
+#endif
+          }
+          else {
+            sb_id = new_sb_id;
+          }
+        }
+      }
+    }
+#ifdef KOKKOS_MEMPOOL_PRINT_INFO
+    else {
+      printf( "** Requested allocation size (%zu) larger than superblock size (%lu). **\n",
+              alloc_size, m_sb_size);
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+      fflush( stdout );
+#endif
+    }
+#endif
+
+    return p;
+  }
+
+  /// \brief Release allocated memory back to the pool.
+  /// \param alloc_ptr Pointer to chunk of memory previously allocated by
+  ///                  the allocator.
+  /// \param alloc_size Size of the allocated memory in number of bytes.
+  KOKKOS_FUNCTION
+  void deallocate( void * alloc_ptr, size_t alloc_size ) const
+  {
+    char * ap = static_cast<char *>( alloc_ptr );
+
+    // Only deallocate memory controlled by this pool.
+    if ( ap >= m_data && ap + alloc_size <= m_data + m_data_size ) {
+      // Get the superblock for the address.  This can be calculated by math on
+      // the address since the superblocks are stored contiguously in one memory
+      // chunk.
+      uint32_t sb_id = ( ap - m_data ) >> m_lg_sb_size;
+
+      // Get the starting position for this superblock's bits in the bitset.
+      uint32_t pos_base = sb_id << m_lg_max_sb_blocks;
+
+      // Get the relative position for this memory location's bit in the bitset.
+      uint32_t offset = ( ap - m_data ) - ( size_t(sb_id) << m_lg_sb_size );
+      uint32_t lg_block_size = m_sb_header(sb_id).m_lg_block_size;
+      uint32_t block_size_id = lg_block_size - LG_MIN_BLOCK_SIZE;
+      uint32_t pos_rel = offset >> lg_block_size;
+
+      bool success;
+      unsigned prev_val;
+
+      Kokkos::tie( success, prev_val ) = m_sb_blocks.fetch_word_reset( pos_base + pos_rel );
+
+      // If the memory location was previously deallocated, do nothing.
+      if ( success ) {
+        uint32_t page_fill_level = Kokkos::Impl::bit_count( prev_val );
+
+        if ( page_fill_level == 1 ) {
+          // This page is now empty.  Increment the number of empty pages for the
+          // superblock.
+          uint32_t empty_pages = atomic_fetch_add( &m_sb_header(sb_id).m_empty_pages, 1 );
+
+          if ( !volatile_load( &m_sb_header(sb_id).m_is_active ) &&
+               empty_pages == m_blocksize_info[block_size_id].m_pages_per_sb - 1 )
+          {
+            // This deallocation caused the superblock to be empty.  Change the
+            // superblock category from partially full to empty.
+            unsigned pos = block_size_id * m_ceil_num_sb + sb_id;
+
+            if ( m_partfull_sb.reset( pos ) ) {
+              // Reset the empty pages and block size for the superblock.
+              volatile_store( &m_sb_header(sb_id).m_empty_pages, uint32_t(0) );
+              volatile_store( &m_sb_header(sb_id).m_lg_block_size, uint32_t(0) );
+
+              memory_fence();
+
+              m_empty_sb.set( sb_id );
+            }
+          }
+        }
+        else if ( page_fill_level == m_blocksize_info[block_size_id].m_page_full_level ) {
+          // This page is no longer full.  Decrement the number of full pages for
+          // the superblock.
+          uint32_t full_pages = atomic_fetch_sub( &m_sb_header(sb_id).m_full_pages, 1 );
+
+          if ( !volatile_load( &m_sb_header(sb_id).m_is_active ) &&
+               full_pages == m_blocksize_info[block_size_id].m_sb_full_level )
+          {
+            // This deallocation caused the number of full pages to decrease below
+            // the full threshold.  Change the superblock category from full to
+            // partially full.
+            unsigned pos = block_size_id * m_ceil_num_sb + sb_id;
+            m_partfull_sb.set( pos );
+          }
+        }
+      }
+    }
+#ifdef KOKKOS_MEMPOOL_PRINTERR
+    else {
+      printf( "\n** MemoryPool::deallocate() ADDRESS_OUT_OF_RANGE(0x%llx) **\n",
+              reinterpret_cast<uint64_t>( alloc_ptr ) );
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+      fflush( stdout );
+#endif
+    }
+#endif
+  }
+
+  /// \brief Tests if the memory pool has no more memory available to allocate.
+  KOKKOS_INLINE_FUNCTION
+  bool is_empty() const
+  {
+    // The allocator is empty if all superblocks are full.  A superblock is
+    // full if it has >= 80% of its pages allocated.
+
+    // Look at all the superblocks.  If one is not full, then the allocator
+    // isn't empty.
+    for ( size_t i = 0; i < m_num_sb; ++i ) {
+      uint32_t lg_block_size = m_sb_header(i).m_lg_block_size;
+
+      // A superblock only has a block size of 0 when it is empty.
+      if ( lg_block_size == 0 ) return false;
+
+      uint32_t block_size_id = lg_block_size - LG_MIN_BLOCK_SIZE;
+      uint32_t full_pages = volatile_load( &m_sb_header(i).m_full_pages );
+
+      if ( full_pages < m_blocksize_info[block_size_id].m_sb_full_level ) return false;
+    }
+
+    // All the superblocks were full.  The allocator is empty.
+    return true;
+  }
+
+  // The following functions are used for debugging.
+  void print_status() const
+  {
+    printf( "\n" );
+
+#ifdef KOKKOS_MEMPOOL_PRINT_SUPERBLOCK_INFO
+    typename SBHeaderView::HostMirror host_sb_header = create_mirror_view(m_sb_header);
+    deep_copy( host_sb_header, m_sb_header );
+
+    UInt32View num_allocated_blocks( "Allocated Blocks", m_num_sb );
+
+    // Count the number of allocated blocks per superblock.
+    {
+      MempoolImpl::count_allocated_blocks< UInt32View, SBHeaderView, MempoolBitset >
+        mch( m_num_sb, num_allocated_blocks, m_sb_header,
+             m_sb_blocks, m_sb_size, m_lg_max_sb_blocks );
+    }
+
+    typename UInt32View::HostMirror host_num_allocated_blocks =
+      create_mirror_view(num_allocated_blocks);
+    deep_copy( host_num_allocated_blocks, num_allocated_blocks );
+
+    // Print header info of all superblocks.
+    printf( "SB_ID    SIZE    ACTIVE    EMPTY_PAGES    FULL_PAGES    USED_BLOCKS\n" );
+    for ( size_t i = 0; i < m_num_sb; ++i ) {
+      printf( "%5zu    %4u    %6d    %11u    %10u     %10u\n", i,
+              host_sb_header(i).m_lg_block_size, host_sb_header(i).m_is_active,
+              host_sb_header(i).m_empty_pages, host_sb_header(i).m_full_pages,
+              host_num_allocated_blocks(i) );
+    }
+
+    printf( "\n" );
+#endif
+
+    UInt32View page_histogram( "Page Histogram", 33 );
+
+    // Get a View version of the blocksize info.
+    typedef View< BlockSizeHeader *, device_type >  BSHeaderView;
+    BSHeaderView blocksize_info( "BlockSize Headers", MAX_BLOCK_SIZES );
+
+    Kokkos::Impl::DeepCopy< backend_memory_space, Kokkos::HostSpace >
+      dc( blocksize_info.ptr_on_device(), m_blocksize_info,
+          sizeof(BlockSizeHeader) * m_num_block_size );
+
+    Kokkos::pair< double, uint32_t > result = Kokkos::pair< double, uint32_t >( 0.0, 0 );
+
+    // Create the page histogram.
+    {
+      MempoolImpl::create_histogram< UInt32View, BSHeaderView, SBHeaderView, MempoolBitset >
+        mch( 0, m_num_sb, page_histogram, blocksize_info, m_sb_header, m_sb_blocks,
+             m_lg_max_sb_blocks, LG_MIN_BLOCK_SIZE, BLOCKS_PER_PAGE, result );
+    }
+
+    typename UInt32View::HostMirror host_page_histogram = create_mirror_view(page_histogram);
+    deep_copy( host_page_histogram, page_histogram );
+
+    // Find the used and total pages and blocks.
+    uint32_t used_pages = 0;
+    uint32_t used_blocks = 0;
+    for ( uint32_t i = 1; i < 33; ++i ) {
+      used_pages += host_page_histogram(i);
+      used_blocks += i * host_page_histogram(i);
+    }
+    uint32_t total_pages = used_pages + host_page_histogram(0);
+
+    unsigned num_empty_sb = m_empty_sb.count();
+    unsigned num_non_empty_sb = m_num_sb - num_empty_sb;
+    unsigned num_partfull_sb = m_partfull_sb.count();
+
+    uint32_t total_blocks = result.second;
+    double ave_sb_full = num_non_empty_sb == 0 ? 0.0 : result.first / num_non_empty_sb;
+    double percent_used_sb = double( m_num_sb - num_empty_sb ) / m_num_sb;
+    double percent_used_pages = total_pages == 0 ? 0.0 : double(used_pages) / total_pages;
+    double percent_used_blocks = total_blocks == 0 ? 0.0 : double(used_blocks) / total_blocks;
+
+    // Count active superblocks.
+    typename UInt32View::HostMirror host_active = create_mirror_view(m_active);
+    deep_copy(host_active, m_active);
+
+    unsigned num_active_sb = 0;
+    for ( size_t i = 0; i < m_num_block_size; ++i ) {
+      num_active_sb += host_active(i) != INVALID_SUPERBLOCK;
+    }
+
+#ifdef KOKKOS_MEMPOOL_PRINT_ACTIVE_SUPERBLOCKS
+    // Print active superblocks.
+    printf( "BS_ID      SB_ID\n" );
+    for ( size_t i = 0; i < m_num_block_size; ++i ) {
+      uint32_t sb_id = host_active(i);
+
+      if ( sb_id == INVALID_SUPERBLOCK ) {
+        printf( "%5zu          I\n", i );
+      }
+      else if ( sb_id == SUPERBLOCK_LOCK ) {
+        printf( "%5zu          L\n", i );
+      }
+      else {
+        printf( "%5zu    %7u\n", i, sb_id );
+      }
+    }
+    printf( "\n" );
+    fflush( stdout );
+#endif
+
+#ifdef KOKKOS_MEMPOOL_PRINT_PAGE_INFO
+    // Print the summary page histogram.
+    printf( "USED_BLOCKS    PAGE_COUNT\n" );
+    for ( uint32_t i = 0; i < 33; ++i ) {
+      printf( "%10u    %10u\n", i, host_page_histogram[i] );
+    }
+    printf( "\n" );
+#endif
+
+#ifdef KOKKOS_MEMPOOL_PRINT_INDIVIDUAL_PAGE_INFO
+    // Print the page histogram for a few individual superblocks.
+//    const uint32_t num_sb_id = 2;
+//    uint32_t sb_id[num_sb_id] = { 0, 10 };
+    const uint32_t num_sb_id = 1;
+    uint32_t sb_id[num_sb_id] = { 0 };
+
+    for ( uint32_t i = 0; i < num_sb_id; ++i ) {
+      deep_copy( page_histogram, 0 );
+
+      {
+        MempoolImpl::create_histogram< UInt32View, BSHeaderView, SBHeaderView, MempoolBitset >
+          mch( sb_id[i], sb_id[i] + 1, page_histogram, blocksize_info, m_sb_header,
+               m_sb_blocks, m_lg_max_sb_blocks, LG_MIN_BLOCK_SIZE, BLOCKS_PER_PAGE, result );
+      }
+
+      deep_copy( host_page_histogram, page_histogram );
+
+      printf( "SB_ID    USED_BLOCKS    PAGE_COUNT\n" );
+      for ( uint32_t j = 0; j < 33; ++j ) {
+        printf( "%5u    %10u    %10u\n", sb_id[i], j, host_page_histogram[j] );
+      }
+      printf( "\n" );
+    }
+
+/*
+    // Print the blocks used for each page of a few individual superblocks.
+    for ( uint32_t i = 0; i < num_sb_id; ++i ) {
+      uint32_t lg_block_size = host_sb_header(sb_id[i]).m_lg_block_size;
+      if ( lg_block_size != 0 ) {
+        printf( "SB_ID    BLOCK ID    USED_BLOCKS\n" );
+
+        uint32_t block_size_id = lg_block_size - LG_MIN_BLOCK_SIZE;
+        uint32_t pages_per_sb = m_blocksize_info[block_size_id].m_pages_per_sb;
+
+        for ( uint32_t j = 0; j < pages_per_sb; ++j ) {
+          unsigned start_pos = ( sb_id[i] << m_lg_max_sb_blocks ) + j * BLOCKS_PER_PAGE;
+          unsigned end_pos = start_pos + BLOCKS_PER_PAGE;
+          uint32_t num_allocated_blocks = 0;
+
+          for ( unsigned k = start_pos; k < end_pos; ++k ) {
+            num_allocated_blocks += m_sb_blocks.test( k );
+          }
+
+          printf( "%5u    %8u    %11u\n", sb_id[i], j, num_allocated_blocks );
+        }
+
+        printf( "\n" );
+      }
+    }
+*/
+#endif
+
+    printf( "   Used blocks: %10u / %10u = %10.6lf\n", used_blocks, total_blocks,
+           percent_used_blocks );
+    printf( "    Used pages: %10u / %10u = %10.6lf\n", used_pages, total_pages,
+           percent_used_pages );
+    printf( "       Used SB: %10zu / %10zu = %10.6lf\n", m_num_sb - num_empty_sb, m_num_sb,
+           percent_used_sb );
+    printf( "     Active SB: %10u\n", num_active_sb );
+    printf( "      Empty SB: %10u\n", num_empty_sb );
+    printf( "   Partfull SB: %10u\n", num_partfull_sb );
+    printf( "       Full SB: %10lu\n",
+           m_num_sb - num_active_sb - num_empty_sb - num_partfull_sb );
+    printf( "Ave. SB Full %%: %10.6lf\n", ave_sb_full );
+    printf( "\n" );
+    fflush( stdout );
+
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+    fflush( stdout );
+#endif
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t get_min_block_size() const { return MIN_BLOCK_SIZE; }
+
+  size_t get_mem_size() const { return m_data_size; }
+
+private:
+  /// \brief Returns the index into the active array for the given size.
+  ///
+  /// Computes log2 of the largest power of two >= the given size
+  /// ( ie ceil( log2(size) ) ) shifted by LG_MIN_BLOCK_SIZE.
+  KOKKOS_FORCEINLINE_FUNCTION
+  int get_block_size_index( const size_t size ) const
+  {
+    // We know the size fits in a 32 bit unsigned because the size of a
+    // superblock is limited to 2^31, so casting to an unsigned is safe.
+
+    // Find the most significant nonzero bit.
+    uint32_t first_nonzero_bit =
+      Kokkos::Impl::bit_scan_reverse( static_cast<unsigned>( size ) );
+
+    // If size is an integral power of 2, ceil( log2(size) ) is equal to the
+    // most significant nonzero bit.  Otherwise, you need to add 1.  Since the
+    // minimum block size is MIN_BLOCK_SIZE, make sure ceil( log2(size) ) is at
+    // least LG_MIN_BLOCK_SIZE.
+    uint32_t lg2_size = first_nonzero_bit + !Kokkos::Impl::is_integral_power_of_two( size );
+    lg2_size = lg2_size > LG_MIN_BLOCK_SIZE ? lg2_size : LG_MIN_BLOCK_SIZE;
+
+    // Return ceil( log2(size) ) shifted so that the value for MIN_BLOCK_SIZE
+    // is 0.
+    return lg2_size - LG_MIN_BLOCK_SIZE;
+  }
+
+  /// \brief Finds a superblock with free space to become a new active superblock.
+  ///
+  /// If this function is called, the current active superblock needs to be replaced
+  /// because it is full.  Initially, only the thread that sets the active superblock
+  /// to full calls this function.  Other threads can still allocate from the "full"
+  /// active superblock because a full superblock still has locations available.  If
+  /// a thread tries to allocate from the active superblock when it has no free
+  /// locations, then that thread will call this function, too, and spin on a lock
+  /// waiting until the active superblock has been replaced.
+  KOKKOS_FUNCTION
+  uint32_t find_superblock( int block_size_id, uint32_t old_sb ) const
+  {
+    // Try to grab the lock on the head.
+    uint32_t lock_sb =
+      Kokkos::atomic_compare_exchange( &m_active(block_size_id), old_sb, SUPERBLOCK_LOCK );
+
+    // Initialize the new superblock to be the previous one so the previous
+    // superblock is returned if a new superblock can't be found.
+    uint32_t new_sb = lock_sb;
+
+    if ( lock_sb == old_sb ) {
+      // This thread has the lock.
+
+      // 1. Look for a partially filled superblock that is of the right block
+      //    size.
+
+      size_t max_tries = m_ceil_num_sb >> LG_BLOCKS_PER_PAGE;
+      size_t tries = 0;
+      bool search_done = false;
+
+      // Set the starting search position to the beginning of this block
+      // size's bitset.
+      unsigned pos = block_size_id * m_ceil_num_sb;
+
+      while (!search_done) {
+        bool success = false;
+        unsigned prev_val;
+
+        Kokkos::tie( success, pos ) = m_partfull_sb.reset_any_in_word( pos, prev_val );
+
+        if ( !success ) {
+          if ( ++tries >= max_tries ) {
+            // Exceeded number of words for this block size's bitset.
+            search_done = true;
+          }
+          else {
+            pos += BLOCKS_PER_PAGE;
+          }
+        }
+        else {
+          // Found a superblock.
+          search_done = true;
+          new_sb = pos - block_size_id * m_ceil_num_sb;
+
+          // Assertions:
+          //   1. A different superblock than the current should be found.
+#ifdef KOKKOS_MEMPOOL_PRINTERR
+          if ( new_sb == lock_sb ) {
+            printf( "\n** MemoryPool::find_superblock() FOUND_SAME_SUPERBLOCK: %u **\n",
+                    new_sb);
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+            fflush( stdout );
+#endif
+            Kokkos::abort( "" );
+          }
+#endif
+
+          // Set the head status for the superblock.
+          volatile_store( &m_sb_header(new_sb).m_is_active, uint32_t(true) );
+
+          // If there was a previous active superblock, mark it as not active.
+          // It is now in the full category and as such isn't tracked.
+          if ( lock_sb != INVALID_SUPERBLOCK ) {
+            volatile_store( &m_sb_header(lock_sb).m_is_active, uint32_t(false) );
+          }
+
+          memory_fence();
+        }
+      }
+
+      // 2. Look for an empty superblock.
+      if ( new_sb == lock_sb ) {
+        tries = 0;
+        search_done = false;
+
+        // Set the starting search position to the beginning of this block
+        // size's bitset.
+        pos = 0;
+
+        while (!search_done) {
+          bool success = false;
+          unsigned prev_val;
+
+          Kokkos::tie( success, pos ) = m_empty_sb.reset_any_in_word( pos, prev_val );
+
+          if ( !success ) {
+            if ( ++tries >= max_tries ) {
+              // Exceeded number of words for this block size's bitset.
+              search_done = true;
+            }
+            else {
+              pos += BLOCKS_PER_PAGE;
+            }
+          }
+          else {
+            // Found a superblock.
+            search_done = true;
+            new_sb = pos;
+
+            // Assertions:
+            //   1. A different superblock than the current should be found.
+#ifdef KOKKOS_MEMPOOL_PRINTERR
+            if ( new_sb == lock_sb ) {
+              printf( "\n** MemoryPool::find_superblock() FOUND_SAME_SUPERBLOCK: %u **\n",
+                      new_sb);
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+              fflush( stdout );
+#endif
+              Kokkos::abort( "" );
+            }
+#endif
+
+            // Set the empty pages, block size, and head status for the
+            // superblock.
+            volatile_store( &m_sb_header(new_sb).m_empty_pages,
+                            m_blocksize_info[block_size_id].m_pages_per_sb );
+            volatile_store( &m_sb_header(new_sb).m_lg_block_size,
+                            block_size_id + LG_MIN_BLOCK_SIZE );
+            volatile_store( &m_sb_header(new_sb).m_is_active, uint32_t(true) );
+
+            // If there was a previous active superblock, mark it as not active.
+            // It is now in the full category and as such isn't tracked.
+            if ( lock_sb != INVALID_SUPERBLOCK ) {
+              volatile_store( &m_sb_header(lock_sb).m_is_active, uint32_t(false) );
+            }
+
+            memory_fence();
+          }
+        }
+      }
+
+      // Write the new active superblock to release the lock.
+      atomic_exchange( &m_active(block_size_id), new_sb );
+    }
+    else {
+      // Either another thread has the lock and is switching the active superblock for
+      // this block size or another thread has already changed the active superblock
+      // since this thread read its value.  Keep reading the active superblock until
+      // it isn't locked to get the new active superblock.
+      do {
+        new_sb = volatile_load( &m_active(block_size_id) );
+      } while ( new_sb == SUPERBLOCK_LOCK );
+
+      // Assertions:
+      //   1. An invalid superblock should never be found here.
+      //   2. If the new superblock is the same as the previous superblock, the
+      //      allocator is empty.
+#ifdef KOKKOS_MEMPOOL_PRINTERR
+      if ( new_sb == INVALID_SUPERBLOCK ) {
+        printf( "\n** MemoryPool::find_superblock() FOUND_INACTIVE_SUPERBLOCK **\n" );
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+        fflush( stdout );
+#endif
+        Kokkos::abort( "" );
+      }
+#endif
+    }
+
+    return new_sb;
+  }
+
+  /// Returns 64 bits from a clock register.
+  KOKKOS_FORCEINLINE_FUNCTION
+  uint64_t get_clock_register(void) const
+  {
+#if defined( __CUDA_ARCH__ )
+    // Return value of 64-bit hi-res clock register.
+	  return clock64();
+#elif defined( __i386__ ) || defined( __x86_64 )
+    // Return value of 64-bit hi-res clock register.
+    unsigned a, d;
+    __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
+    return ( (uint64_t) a) | ( ( (uint64_t) d ) << 32 );
+#else
+    const uint64_t ticks = std::chrono::high_resolution_clock::now().time_since_epoch().count();
+    return ticks;
+#endif
+  }
+};
+
+} // namespace Experimental
+} // namespace Kokkos
+
+#ifdef KOKKOS_MEMPOOL_PRINTERR
+#undef KOKKOS_MEMPOOL_PRINTERR
+#endif
+
+#ifdef KOKKOS_MEMPOOL_PRINT_INFO
+#undef KOKKOS_MEMPOOL_PRINT_INFO
+#endif
+
+#ifdef KOKKOS_MEMPOOL_PRINT_BLOCKSIZE_INFO
+#undef KOKKOS_MEMPOOL_PRINT_BLOCKSIZE_INFO
+#endif
+
+#ifdef KOKKOS_MEMPOOL_PRINT_SUPERBLOCK_INFO
+#undef KOKKOS_MEMPOOL_PRINT_SUPERBLOCK_INFO
+#endif
+
+#ifdef KOKKOS_MEMPOOL_PRINT_PAGE_INFO
+#undef KOKKOS_MEMPOOL_PRINT_PAGE_INFO
+#endif
+
+#ifdef KOKKOS_MEMPOOL_PRINT_INDIVIDUAL_PAGE_INFO
+#undef KOKKOS_MEMPOOL_PRINT_INDIVIDUAL_PAGE_INFO
+#endif
+
+#undef KOKKOS_MEMPOOL_SB_FULL_FRACTION
+#undef KOKKOS_MEMPOOL_PAGE_FULL_FRACTION
+
+#endif // KOKKOS_MEMORYPOOL_HPP
diff --git a/lib/kokkos/core/src/Kokkos_MemoryTraits.hpp b/lib/kokkos/core/src/Kokkos_MemoryTraits.hpp
new file mode 100644
index 0000000000..5ee1f16fec
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_MemoryTraits.hpp
@@ -0,0 +1,116 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_MEMORYTRAITS_HPP
+#define KOKKOS_MEMORYTRAITS_HPP
+
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+/** \brief  Memory access traits for views, an extension point.
+ *
+ *  These traits should be orthogonal.  If there are dependencies then
+ *  the MemoryTraits template must detect and enforce dependencies.
+ *
+ *  A zero value is the default for a View, indicating that none of
+ *  these traits are present.
+ */
+enum MemoryTraitsFlags
+  { Unmanaged  = 0x01
+  , RandomAccess = 0x02
+  , Atomic = 0x04
+  };
+
+template < unsigned T >
+struct MemoryTraits {
+  //! Tag this class as a kokkos memory traits:
+  typedef MemoryTraits memory_traits ;
+
+  enum { Unmanaged    = T & unsigned(Kokkos::Unmanaged) };
+  enum { RandomAccess = T & unsigned(Kokkos::RandomAccess) };
+  enum { Atomic       = T & unsigned(Kokkos::Atomic) };
+
+};
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+typedef Kokkos::MemoryTraits<0> MemoryManaged ;
+typedef Kokkos::MemoryTraits< Kokkos::Unmanaged > MemoryUnmanaged ;
+typedef Kokkos::MemoryTraits< Kokkos::Unmanaged | Kokkos::RandomAccess > MemoryRandomAccess ;
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+/** \brief Memory alignment settings
+ *
+ *  Sets global value for memory alignment.  Must be a power of two!
+ *  Enable compatibility of views from different devices with static stride.
+ *  Use compiler flag to enable overwrites.
+ */
+enum { MEMORY_ALIGNMENT =
+#if defined( KOKKOS_MEMORY_ALIGNMENT )
+    ( 1 << Kokkos::Impl::integral_power_of_two( KOKKOS_MEMORY_ALIGNMENT ) )
+#else
+    ( 1 << Kokkos::Impl::integral_power_of_two( 128 ) )
+#endif
+  , MEMORY_ALIGNMENT_THRESHOLD = 4 
+  };
+
+
+} //namespace Impl
+} // namespace Kokkos
+
+#endif /* #ifndef KOKKOS_MEMORYTRAITS_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_OpenMP.hpp b/lib/kokkos/core/src/Kokkos_OpenMP.hpp
new file mode 100644
index 0000000000..7be4f8245f
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_OpenMP.hpp
@@ -0,0 +1,189 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_OPENMP_HPP
+#define KOKKOS_OPENMP_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+
+#if defined( KOKKOS_HAVE_OPENMP ) && defined( _OPENMP )
+
+#include <omp.h>
+
+#include <cstddef>
+#include <iosfwd>
+#include <Kokkos_HostSpace.hpp>
+#ifdef KOKKOS_HAVE_HBWSPACE
+#include <Kokkos_HBWSpace.hpp>
+#endif
+#include <Kokkos_ScratchSpace.hpp>
+#include <Kokkos_Parallel.hpp>
+#include <Kokkos_TaskPolicy.hpp>
+#include <Kokkos_Layout.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+#include <KokkosExp_MDRangePolicy.hpp>
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/// \class OpenMP
+/// \brief Kokkos device for multicore processors in the host memory space.
+class OpenMP {
+public:
+  //------------------------------------
+  //! \name Type declarations that all Kokkos devices must provide.
+  //@{
+
+  //! Tag this class as a kokkos execution space
+  typedef OpenMP                execution_space ;
+  #ifdef KOKKOS_HAVE_HBWSPACE
+  typedef Experimental::HBWSpace memory_space ;
+  #else
+  typedef HostSpace             memory_space ;
+  #endif
+  //! This execution space preferred device_type
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  typedef LayoutRight           array_layout ;
+  typedef memory_space::size_type  size_type ;
+
+  typedef ScratchMemorySpace< OpenMP > scratch_memory_space ;
+
+  //@}
+  //------------------------------------
+  //! \name Functions that all Kokkos execution spaces must implement.
+  //@{
+
+  inline static bool in_parallel() { return omp_in_parallel(); }
+
+  /** \brief  Set the device in a "sleep" state. A noop for OpenMP.  */
+  static bool sleep();
+
+  /** \brief Wake the device from the 'sleep' state. A noop for OpenMP. */
+  static bool wake();
+
+  /** \brief Wait until all dispatched functors complete. A noop for OpenMP. */
+  static void fence() {}
+
+  /// \brief Print configuration information to the given output stream.
+  static void print_configuration( std::ostream & , const bool detail = false );
+
+  /// \brief Free any resources being consumed by the device.
+  static void finalize();
+
+  /** \brief  Initialize the device.
+   *
+   *  1) If the hardware locality library is enabled and OpenMP has not
+   *     already bound threads then bind OpenMP threads to maximize
+   *     core utilization and group for memory hierarchy locality.
+   *
+   *  2) Allocate a HostThread for each OpenMP thread to hold its
+   *     topology and fan in/out data.
+   */
+  static void initialize( unsigned thread_count = 0 ,
+                          unsigned use_numa_count = 0 ,
+                          unsigned use_cores_per_numa = 0 );
+
+  static int is_initialized();
+
+  /** \brief  Return the maximum amount of concurrency.  */
+  static int concurrency();
+
+  //@}
+  //------------------------------------
+  /** \brief  This execution space has a topological thread pool which can be queried.
+   *
+   *  All threads within a pool have a common memory space for which they are cache coherent.
+   *    depth = 0  gives the number of threads in the whole pool.
+   *    depth = 1  gives the number of threads in a NUMA region, typically sharing L3 cache.
+   *    depth = 2  gives the number of threads at the finest granularity, typically sharing L1 cache.
+   */
+  inline static int thread_pool_size( int depth = 0 );
+
+  /** \brief  The rank of the executing thread in this thread pool */
+  KOKKOS_INLINE_FUNCTION static int thread_pool_rank();
+
+  //------------------------------------
+
+  inline static unsigned max_hardware_threads() { return thread_pool_size(0); }
+
+  KOKKOS_INLINE_FUNCTION static
+  unsigned hardware_thread_id() { return thread_pool_rank(); }
+};
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+struct VerifyExecutionCanAccessMemorySpace
+  < Kokkos::OpenMP::memory_space
+  , Kokkos::OpenMP::scratch_memory_space
+  >
+{
+  enum { value = true };
+  inline static void verify( void ) { }
+  inline static void verify( const void * ) { }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#include <OpenMP/Kokkos_OpenMPexec.hpp>
+#include <OpenMP/Kokkos_OpenMP_Parallel.hpp>
+#include <OpenMP/Kokkos_OpenMP_Task.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+#endif /* #if defined( KOKKOS_HAVE_OPENMP ) && defined( _OPENMP ) */
+#endif /* #ifndef KOKKOS_OPENMP_HPP */
+
+
diff --git a/lib/kokkos/core/src/Kokkos_Pair.hpp b/lib/kokkos/core/src/Kokkos_Pair.hpp
new file mode 100644
index 0000000000..83436826f4
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Pair.hpp
@@ -0,0 +1,530 @@
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+
+/// \file Kokkos_Pair.hpp
+/// \brief Declaration and definition of Kokkos::pair.
+///
+/// This header file declares and defines Kokkos::pair and its related
+/// nonmember functions.
+
+#ifndef KOKKOS_PAIR_HPP
+#define KOKKOS_PAIR_HPP
+
+#include <Kokkos_Macros.hpp>
+#include <utility>
+
+namespace Kokkos {
+/// \struct pair
+/// \brief Replacement for std::pair that works on CUDA devices.
+///
+/// The instance methods of std::pair, including its constructors, are
+/// not marked as <tt>__device__</tt> functions.  Thus, they cannot be
+/// called on a CUDA device, such as an NVIDIA GPU.  This struct
+/// implements the same interface as std::pair, but can be used on a
+/// CUDA device as well as on the host.
+template <class T1, class T2>
+struct pair
+{
+  //! The first template parameter of this class.
+  typedef T1 first_type;
+  //! The second template parameter of this class.
+  typedef T2 second_type;
+
+  //! The first element of the pair.
+  first_type  first;
+  //! The second element of the pair.
+  second_type second;
+
+  /// \brief Default constructor.
+  ///
+  /// This calls the default constructors of T1 and T2.  It won't
+  /// compile if those default constructors are not defined and
+  /// public.
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair()
+    : first(), second()
+  {}
+
+  /// \brief Constructor that takes both elements of the pair.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair(first_type const& f, second_type const& s)
+    : first(f), second(s)
+  {}
+
+  /// \brief Copy constructor.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair( const pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  /// \brief Copy constructor.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair( const volatile pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  /// \brief Assignment operator.
+  ///
+  /// This calls the assignment operators of T1 and T2.  It won't
+  /// compile if the assignment operators are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair<T1, T2> & operator=(const pair<U,V> &p)
+  {
+    first = p.first;
+    second = p.second;
+    return *this;
+  }
+
+
+  /// \brief Assignment operator, for volatile <tt>*this</tt>.
+  ///
+  /// \param p [in] Input; right-hand side of the assignment.
+  ///
+  /// This calls the assignment operators of T1 and T2.  It will not
+  /// compile if the assignment operators are not defined and public.
+  ///
+  /// This operator returns \c void instead of <tt>volatile pair<T1,
+  /// T2>& </tt>.  See Kokkos Issue #177 for the explanation.  In
+  /// practice, this means that you should not chain assignments with
+  /// volatile lvalues.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator=(const volatile pair<U,V> &p) volatile
+  {
+    first = p.first;
+    second = p.second;
+    // We deliberately do not return anything here.  See explanation
+    // in public documentation above.
+  }
+
+  // from std::pair<U,V>
+  template <class U, class V>
+  pair( const std::pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  /// \brief Return the std::pair version of this object.
+  ///
+  /// This is <i>not</i> a device function; you may not call it on a
+  /// CUDA device.  It is meant to be called on the host, if the user
+  /// wants an std::pair instead of a Kokkos::pair.
+  ///
+  /// \note This is not a conversion operator, since defining a
+  ///   conversion operator made the relational operators have
+  ///   ambiguous definitions.
+  std::pair<T1,T2> to_std_pair() const
+  { return std::make_pair(first,second); }
+};
+
+template <class T1, class T2>
+struct pair<T1&, T2&>
+{
+  //! The first template parameter of this class.
+  typedef T1& first_type;
+  //! The second template parameter of this class.
+  typedef T2& second_type;
+
+  //! The first element of the pair.
+  first_type  first;
+  //! The second element of the pair.
+  second_type second;
+
+  /// \brief Constructor that takes both elements of the pair.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair(first_type f, second_type s)
+    : first(f), second(s)
+  {}
+
+  /// \brief Copy constructor.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair( const pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  // from std::pair<U,V>
+  template <class U, class V>
+  pair( const std::pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  /// \brief Assignment operator.
+  ///
+  /// This calls the assignment operators of T1 and T2.  It won't
+  /// compile if the assignment operators are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair<first_type, second_type> & operator=(const pair<U,V> &p)
+  {
+    first = p.first;
+    second = p.second;
+    return *this;
+  }
+
+  /// \brief Return the std::pair version of this object.
+  ///
+  /// This is <i>not</i> a device function; you may not call it on a
+  /// CUDA device.  It is meant to be called on the host, if the user
+  /// wants an std::pair instead of a Kokkos::pair.
+  ///
+  /// \note This is not a conversion operator, since defining a
+  ///   conversion operator made the relational operators have
+  ///   ambiguous definitions.
+  std::pair<T1,T2> to_std_pair() const
+  { return std::make_pair(first,second); }
+};
+
+template <class T1, class T2>
+struct pair<T1, T2&>
+{
+  //! The first template parameter of this class.
+  typedef T1  first_type;
+  //! The second template parameter of this class.
+  typedef T2& second_type;
+
+  //! The first element of the pair.
+  first_type  first;
+  //! The second element of the pair.
+  second_type second;
+
+  /// \brief Constructor that takes both elements of the pair.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair(first_type const& f, second_type s)
+    : first(f), second(s)
+  {}
+
+  /// \brief Copy constructor.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair( const pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  // from std::pair<U,V>
+  template <class U, class V>
+  pair( const std::pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  /// \brief Assignment operator.
+  ///
+  /// This calls the assignment operators of T1 and T2.  It won't
+  /// compile if the assignment operators are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair<first_type, second_type> & operator=(const pair<U,V> &p)
+  {
+    first = p.first;
+    second = p.second;
+    return *this;
+  }
+
+  /// \brief Return the std::pair version of this object.
+  ///
+  /// This is <i>not</i> a device function; you may not call it on a
+  /// CUDA device.  It is meant to be called on the host, if the user
+  /// wants an std::pair instead of a Kokkos::pair.
+  ///
+  /// \note This is not a conversion operator, since defining a
+  ///   conversion operator made the relational operators have
+  ///   ambiguous definitions.
+  std::pair<T1,T2> to_std_pair() const
+  { return std::make_pair(first,second); }
+};
+
+template <class T1, class T2>
+struct pair<T1&, T2>
+{
+  //! The first template parameter of this class.
+  typedef T1&  first_type;
+  //! The second template parameter of this class.
+  typedef T2 second_type;
+
+  //! The first element of the pair.
+  first_type  first;
+  //! The second element of the pair.
+  second_type second;
+
+  /// \brief Constructor that takes both elements of the pair.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair(first_type f, second_type const& s)
+    : first(f), second(s)
+  {}
+
+  /// \brief Copy constructor.
+  ///
+  /// This calls the copy constructors of T1 and T2.  It won't compile
+  /// if those copy constructors are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair( const pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  // from std::pair<U,V>
+  template <class U, class V>
+  pair( const std::pair<U,V> &p)
+    : first(p.first), second(p.second)
+  {}
+
+  /// \brief Assignment operator.
+  ///
+  /// This calls the assignment operators of T1 and T2.  It won't
+  /// compile if the assignment operators are not defined and public.
+  template <class U, class V>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair<first_type, second_type> & operator=(const pair<U,V> &p)
+  {
+    first = p.first;
+    second = p.second;
+    return *this;
+  }
+
+  /// \brief Return the std::pair version of this object.
+  ///
+  /// This is <i>not</i> a device function; you may not call it on a
+  /// CUDA device.  It is meant to be called on the host, if the user
+  /// wants an std::pair instead of a Kokkos::pair.
+  ///
+  /// \note This is not a conversion operator, since defining a
+  ///   conversion operator made the relational operators have
+  ///   ambiguous definitions.
+  std::pair<T1,T2> to_std_pair() const
+  { return std::make_pair(first,second); }
+};
+
+//! Equality operator for Kokkos::pair.
+template <class T1, class T2>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator== (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
+{ return lhs.first==rhs.first && lhs.second==rhs.second; }
+
+//! Inequality operator for Kokkos::pair.
+template <class T1, class T2>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator!= (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
+{ return !(lhs==rhs); }
+
+//! Less-than operator for Kokkos::pair.
+template <class T1, class T2>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator<  (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
+{ return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second); }
+
+//! Less-than-or-equal-to operator for Kokkos::pair.
+template <class T1, class T2>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator<= (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
+{ return !(rhs<lhs); }
+
+//! Greater-than operator for Kokkos::pair.
+template <class T1, class T2>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator>  (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
+{ return rhs<lhs; }
+
+//! Greater-than-or-equal-to operator for Kokkos::pair.
+template <class T1, class T2>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator>= (const pair<T1,T2>& lhs, const pair<T1,T2>& rhs)
+{ return !(lhs<rhs); }
+
+/// \brief Return a new pair.
+///
+/// This is a "nonmember constructor" for Kokkos::pair.  It works just
+/// like std::make_pair.
+template <class T1,class T2>
+KOKKOS_FORCEINLINE_FUNCTION
+pair<T1,T2> make_pair (T1 x, T2 y)
+{ return ( pair<T1,T2>(x,y) ); }
+
+/// \brief Return a pair of references to the input arguments.
+///
+/// This compares to std::tie (new in C++11).  You can use it to
+/// assign to two variables at once, from the result of a function
+/// that returns a pair.  For example (<tt>__device__</tt> and
+/// <tt>__host__</tt> attributes omitted for brevity):
+/// \code
+/// // Declaration of the function to call.
+/// // First return value: operation count.
+/// // Second return value: whether all operations succeeded.
+/// Kokkos::pair<int, bool> someFunction ();
+///
+/// // Code that uses Kokkos::tie.
+/// int myFunction () {
+///   int count = 0;
+///   bool success = false;
+///
+///   // This assigns to both count and success.
+///   Kokkos::tie (count, success) = someFunction ();
+///
+///   if (! success) {
+///     // ... Some operation failed;
+///     //     take corrective action ...
+///   }
+///   return count;
+/// }
+/// \endcode
+///
+/// The line that uses tie() could have been written like this:
+/// \code
+///   Kokkos::pair<int, bool> result = someFunction ();
+///   count = result.first;
+///   success = result.second;
+/// \endcode
+///
+/// Using tie() saves two lines of code and avoids a copy of each
+/// element of the pair.  The latter could be significant if one or
+/// both elements of the pair are more substantial objects than \c int
+/// or \c bool.
+template <class T1,class T2>
+KOKKOS_FORCEINLINE_FUNCTION
+pair<T1 &,T2 &> tie (T1 & x, T2 & y)
+{ return ( pair<T1 &,T2 &>(x,y) ); }
+
+//
+// Specialization of Kokkos::pair for a \c void second argument.  This
+// is not actually a "pair"; it only contains one element, the first.
+//
+template <class T1>
+struct pair<T1,void>
+{
+  typedef T1 first_type;
+  typedef void second_type;
+
+  first_type  first;
+  enum { second = 0 };
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair()
+    : first()
+  {}
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair(const first_type & f)
+    : first(f)
+  {}
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair(const first_type & f, int)
+    : first(f)
+  {}
+
+  template <class U>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair( const pair<U,void> &p)
+    : first(p.first)
+  {}
+
+  template <class U>
+  KOKKOS_FORCEINLINE_FUNCTION
+  pair<T1, void> & operator=(const pair<U,void> &p)
+  {
+    first = p.first;
+    return *this;
+  }
+};
+
+//
+// Specialization of relational operators for Kokkos::pair<T1,void>.
+//
+
+template <class T1>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator== (const pair<T1,void>& lhs, const pair<T1,void>& rhs)
+{ return lhs.first==rhs.first; }
+
+template <class T1>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator!= (const pair<T1,void>& lhs, const pair<T1,void>& rhs)
+{ return !(lhs==rhs); }
+
+template <class T1>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator<  (const pair<T1,void>& lhs, const pair<T1,void>& rhs)
+{ return lhs.first<rhs.first; }
+
+template <class T1>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator<= (const pair<T1,void>& lhs, const pair<T1,void>& rhs)
+{ return !(rhs<lhs); }
+
+template <class T1>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator>  (const pair<T1,void>& lhs, const pair<T1,void>& rhs)
+{ return rhs<lhs; }
+
+template <class T1>
+KOKKOS_FORCEINLINE_FUNCTION
+bool operator>= (const pair<T1,void>& lhs, const pair<T1,void>& rhs)
+{ return !(lhs<rhs); }
+
+} // namespace Kokkos
+
+
+#endif //KOKKOS_PAIR_HPP
diff --git a/lib/kokkos/core/src/Kokkos_Parallel.hpp b/lib/kokkos/core/src/Kokkos_Parallel.hpp
new file mode 100644
index 0000000000..588dc90af3
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Parallel.hpp
@@ -0,0 +1,527 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/// \file Kokkos_Parallel.hpp
+/// \brief Declaration of parallel operators
+
+#ifndef KOKKOS_PARALLEL_HPP
+#define KOKKOS_PARALLEL_HPP
+
+#include <cstddef>
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_View.hpp>
+#include <Kokkos_ExecPolicy.hpp>
+
+#if (KOKKOS_ENABLE_PROFILING)
+#include <impl/Kokkos_Profiling_Interface.hpp>
+#include <typeinfo>
+#endif
+
+#include <impl/Kokkos_Tags.hpp>
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_FunctorAdapter.hpp>
+
+#ifdef KOKKOS_HAVE_DEBUG
+#include<iostream>
+#endif
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+/** \brief  Given a Functor and Execution Policy query an execution space.
+ *
+ *  if       the Policy has an execution space use that
+ *  else if  the Functor has an execution_space use that
+ *  else if  the Functor has a device_type use that for backward compatibility
+ *  else     use the default
+ */
+template< class Functor
+        , class Policy
+        , class EnableFunctor
+        , class EnablePolicy
+        >
+struct FunctorPolicyExecutionSpace {
+  typedef Kokkos::DefaultExecutionSpace execution_space ;
+};
+
+template< class Functor , class Policy >
+struct FunctorPolicyExecutionSpace
+  < Functor , Policy
+  , typename enable_if_type< typename Functor::device_type     >::type
+  , typename enable_if_type< typename Policy ::execution_space >::type
+  >
+{
+  typedef typename Policy ::execution_space execution_space ;
+};
+
+template< class Functor , class Policy >
+struct FunctorPolicyExecutionSpace
+  < Functor , Policy
+  , typename enable_if_type< typename Functor::execution_space >::type
+  , typename enable_if_type< typename Policy ::execution_space >::type
+  >
+{
+  typedef typename Policy ::execution_space execution_space ;
+};
+
+template< class Functor , class Policy , class EnableFunctor >
+struct FunctorPolicyExecutionSpace
+  < Functor , Policy
+  , EnableFunctor
+  , typename enable_if_type< typename Policy::execution_space >::type
+  >
+{
+  typedef typename Policy ::execution_space execution_space ;
+};
+
+template< class Functor , class Policy , class EnablePolicy >
+struct FunctorPolicyExecutionSpace
+  < Functor , Policy
+  , typename enable_if_type< typename Functor::device_type >::type
+  , EnablePolicy
+  >
+{
+  typedef typename Functor::device_type execution_space ;
+};
+
+template< class Functor , class Policy , class EnablePolicy >
+struct FunctorPolicyExecutionSpace
+  < Functor , Policy
+  , typename enable_if_type< typename Functor::execution_space >::type
+  , EnablePolicy
+  >
+{
+  typedef typename Functor::execution_space execution_space ;
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+/** \brief Execute \c functor in parallel according to the execution \c policy.
+ *
+ * A "functor" is a class containing the function to execute in parallel,
+ * data needed for that execution, and an optional \c execution_space
+ * typedef.  Here is an example functor for parallel_for:
+ *
+ * \code
+ *  class FunctorType {
+ *  public:
+ *    typedef  ...  execution_space ;
+ *    void operator() ( WorkType iwork ) const ;
+ *  };
+ * \endcode
+ *
+ * In the above example, \c WorkType is any integer type for which a
+ * valid conversion from \c size_t to \c IntType exists.  Its
+ * <tt>operator()</tt> method defines the operation to parallelize,
+ * over the range of integer indices <tt>iwork=[0,work_count-1]</tt>.
+ * This compares to a single iteration \c iwork of a \c for loop.
+ * If \c execution_space is not defined DefaultExecutionSpace will be used.
+ */
+template< class ExecPolicy , class FunctorType >
+inline
+void parallel_for( const ExecPolicy  & policy
+                 , const FunctorType & functor
+                 , const std::string& str = ""
+                 , typename Impl::enable_if< ! Impl::is_integral< ExecPolicy >::value >::type * = 0
+                 )
+{
+#if (KOKKOS_ENABLE_PROFILING)
+    uint64_t kpID = 0;
+     if(Kokkos::Profiling::profileLibraryLoaded()) {
+     	Kokkos::Profiling::beginParallelFor("" == str ? typeid(FunctorType).name() : str, 0, &kpID);
+     }
+#endif
+
+    Kokkos::Impl::shared_allocation_tracking_claim_and_disable();
+    Impl::ParallelFor< FunctorType , ExecPolicy > closure( functor , policy );
+    Kokkos::Impl::shared_allocation_tracking_release_and_enable();
+   
+   closure.execute();
+
+#if (KOKKOS_ENABLE_PROFILING)
+     if(Kokkos::Profiling::profileLibraryLoaded()) {
+        Kokkos::Profiling::endParallelFor(kpID);
+     }
+#endif
+}
+
+template< class FunctorType >
+inline
+void parallel_for( const size_t        work_count
+                 , const FunctorType & functor
+                 , const std::string& str = ""
+                 )
+{
+  typedef typename
+    Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
+      execution_space ;
+  typedef RangePolicy< execution_space > policy ;
+
+#if (KOKKOS_ENABLE_PROFILING)
+  uint64_t kpID = 0;
+     if(Kokkos::Profiling::profileLibraryLoaded()) {
+  	Kokkos::Profiling::beginParallelFor("" == str ? typeid(FunctorType).name() : str, 0, &kpID);
+     }
+#endif
+    
+  Kokkos::Impl::shared_allocation_tracking_claim_and_disable();
+  Impl::ParallelFor< FunctorType , policy > closure( functor , policy(0,work_count) );
+  Kokkos::Impl::shared_allocation_tracking_release_and_enable();
+
+  closure.execute();
+
+#if (KOKKOS_ENABLE_PROFILING)
+     if(Kokkos::Profiling::profileLibraryLoaded()) {
+	Kokkos::Profiling::endParallelFor(kpID);
+     }
+#endif
+}
+
+template< class ExecPolicy , class FunctorType >
+inline
+void parallel_for( const std::string & str
+                 , const ExecPolicy  & policy
+                 , const FunctorType & functor )
+{
+  #if KOKKOS_ENABLE_DEBUG_PRINT_KERNEL_NAMES
+  Kokkos::fence();
+  std::cout << "KOKKOS_DEBUG Start parallel_for kernel: " << str << std::endl;
+  #endif
+
+  parallel_for(policy,functor,str);
+
+  #if KOKKOS_ENABLE_DEBUG_PRINT_KERNEL_NAMES
+  Kokkos::fence();
+  std::cout << "KOKKOS_DEBUG End   parallel_for kernel: " << str << std::endl;
+  #endif
+  (void) str;
+}
+
+}
+
+#include <Kokkos_Parallel_Reduce.hpp>
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+/// \fn parallel_scan
+/// \tparam ExecutionPolicy The execution policy type.
+/// \tparam FunctorType     The scan functor type.
+///
+/// \param policy  [in] The execution policy.
+/// \param functor [in] The scan functor.
+///
+/// This function implements a parallel scan pattern.  The scan can
+/// be either inclusive or exclusive, depending on how you implement
+/// the scan functor.
+///
+/// A scan functor looks almost exactly like a reduce functor, except
+/// that its operator() takes a third \c bool argument, \c final_pass,
+/// which indicates whether this is the last pass of the scan
+/// operation.  We will show below how to use the \c final_pass
+/// argument to control whether the scan is inclusive or exclusive.
+///
+/// Here is the minimum required interface of a scan functor for a POD
+/// (plain old data) value type \c PodType.  That is, the result is a
+/// View of zero or more PodType.  It is also possible for the result
+/// to be an array of (same-sized) arrays of PodType, but we do not
+/// show the required interface for that here.
+/// \code
+/// template< class ExecPolicy , class FunctorType >
+/// class ScanFunctor {
+/// public:
+///   // The Kokkos device type
+///   typedef ... execution_space;
+///   // Type of an entry of the array containing the result;
+///   // also the type of each of the entries combined using
+///   // operator() or join().
+///   typedef PodType value_type;
+///
+///   void operator () (const ExecPolicy::member_type & i, value_type& update, const bool final_pass) const;
+///   void init (value_type& update) const;
+///   void join (volatile value_type& update, volatile const value_type& input) const
+/// };
+/// \endcode
+///
+/// Here is an example of a functor which computes an inclusive plus-scan
+/// of an array of \c int, in place.  If given an array [1, 2, 3, 4], this
+/// scan will overwrite that array with [1, 3, 6, 10].
+///
+/// \code
+/// template<class SpaceType>
+/// class InclScanFunctor {
+/// public:
+///   typedef SpaceType execution_space;
+///   typedef int value_type;
+///   typedef typename SpaceType::size_type size_type;
+///
+///   InclScanFunctor( Kokkos::View<value_type*, execution_space> x
+///                  , Kokkos::View<value_type*, execution_space> y ) : m_x(x), m_y(y) {}
+///
+///   void operator () (const size_type i, value_type& update, const bool final_pass) const {
+///     update += m_x(i);
+///     if (final_pass) {
+///       m_y(i) = update;
+///     }
+///   }
+///   void init (value_type& update) const {
+///     update = 0;
+///   }
+///   void join (volatile value_type& update, volatile const value_type& input) const {
+///     update += input;
+///   }
+///
+/// private:
+///   Kokkos::View<value_type*, execution_space> m_x;
+///   Kokkos::View<value_type*, execution_space> m_y;
+/// };
+/// \endcode
+///
+/// Here is an example of a functor which computes an <i>exclusive</i>
+/// scan of an array of \c int, in place.  In operator(), note both
+/// that the final_pass test and the update have switched places, and
+/// the use of a temporary.  If given an array [1, 2, 3, 4], this scan
+/// will overwrite that array with [0, 1, 3, 6].
+///
+/// \code
+/// template<class SpaceType>
+/// class ExclScanFunctor {
+/// public:
+///   typedef SpaceType execution_space;
+///   typedef int value_type;
+///   typedef typename SpaceType::size_type size_type;
+///
+///   ExclScanFunctor (Kokkos::View<value_type*, execution_space> x) : x_ (x) {}
+///
+///   void operator () (const size_type i, value_type& update, const bool final_pass) const {
+///     const value_type x_i = x_(i);
+///     if (final_pass) {
+///       x_(i) = update;
+///     }
+///     update += x_i;
+///   }
+///   void init (value_type& update) const {
+///     update = 0;
+///   }
+///   void join (volatile value_type& update, volatile const value_type& input) const {
+///     update += input;
+///   }
+///
+/// private:
+///   Kokkos::View<value_type*, execution_space> x_;
+/// };
+/// \endcode
+///
+/// Here is an example of a functor which builds on the above
+/// exclusive scan example, to compute an offsets array from a
+/// population count array, in place.  We assume that the pop count
+/// array has an extra entry at the end to store the final count.  If
+/// given an array [1, 2, 3, 4, 0], this scan will overwrite that
+/// array with [0, 1, 3, 6, 10].
+///
+/// \code
+/// template<class SpaceType>
+/// class OffsetScanFunctor {
+/// public:
+///   typedef SpaceType execution_space;
+///   typedef int value_type;
+///   typedef typename SpaceType::size_type size_type;
+///
+///   // lastIndex_ is the last valid index (zero-based) of x.
+///   // If x has length zero, then lastIndex_ won't be used anyway.
+///   OffsetScanFunctor( Kokkos::View<value_type*, execution_space> x
+///                    , Kokkos::View<value_type*, execution_space> y )
+///      : m_x(x), m_y(y), last_index_ (x.dimension_0 () == 0 ? 0 : x.dimension_0 () - 1)
+///   {}
+///
+///   void operator () (const size_type i, int& update, const bool final_pass) const {
+///     if (final_pass) {
+///       m_y(i) = update;
+///     }
+///     update += m_x(i);
+///     // The last entry of m_y gets the final sum.
+///     if (final_pass && i == last_index_) {
+///       m_y(i+1) = update;
+///     }
+///   }
+///   void init (value_type& update) const {
+///     update = 0;
+///   }
+///   void join (volatile value_type& update, volatile const value_type& input) const {
+///     update += input;
+///   }
+///
+/// private:
+///   Kokkos::View<value_type*, execution_space> m_x;
+///   Kokkos::View<value_type*, execution_space> m_y;
+///   const size_type last_index_;
+/// };
+/// \endcode
+///
+template< class ExecutionPolicy , class FunctorType >
+inline
+void parallel_scan( const ExecutionPolicy & policy
+                  , const FunctorType     & functor
+                  , const std::string& str = ""
+                  , typename Impl::enable_if< ! Impl::is_integral< ExecutionPolicy >::value >::type * = 0
+                  )
+{
+#if (KOKKOS_ENABLE_PROFILING)
+  uint64_t kpID = 0;
+     if(Kokkos::Profiling::profileLibraryLoaded()) {
+	Kokkos::Profiling::beginParallelScan("" == str ? typeid(FunctorType).name() : str, 0, &kpID);
+     }
+#endif
+
+  Kokkos::Impl::shared_allocation_tracking_claim_and_disable();
+  Impl::ParallelScan< FunctorType , ExecutionPolicy > closure( functor , policy );
+  Kokkos::Impl::shared_allocation_tracking_release_and_enable();
+
+  closure.execute();
+
+#if (KOKKOS_ENABLE_PROFILING)
+     if(Kokkos::Profiling::profileLibraryLoaded()) {
+	Kokkos::Profiling::endParallelScan(kpID);
+     }
+#endif
+
+}
+
+template< class FunctorType >
+inline
+void parallel_scan( const size_t        work_count
+                  , const FunctorType & functor
+                  , const std::string& str = "" )
+{
+  typedef typename
+    Kokkos::Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
+      execution_space ;
+
+  typedef Kokkos::RangePolicy< execution_space > policy ;
+
+#if (KOKKOS_ENABLE_PROFILING)
+  uint64_t kpID = 0;
+     if(Kokkos::Profiling::profileLibraryLoaded()) {
+	Kokkos::Profiling::beginParallelScan("" == str ? typeid(FunctorType).name() : str, 0, &kpID);
+     }
+#endif
+    
+  Kokkos::Impl::shared_allocation_tracking_claim_and_disable();
+  Impl::ParallelScan< FunctorType , policy > closure( functor , policy(0,work_count) );
+  Kokkos::Impl::shared_allocation_tracking_release_and_enable();
+
+  closure.execute();
+
+#if (KOKKOS_ENABLE_PROFILING)
+     if(Kokkos::Profiling::profileLibraryLoaded()) {
+	Kokkos::Profiling::endParallelScan(kpID);
+     }
+#endif
+
+}
+
+template< class ExecutionPolicy , class FunctorType >
+inline
+void parallel_scan( const std::string& str
+                  , const ExecutionPolicy & policy
+                  , const FunctorType     & functor)
+{
+  #if KOKKOS_ENABLE_DEBUG_PRINT_KERNEL_NAMES
+  Kokkos::fence();
+  std::cout << "KOKKOS_DEBUG Start parallel_scan kernel: " << str << std::endl;
+  #endif
+
+  parallel_scan(policy,functor,str);
+
+  #if KOKKOS_ENABLE_DEBUG_PRINT_KERNEL_NAMES
+  Kokkos::fence();
+  std::cout << "KOKKOS_DEBUG End   parallel_scan kernel: " << str << std::endl;
+  #endif
+  (void) str;
+}
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class Enable = void >
+struct FunctorTeamShmemSize
+{
+  KOKKOS_INLINE_FUNCTION static size_t value( const FunctorType & , int ) { return 0 ; }
+};
+
+template< class FunctorType >
+struct FunctorTeamShmemSize< FunctorType , typename Impl::enable_if< 0 < sizeof( & FunctorType::team_shmem_size ) >::type >
+{
+  static inline size_t value( const FunctorType & f , int team_size ) { return f.team_shmem_size( team_size ) ; }
+};
+
+template< class FunctorType >
+struct FunctorTeamShmemSize< FunctorType , typename Impl::enable_if< 0 < sizeof( & FunctorType::shmem_size ) >::type >
+{
+  static inline size_t value( const FunctorType & f , int team_size ) { return f.shmem_size( team_size ) ; }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* KOKKOS_PARALLEL_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_Parallel_Reduce.hpp b/lib/kokkos/core/src/Kokkos_Parallel_Reduce.hpp
new file mode 100644
index 0000000000..695bc79a1a
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Parallel_Reduce.hpp
@@ -0,0 +1,1240 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+
+namespace Kokkos {
+
+
+template<class T, class Enable = void>
+struct is_reducer_type {
+  enum { value = 0 };
+};
+
+
+template<class T>
+struct is_reducer_type<T,typename std::enable_if<
+                       std::is_same<T,typename T::reducer_type>::value
+                      >::type> {
+  enum { value = 1 };
+};
+
+namespace Experimental {
+
+
+template<class Scalar,class Space = HostSpace>
+struct Sum {
+public:
+  //Required
+  typedef Sum reducer_type;
+  typedef Scalar value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  value_type init_value;
+
+private:
+  result_view_type result;
+
+  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
+  struct InitWrapper;
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,true> {
+    static ValueType value() {
+      return static_cast<value_type>(0);
+    }
+  };
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,false> {
+    static ValueType value() {
+      return value_type();
+    }
+  };
+
+public:
+
+  Sum(value_type& result_):
+    init_value(InitWrapper<value_type>::value()),result(&result_) {}
+  Sum(const result_view_type& result_):
+    init_value(InitWrapper<value_type>::value()),result(result_) {}
+  Sum(value_type& result_, const value_type& init_value_):
+    init_value(init_value_),result(&result_) {}
+  Sum(const result_view_type& result_, const value_type& init_value_):
+    init_value(init_value_),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    dest += src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest += src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar,class Space = HostSpace>
+struct Prod {
+public:
+  //Required
+  typedef Prod reducer_type;
+  typedef Scalar value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  value_type init_value;
+
+private:
+  result_view_type result;
+
+  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
+  struct InitWrapper;
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,true> {
+    static ValueType value() {
+      return static_cast<value_type>(1);
+    }
+  };
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,false> {
+    static ValueType value() {
+      return value_type();
+    }
+  };
+
+public:
+
+  Prod(value_type& result_):
+    init_value(InitWrapper<value_type>::value()),result(&result_) {}
+  Prod(const result_view_type& result_):
+    init_value(InitWrapper<value_type>::value()),result(result_) {}
+  Prod(value_type& result_, const value_type& init_value_):
+    init_value(init_value_),result(&result_) {}
+  Prod(const result_view_type& result_, const value_type& init_value_):
+    init_value(init_value_),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    dest *= src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest *= src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Space = HostSpace>
+struct Min {
+public:
+  //Required
+  typedef Min reducer_type;
+  typedef typename std::remove_cv<Scalar>::type value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  value_type init_value;
+
+private:
+  result_view_type result;
+
+  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
+  struct InitWrapper;
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,true> {
+    static ValueType value() {
+      return std::numeric_limits<value_type>::max();
+    }
+  };
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,false> {
+    static ValueType value() {
+      return value_type();
+    }
+  };
+
+public:
+
+  Min(value_type& result_):
+    init_value(InitWrapper<value_type>::value()),result(&result_) {}
+  Min(const result_view_type& result_):
+    init_value(InitWrapper<value_type>::value()),result(result_) {}
+  Min(value_type& result_, const value_type& init_value_):
+    init_value(init_value_),result(&result_) {}
+  Min(const result_view_type& result_, const value_type& init_value_):
+    init_value(init_value_),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    if ( src < dest )
+      dest = src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    if ( src < dest )
+      dest = src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Space = HostSpace>
+struct Max {
+public:
+  //Required
+  typedef Max reducer_type;
+  typedef typename std::remove_cv<Scalar>::type value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  value_type init_value;
+
+private:
+  result_view_type result;
+
+  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
+  struct InitWrapper;
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,true> {
+    static ValueType value() {
+      return std::numeric_limits<value_type>::min();
+    }
+  };
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,false> {
+    static ValueType value() {
+      return value_type();
+    }
+  };
+
+public:
+
+  Max(value_type& result_):
+    init_value(InitWrapper<value_type>::value()),result(&result_) {}
+  Max(const result_view_type& result_):
+    init_value(InitWrapper<value_type>::value()),result(result_) {}
+  Max(value_type& result_, const value_type& init_value_):
+    init_value(init_value_),result(&result_) {}
+  Max(const result_view_type& result_, const value_type& init_value_):
+    init_value(init_value_),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    if ( src > dest )
+      dest = src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    if ( src > dest )
+      dest = src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Space = HostSpace>
+struct LAnd {
+public:
+  //Required
+  typedef LAnd reducer_type;
+  typedef Scalar value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+private:
+  result_view_type result;
+
+public:
+
+  LAnd(value_type& result_):result(&result_) {}
+  LAnd(const result_view_type& result_):result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    dest = dest && src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest = dest && src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = 1;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Space = HostSpace>
+struct LOr {
+public:
+  //Required
+  typedef LOr reducer_type;
+  typedef Scalar value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+private:
+  result_view_type result;
+
+public:
+
+  LOr(value_type& result_):result(&result_) {}
+  LOr(const result_view_type& result_):result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    dest = dest || src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest = dest || src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = 0;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Space = HostSpace>
+struct LXor {
+public:
+  //Required
+  typedef LXor reducer_type;
+  typedef Scalar value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+private:
+  result_view_type result;
+
+public:
+
+  LXor(value_type& result_):result(&result_) {}
+  LXor(const result_view_type& result_):result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    dest = dest? (!src) : src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest = dest? (!src) : src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = 0;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Space = HostSpace>
+struct BAnd {
+public:
+  //Required
+  typedef BAnd reducer_type;
+  typedef typename std::remove_cv<Scalar>::type value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  value_type init_value;
+
+private:
+  result_view_type result;
+
+public:
+
+  BAnd(value_type& result_):
+    init_value(value_type() | (~value_type())),result(&result_) {}
+  BAnd(const result_view_type& result_):
+    init_value(value_type() | (~value_type())),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+      dest = dest & src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest = dest & src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Space = HostSpace>
+struct BOr {
+public:
+  //Required
+  typedef BOr reducer_type;
+  typedef typename std::remove_cv<Scalar>::type value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  value_type init_value;
+
+private:
+  result_view_type result;
+
+public:
+
+  BOr(value_type& result_):
+    init_value(value_type() & (~value_type())),result(&result_) {}
+  BOr(const result_view_type& result_):
+    init_value(value_type() & (~value_type())),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+      dest = dest | src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest = dest | src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Space = HostSpace>
+struct BXor {
+public:
+  //Required
+  typedef BXor reducer_type;
+  typedef typename std::remove_cv<Scalar>::type value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  value_type init_value;
+
+private:
+  result_view_type result;
+
+public:
+
+  BXor(value_type& result_):
+    init_value(value_type() & (~value_type())),result(&result_) {}
+  BXor(const result_view_type& result_):
+    init_value(value_type() & (~value_type())),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+      dest = dest ^ src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest = dest ^ src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Index>
+struct ValLocScalar {
+  Scalar val;
+  Index loc;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator = (const ValLocScalar& rhs) {
+    val = rhs.val;
+    loc = rhs.loc;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator = (const volatile ValLocScalar& rhs) volatile {
+    val = rhs.val;
+    loc = rhs.loc;
+  }
+};
+
+template<class Scalar, class Index, class Space = HostSpace>
+struct MinLoc {
+private:
+  typedef typename std::remove_cv<Scalar>::type scalar_type;
+  typedef typename std::remove_cv<Index>::type index_type;
+
+public:
+  //Required
+  typedef MinLoc reducer_type;
+  typedef ValLocScalar<scalar_type,index_type> value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  scalar_type init_value;
+
+private:
+  result_view_type result;
+
+  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
+  struct InitWrapper;
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,true> {
+    static ValueType value() {
+      return std::numeric_limits<scalar_type>::max();
+    }
+  };
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,false> {
+    static ValueType value() {
+      return scalar_type();
+    }
+  };
+
+public:
+
+  MinLoc(value_type& result_):
+    init_value(InitWrapper<scalar_type>::value()),result(&result_) {}
+  MinLoc(const result_view_type& result_):
+    init_value(InitWrapper<scalar_type>::value()),result(result_) {}
+  MinLoc(value_type& result_, const scalar_type& init_value_):
+    init_value(init_value_),result(&result_) {}
+  MinLoc(const result_view_type& result_, const scalar_type& init_value_):
+    init_value(init_value_),result(result_) {}
+
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    if ( src.val < dest.val )
+      dest = src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    if ( src.val < dest.val )
+      dest = src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val.val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Index, class Space = HostSpace>
+struct MaxLoc {
+private:
+  typedef typename std::remove_cv<Scalar>::type scalar_type;
+  typedef typename std::remove_cv<Index>::type index_type;
+
+public:
+  //Required
+  typedef MaxLoc reducer_type;
+  typedef ValLocScalar<scalar_type,index_type> value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  scalar_type init_value;
+
+private:
+  result_view_type result;
+
+  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
+  struct InitWrapper;
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,true> {
+    static ValueType value() {
+      return std::numeric_limits<scalar_type>::min();
+    }
+  };
+
+  template<class ValueType >
+  struct InitWrapper<ValueType,false> {
+    static ValueType value() {
+      return scalar_type();
+    }
+  };
+
+public:
+
+  MaxLoc(value_type& result_):
+    init_value(InitWrapper<scalar_type>::value()),result(&result_) {}
+  MaxLoc(const result_view_type& result_):
+    init_value(InitWrapper<scalar_type>::value()),result(result_) {}
+  MaxLoc(value_type& result_, const scalar_type& init_value_):
+    init_value(init_value_),result(&result_) {}
+  MaxLoc(const result_view_type& result_, const scalar_type& init_value_):
+    init_value(init_value_),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    if ( src.val > dest.val )
+      dest = src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    if ( src.val > dest.val )
+      dest = src;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val.val = init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<class Scalar, class Index>
+struct MinMaxLocScalar {
+  Scalar min_val,max_val;
+  Index min_loc,max_loc;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator = (const MinMaxLocScalar& rhs) {
+    min_val = rhs.min_val;
+    min_loc = rhs.min_loc;
+    max_val = rhs.max_val;
+    max_loc = rhs.max_loc;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator = (const volatile MinMaxLocScalar& rhs) volatile {
+    min_val = rhs.min_val;
+    min_loc = rhs.min_loc;
+    max_val = rhs.max_val;
+    max_loc = rhs.max_loc;
+  }
+};
+
+template<class Scalar, class Index, class Space = HostSpace>
+struct MinMaxLoc {
+private:
+  typedef typename std::remove_cv<Scalar>::type scalar_type;
+  typedef typename std::remove_cv<Index>::type index_type;
+
+public:
+  //Required
+  typedef MinMaxLoc reducer_type;
+  typedef MinMaxLocScalar<scalar_type,index_type> value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+  scalar_type min_init_value;
+  scalar_type max_init_value;
+
+private:
+  result_view_type result;
+
+  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
+  struct MinInitWrapper;
+
+  template<class ValueType >
+  struct MinInitWrapper<ValueType,true> {
+    static ValueType value() {
+      return std::numeric_limits<scalar_type>::max();
+    }
+  };
+
+  template<class ValueType >
+  struct MinInitWrapper<ValueType,false> {
+    static ValueType value() {
+      return scalar_type();
+    }
+  };
+
+  template<class ValueType, bool is_arithmetic = std::is_arithmetic<ValueType>::value >
+  struct MaxInitWrapper;
+
+  template<class ValueType >
+  struct MaxInitWrapper<ValueType,true> {
+    static ValueType value() {
+      return std::numeric_limits<scalar_type>::min();
+    }
+  };
+
+  template<class ValueType >
+  struct MaxInitWrapper<ValueType,false> {
+    static ValueType value() {
+      return scalar_type();
+    }
+  };
+
+public:
+
+  MinMaxLoc(value_type& result_):
+    min_init_value(MinInitWrapper<scalar_type>::value()),max_init_value(MaxInitWrapper<scalar_type>::value()),result(&result_) {}
+  MinMaxLoc(const result_view_type& result_):
+    min_init_value(MinInitWrapper<scalar_type>::value()),max_init_value(MaxInitWrapper<scalar_type>::value()),result(result_) {}
+  MinMaxLoc(value_type& result_, const scalar_type& min_init_value_, const scalar_type& max_init_value_):
+    min_init_value(min_init_value_),max_init_value(max_init_value_),result(&result_) {}
+  MinMaxLoc(const result_view_type& result_, const scalar_type& min_init_value_, const scalar_type& max_init_value_):
+    min_init_value(min_init_value_),max_init_value(max_init_value_),result(result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    if ( src.min_val < dest.min_val ) {
+      dest.min_val = src.min_val;
+      dest.min_loc = src.min_loc;
+    }
+    if ( src.max_val > dest.max_val ) {
+      dest.max_val = src.max_val;
+      dest.max_loc = src.max_loc;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    if ( src.min_val < dest.min_val ) {
+      dest.min_val = src.min_val;
+      dest.min_loc = src.min_loc;
+    }
+    if ( src.max_val > dest.max_val ) {
+      dest.max_val = src.max_val;
+      dest.max_loc = src.max_loc;
+    }
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val.min_val = min_init_value;
+    val.max_val = max_init_value;
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+}
+}
+
+
+namespace Kokkos {
+namespace Impl {
+
+template< class T, class ReturnType , class ValueTraits>
+struct ParallelReduceReturnValue;
+
+template< class ReturnType , class FunctorType >
+struct ParallelReduceReturnValue<typename std::enable_if<Kokkos::is_view<ReturnType>::value>::type, ReturnType, FunctorType> {
+  typedef ReturnType return_type;
+  typedef InvalidType reducer_type;
+
+  typedef typename return_type::value_type value_type_scalar;
+  typedef typename return_type::value_type value_type_array[];
+
+  typedef typename if_c<return_type::rank==0,value_type_scalar,value_type_array>::type value_type;
+
+  static return_type& return_value(ReturnType& return_val, const FunctorType&) {
+    return return_val;
+  }
+};
+
+template< class ReturnType , class FunctorType>
+struct ParallelReduceReturnValue<typename std::enable_if<
+                                   !Kokkos::is_view<ReturnType>::value &&
+                                  (!std::is_array<ReturnType>::value && !std::is_pointer<ReturnType>::value) &&
+                                   !Kokkos::is_reducer_type<ReturnType>::value
+                                 >::type, ReturnType, FunctorType> {
+  typedef Kokkos::View<  ReturnType
+                       , Kokkos::HostSpace
+                       , Kokkos::MemoryUnmanaged
+      > return_type;
+
+  typedef InvalidType reducer_type;
+
+  typedef typename return_type::value_type value_type;
+
+  static return_type return_value(ReturnType& return_val, const FunctorType&) {
+    return return_type(&return_val);
+  }
+};
+
+template< class ReturnType , class FunctorType>
+struct ParallelReduceReturnValue<typename std::enable_if<
+                                  (is_array<ReturnType>::value || std::is_pointer<ReturnType>::value)
+                                >::type, ReturnType, FunctorType> {
+  typedef Kokkos::View<  typename std::remove_const<ReturnType>::type
+                       , Kokkos::HostSpace
+                       , Kokkos::MemoryUnmanaged
+      > return_type;
+
+  typedef InvalidType reducer_type;
+
+  typedef typename return_type::value_type value_type[];
+
+  static return_type return_value(ReturnType& return_val,
+                                  const FunctorType& functor) {
+    return return_type(return_val,functor.value_count);
+  }
+};
+
+template< class ReturnType , class FunctorType>
+struct ParallelReduceReturnValue<typename std::enable_if<
+                                   Kokkos::is_reducer_type<ReturnType>::value
+                                >::type, ReturnType, FunctorType> {
+  typedef ReturnType return_type;
+  typedef ReturnType reducer_type;
+  typedef typename return_type::value_type value_type;
+
+  static return_type return_value(ReturnType& return_val,
+                                  const FunctorType& functor) {
+    return return_val;
+  }
+};
+}
+
+namespace Impl {
+template< class T, class ReturnType , class FunctorType>
+struct ParallelReducePolicyType;
+
+template< class PolicyType , class FunctorType >
+struct ParallelReducePolicyType<typename std::enable_if<Kokkos::Impl::is_execution_policy<PolicyType>::value>::type, PolicyType,FunctorType> {
+
+  typedef PolicyType policy_type;
+  static PolicyType policy(const PolicyType& policy_) {
+    return policy_;
+  }
+};
+
+template< class PolicyType , class FunctorType >
+struct ParallelReducePolicyType<typename std::enable_if<std::is_integral<PolicyType>::value>::type, PolicyType,FunctorType> {
+  typedef typename
+    Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
+      execution_space ;
+
+  typedef Kokkos::RangePolicy<execution_space> policy_type;
+
+  static policy_type policy(const PolicyType& policy_) {
+    return policy_type(0,policy_);
+  }
+};
+
+}
+
+namespace Impl {
+  template< class FunctorType, class ExecPolicy, class ValueType, class ExecutionSpace>
+  struct ParallelReduceFunctorType {
+    typedef FunctorType functor_type;
+    static const functor_type& functor(const functor_type& functor) {
+      return functor;
+    }
+  };
+}
+
+namespace Impl {
+
+  template< class PolicyType, class FunctorType, class ReturnType >
+  struct ParallelReduceAdaptor {
+    typedef Impl::ParallelReduceReturnValue<void,ReturnType,FunctorType> return_value_adapter;
+    #ifdef KOKKOS_IMPL_NEED_FUNCTOR_WRAPPER
+    typedef Impl::ParallelReduceFunctorType<FunctorType,PolicyType,
+                                            typename return_value_adapter::value_type,
+                                            typename PolicyType::execution_space> functor_adaptor;
+    #endif
+    static inline
+    void execute(const std::string& label,
+        const PolicyType& policy,
+        const FunctorType& functor,
+        ReturnType& return_value) {
+          #if (KOKKOS_ENABLE_PROFILING)
+            uint64_t kpID = 0;
+            if(Kokkos::Profiling::profileLibraryLoaded()) {
+              Kokkos::Profiling::beginParallelReduce("" == label ? typeid(FunctorType).name() : label, 0, &kpID);
+            }
+          #endif
+
+          Kokkos::Impl::shared_allocation_tracking_claim_and_disable();
+          #ifdef KOKKOS_IMPL_NEED_FUNCTOR_WRAPPER
+          Impl::ParallelReduce<typename functor_adaptor::functor_type, PolicyType, typename return_value_adapter::reducer_type >
+             closure(functor_adaptor::functor(functor),
+                     policy,
+                     return_value_adapter::return_value(return_value,functor));
+          #else
+          Impl::ParallelReduce<FunctorType, PolicyType, typename return_value_adapter::reducer_type >
+             closure(functor,
+                     policy,
+                     return_value_adapter::return_value(return_value,functor));
+          #endif
+          Kokkos::Impl::shared_allocation_tracking_release_and_enable();
+          closure.execute();
+
+          #if (KOKKOS_ENABLE_PROFILING)
+            if(Kokkos::Profiling::profileLibraryLoaded()) {
+              Kokkos::Profiling::endParallelReduce(kpID);
+            }
+          #endif
+        }
+
+  };
+}
+/*! \fn void parallel_reduce(label,policy,functor,return_argument)
+    \brief Perform a parallel reduction.
+    \param label An optional Label giving the call name. Must be able to construct a std::string from the argument.
+    \param policy A Kokkos Execution Policy, such as an integer, a RangePolicy or a TeamPolicy.
+    \param functor A functor with a reduction operator, and optional init, join and final functions.
+    \param return_argument A return argument which can be a scalar, a View, or a ReducerStruct. This argument can be left out if the functor has a final function.
+*/
+
+/** \brief  Parallel reduction
+ *
+ * parallel_reduce performs parallel reductions with arbitrary functions - i.e.
+ * it is not solely data based. The call expects up to 4 arguments:
+ *
+ *
+ * Example of a parallel_reduce functor for a POD (plain old data) value type:
+ * \code
+ *  class FunctorType { // For POD value type
+ *  public:
+ *    typedef    ...     execution_space ;
+ *    typedef <podType>  value_type ;
+ *    void operator()( <intType> iwork , <podType> & update ) const ;
+ *    void init( <podType> & update ) const ;
+ *    void join( volatile       <podType> & update ,
+ *               volatile const <podType> & input ) const ;
+ *
+ *    typedef true_type has_final ;
+ *    void final( <podType> & update ) const ;
+ *  };
+ * \endcode
+ *
+ * Example of a parallel_reduce functor for an array of POD (plain old data) values:
+ * \code
+ *  class FunctorType { // For array of POD value
+ *  public:
+ *    typedef    ...     execution_space ;
+ *    typedef <podType>  value_type[] ;
+ *    void operator()( <intType> , <podType> update[] ) const ;
+ *    void init( <podType> update[] ) const ;
+ *    void join( volatile       <podType> update[] ,
+ *               volatile const <podType> input[] ) const ;
+ *
+ *    typedef true_type has_final ;
+ *    void final( <podType> update[] ) const ;
+ *  };
+ * \endcode
+ */
+
+// ReturnValue is scalar or array: take by reference
+
+template< class PolicyType, class FunctorType, class ReturnType >
+inline
+void parallel_reduce(const std::string& label,
+                     const PolicyType& policy,
+                     const FunctorType& functor,
+                     ReturnType& return_value,
+                     typename Impl::enable_if<
+                       Kokkos::Impl::is_execution_policy<PolicyType>::value
+                     >::type * = 0) {
+  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute(label,policy,functor,return_value);
+}
+
+template< class PolicyType, class FunctorType, class ReturnType >
+inline
+void parallel_reduce(const PolicyType& policy,
+                     const FunctorType& functor,
+                     ReturnType& return_value,
+                     typename Impl::enable_if<
+                       Kokkos::Impl::is_execution_policy<PolicyType>::value
+                     >::type * = 0) {
+  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute("",policy,functor,return_value);
+}
+
+template< class FunctorType, class ReturnType >
+inline
+void parallel_reduce(const size_t& policy,
+                     const FunctorType& functor,
+                     ReturnType& return_value) {
+  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
+  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute("",policy_type(0,policy),functor,return_value);
+}
+
+template< class FunctorType, class ReturnType >
+inline
+void parallel_reduce(const std::string& label,
+                     const size_t& policy,
+                     const FunctorType& functor,
+                     ReturnType& return_value) {
+  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
+  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute(label,policy_type(0,policy),functor,return_value);
+}
+
+// ReturnValue as View or Reducer: take by copy to allow for inline construction
+
+template< class PolicyType, class FunctorType, class ReturnType >
+inline
+void parallel_reduce(const std::string& label,
+                     const PolicyType& policy,
+                     const FunctorType& functor,
+                     const ReturnType& return_value,
+                     typename Impl::enable_if<
+                       Kokkos::Impl::is_execution_policy<PolicyType>::value
+                     >::type * = 0) {
+  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,const ReturnType>::execute(label,policy,functor,return_value);
+}
+
+template< class PolicyType, class FunctorType, class ReturnType >
+inline
+void parallel_reduce(const PolicyType& policy,
+                     const FunctorType& functor,
+                     const ReturnType& return_value,
+                     typename Impl::enable_if<
+                       Kokkos::Impl::is_execution_policy<PolicyType>::value
+                     >::type * = 0) {
+  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,const ReturnType>::execute("",policy,functor,return_value);
+}
+
+template< class FunctorType, class ReturnType >
+inline
+void parallel_reduce(const size_t& policy,
+                     const FunctorType& functor,
+                     const ReturnType& return_value) {
+  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
+
+  Impl::ParallelReduceAdaptor<policy_type,FunctorType,const ReturnType>::execute("",policy_type(0,policy),functor,return_value);
+}
+
+template< class FunctorType, class ReturnType >
+inline
+void parallel_reduce(const std::string& label,
+                     const size_t& policy,
+                     const FunctorType& functor,
+                     const ReturnType& return_value) {
+  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
+  Impl::ParallelReduceAdaptor<policy_type,FunctorType,const ReturnType>::execute(label,policy_type(0,policy),functor,return_value);
+}
+
+// No Return Argument
+
+template< class PolicyType, class FunctorType>
+inline
+void parallel_reduce(const std::string& label,
+                     const PolicyType& policy,
+                     const FunctorType& functor,
+                     typename Impl::enable_if<
+                       Kokkos::Impl::is_execution_policy<PolicyType>::value
+                     >::type * = 0) {
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void >  ValueTraits ;
+  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
+                                     , typename ValueTraits::value_type
+                                     , typename ValueTraits::pointer_type
+                                     >::type value_type ;
+
+  typedef Kokkos::View< value_type
+              , Kokkos::HostSpace
+              , Kokkos::MemoryUnmanaged
+              > result_view_type;
+  result_view_type result_view ;
+
+  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,result_view_type>::execute(label,policy,functor,result_view);
+}
+
+template< class PolicyType, class FunctorType >
+inline
+void parallel_reduce(const PolicyType& policy,
+                     const FunctorType& functor,
+                     typename Impl::enable_if<
+                       Kokkos::Impl::is_execution_policy<PolicyType>::value
+                     >::type * = 0) {
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void >  ValueTraits ;
+  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
+                                     , typename ValueTraits::value_type
+                                     , typename ValueTraits::pointer_type
+                                     >::type value_type ;
+
+  typedef Kokkos::View< value_type
+              , Kokkos::HostSpace
+              , Kokkos::MemoryUnmanaged
+              > result_view_type;
+  result_view_type result_view ;
+
+  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,result_view_type>::execute("",policy,functor,result_view);
+}
+
+template< class FunctorType >
+inline
+void parallel_reduce(const size_t& policy,
+                     const FunctorType& functor) {
+  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void >  ValueTraits ;
+  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
+                                     , typename ValueTraits::value_type
+                                     , typename ValueTraits::pointer_type
+                                     >::type value_type ;
+
+  typedef Kokkos::View< value_type
+              , Kokkos::HostSpace
+              , Kokkos::MemoryUnmanaged
+              > result_view_type;
+  result_view_type result_view ;
+
+  Impl::ParallelReduceAdaptor<policy_type,FunctorType,result_view_type>::execute("",policy_type(0,policy),functor,result_view);
+}
+
+template< class FunctorType>
+inline
+void parallel_reduce(const std::string& label,
+                     const size_t& policy,
+                     const FunctorType& functor) {
+  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void >  ValueTraits ;
+  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
+                                     , typename ValueTraits::value_type
+                                     , typename ValueTraits::pointer_type
+                                     >::type value_type ;
+
+  typedef Kokkos::View< value_type
+              , Kokkos::HostSpace
+              , Kokkos::MemoryUnmanaged
+              > result_view_type;
+  result_view_type result_view ;
+
+  Impl::ParallelReduceAdaptor<policy_type,FunctorType,result_view_type>::execute(label,policy_type(0,policy),functor,result_view);
+}
+
+
+
+} //namespace Kokkos
diff --git a/lib/kokkos/core/src/Kokkos_Qthread.hpp b/lib/kokkos/core/src/Kokkos_Qthread.hpp
new file mode 100644
index 0000000000..d61f8d518e
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Qthread.hpp
@@ -0,0 +1,172 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_QTHREAD_HPP
+#define KOKKOS_QTHREAD_HPP
+
+#include <cstddef>
+#include <iosfwd>
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Layout.hpp>
+#include <Kokkos_MemoryTraits.hpp>
+#include <Kokkos_HostSpace.hpp>
+#include <Kokkos_ExecPolicy.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+class QthreadExec ;
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/** \brief  Execution space supported by Qthread */
+class Qthread {
+public:
+  //! \name Type declarations that all Kokkos devices must provide.
+  //@{
+
+  //! Tag this class as an execution space
+  typedef Qthread                  execution_space ;
+  typedef Kokkos::HostSpace        memory_space ;
+  //! This execution space preferred device_type
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  typedef Kokkos::LayoutRight      array_layout ;
+  typedef memory_space::size_type  size_type ;
+
+  typedef ScratchMemorySpace< Qthread > scratch_memory_space ;
+
+  //@}
+  /*------------------------------------------------------------------------*/
+
+  /** \brief  Initialization will construct one or more instances */
+  static Qthread & instance( int = 0 );
+
+  /** \brief  Set the execution space to a "sleep" state.
+   *
+   * This function sets the "sleep" state in which it is not ready for work.
+   * This may consume less resources than in an "ready" state,
+   * but it may also take time to transition to the "ready" state.
+   *
+   * \return True if enters or is in the "sleep" state.
+   *         False if functions are currently executing.
+   */
+  bool sleep();
+
+  /** \brief  Wake from the sleep state.
+   * 
+   *  \return True if enters or is in the "ready" state.
+   *          False if functions are currently executing.
+   */
+  static bool wake();
+
+  /** \brief Wait until all dispatched functions to complete.
+   * 
+   *  The parallel_for or parallel_reduce dispatch of a functor may
+   *  return asynchronously, before the functor completes.  This
+   *  method does not return until all dispatched functors on this
+   *  device have completed.
+   */
+  static void fence();
+
+  /*------------------------------------------------------------------------*/
+
+  static int in_parallel();
+
+  static int is_initialized();
+
+  /** \brief  Return maximum amount of concurrency */
+  static int concurrency();
+
+  static void initialize( int thread_count );
+  static void finalize();
+
+  /** \brief Print configuration information to the given output stream. */
+  static void print_configuration( std::ostream & , const bool detail = false );
+
+  int shepherd_size() const ;
+  int shepherd_worker_size() const ;
+};
+
+/*--------------------------------------------------------------------------*/
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+struct VerifyExecutionCanAccessMemorySpace
+  < Kokkos::Qthread::memory_space
+  , Kokkos::Qthread::scratch_memory_space
+  >
+{
+  enum { value = true };
+  inline static void verify( void ) { }
+  inline static void verify( const void * ) { }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#include <Kokkos_Parallel.hpp>
+#include <Qthread/Kokkos_QthreadExec.hpp>
+#include <Qthread/Kokkos_Qthread_Parallel.hpp>
+
+#endif /* #define KOKKOS_QTHREAD_HPP */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/core/src/Kokkos_ScratchSpace.hpp b/lib/kokkos/core/src/Kokkos_ScratchSpace.hpp
new file mode 100644
index 0000000000..09a5993863
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_ScratchSpace.hpp
@@ -0,0 +1,166 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_SCRATCHSPACE_HPP
+#define KOKKOS_SCRATCHSPACE_HPP
+
+#include <stdio.h>
+#include <Kokkos_Core_fwd.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/** \brief  Scratch memory space associated with an execution space.
+ *
+ */
+template< class ExecSpace >
+class ScratchMemorySpace {
+  static_assert (Impl::is_execution_space<ExecSpace>::value,"Instantiating ScratchMemorySpace on non-execution-space type.");
+public:
+
+  // Alignment of memory chunks returned by 'get'
+  // must be a power of two
+  enum { ALIGN = 8 };
+
+private:
+
+  mutable char * m_iter_L0 ;
+  char *         m_end_L0 ;
+  mutable char * m_iter_L1 ;
+  char *         m_end_L1 ;
+
+
+  mutable int m_multiplier;
+  mutable int m_offset;
+  mutable int m_default_level;
+
+  ScratchMemorySpace();
+  ScratchMemorySpace & operator = ( const ScratchMemorySpace & );
+
+  enum { MASK = ALIGN - 1 }; // Alignment used by View::shmem_size
+
+public:
+
+  //! Tag this class as a memory space
+  typedef ScratchMemorySpace                memory_space ;
+  typedef ExecSpace                         execution_space ;
+  //! This execution space preferred device_type
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  typedef typename ExecSpace::array_layout  array_layout ;
+  typedef typename ExecSpace::size_type     size_type ;
+
+  template< typename IntType >
+  KOKKOS_INLINE_FUNCTION static
+  IntType align( const IntType & size )
+    { return ( size + MASK ) & ~MASK ; }
+
+  template< typename IntType >
+  KOKKOS_INLINE_FUNCTION
+  void* get_shmem (const IntType& size, int level = -1) const {
+    if(level == -1)
+      level = m_default_level;
+    if(level == 0) {
+      void* tmp = m_iter_L0 + m_offset * align (size);
+      if (m_end_L0 < (m_iter_L0 += align (size) * m_multiplier)) {
+        m_iter_L0 -= align (size) * m_multiplier; // put it back like it was
+        #ifdef KOKKOS_HAVE_DEBUG
+        // mfh 23 Jun 2015: printf call consumes 25 registers
+        // in a CUDA build, so only print in debug mode.  The
+        // function still returns NULL if not enough memory.
+        printf ("ScratchMemorySpace<...>::get_shmem: Failed to allocate "
+                "%ld byte(s); remaining capacity is %ld byte(s)\n", long(size),
+                long(m_end_L0-m_iter_L0));
+        #endif // KOKKOS_HAVE_DEBUG
+        tmp = 0;
+      }
+      return tmp;
+    } else {
+      void* tmp = m_iter_L1 + m_offset * align (size);
+      if (m_end_L1 < (m_iter_L1 += align (size) * m_multiplier)) {
+        m_iter_L1 -= align (size) * m_multiplier; // put it back like it was
+        #ifdef KOKKOS_HAVE_DEBUG
+        // mfh 23 Jun 2015: printf call consumes 25 registers
+        // in a CUDA build, so only print in debug mode.  The
+        // function still returns NULL if not enough memory.
+        printf ("ScratchMemorySpace<...>::get_shmem: Failed to allocate "
+                "%ld byte(s); remaining capacity is %ld byte(s)\n", long(size),
+                long(m_end_L1-m_iter_L1));
+        #endif // KOKKOS_HAVE_DEBUG
+        tmp = 0;
+      }
+      return tmp;
+
+    }
+  }
+
+  template< typename IntType >
+  KOKKOS_INLINE_FUNCTION
+  ScratchMemorySpace( void * ptr_L0 , const IntType & size_L0 , void * ptr_L1 = NULL , const IntType & size_L1 = 0)
+    : m_iter_L0( (char *) ptr_L0 )
+    , m_end_L0(  m_iter_L0 + size_L0 )
+    , m_iter_L1( (char *) ptr_L1 )
+    , m_end_L1(  m_iter_L1 + size_L1 )
+    , m_multiplier( 1 )
+    , m_offset( 0 )
+    , m_default_level( 0 )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  const ScratchMemorySpace& set_team_thread_mode(const int& level, const int& multiplier, const int& offset) const {
+    m_default_level = level;
+    m_multiplier = multiplier;
+    m_offset = offset;
+    return *this;
+  }
+};
+
+} // namespace Kokkos
+
+#endif /* #ifndef KOKKOS_SCRATCHSPACE_HPP */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/core/src/Kokkos_Serial.hpp b/lib/kokkos/core/src/Kokkos_Serial.hpp
new file mode 100644
index 0000000000..233b56c939
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Serial.hpp
@@ -0,0 +1,1116 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+/// \file Kokkos_Serial.hpp
+/// \brief Declaration and definition of Kokkos::Serial device.
+
+#ifndef KOKKOS_SERIAL_HPP
+#define KOKKOS_SERIAL_HPP
+
+#include <cstddef>
+#include <iosfwd>
+#include <Kokkos_Parallel.hpp>
+#include <Kokkos_TaskPolicy.hpp>
+#include <Kokkos_Layout.hpp>
+#include <Kokkos_HostSpace.hpp>
+#include <Kokkos_ScratchSpace.hpp>
+#include <Kokkos_MemoryTraits.hpp>
+#include <impl/Kokkos_Tags.hpp>
+#include <impl/Kokkos_FunctorAdapter.hpp>
+#include <impl/Kokkos_Profiling_Interface.hpp>
+
+
+#include <KokkosExp_MDRangePolicy.hpp>
+
+#if defined( KOKKOS_HAVE_SERIAL )
+
+namespace Kokkos {
+
+/// \class Serial
+/// \brief Kokkos device for non-parallel execution
+///
+/// A "device" represents a parallel execution model.  It tells Kokkos
+/// how to parallelize the execution of kernels in a parallel_for or
+/// parallel_reduce.  For example, the Threads device uses Pthreads or
+/// C++11 threads on a CPU, the OpenMP device uses the OpenMP language
+/// extensions, and the Cuda device uses NVIDIA's CUDA programming
+/// model.  The Serial device executes "parallel" kernels
+/// sequentially.  This is useful if you really do not want to use
+/// threads, or if you want to explore different combinations of MPI
+/// and shared-memory parallel programming models.
+class Serial {
+public:
+  //! \name Type declarations that all Kokkos devices must provide.
+  //@{
+
+  //! Tag this class as an execution space:
+  typedef Serial                execution_space ;
+  //! The size_type typedef best suited for this device.
+  typedef HostSpace::size_type  size_type ;
+  //! This device's preferred memory space.
+  typedef HostSpace             memory_space ;
+  //! This execution space preferred device_type
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  //! This device's preferred array layout.
+  typedef LayoutRight           array_layout ;
+
+  /// \brief  Scratch memory space
+  typedef ScratchMemorySpace< Kokkos::Serial >  scratch_memory_space ;
+
+  //@}
+
+  /// \brief True if and only if this method is being called in a
+  ///   thread-parallel function.
+  ///
+  /// For the Serial device, this method <i>always</i> returns false,
+  /// because parallel_for or parallel_reduce with the Serial device
+  /// always execute sequentially.
+  inline static int in_parallel() { return false ; }
+
+  /** \brief  Set the device in a "sleep" state.
+   *
+   * This function sets the device in a "sleep" state in which it is
+   * not ready for work.  This may consume less resources than if the
+   * device were in an "awake" state, but it may also take time to
+   * bring the device from a sleep state to be ready for work.
+   *
+   * \return True if the device is in the "sleep" state, else false if
+   *   the device is actively working and could not enter the "sleep"
+   *   state.
+   */
+  static bool sleep();
+
+  /// \brief Wake the device from the 'sleep' state so it is ready for work.
+  ///
+  /// \return True if the device is in the "ready" state, else "false"
+  ///  if the device is actively working (which also means that it's
+  ///  awake).
+  static bool wake();
+
+  /// \brief Wait until all dispatched functors complete.
+  ///
+  /// The parallel_for or parallel_reduce dispatch of a functor may
+  /// return asynchronously, before the functor completes.  This
+  /// method does not return until all dispatched functors on this
+  /// device have completed.
+  static void fence() {}
+
+  static void initialize( unsigned threads_count = 1 ,
+                          unsigned use_numa_count = 0 ,
+                          unsigned use_cores_per_numa = 0 ,
+                          bool allow_asynchronous_threadpool = false) {
+    (void) threads_count;
+    (void) use_numa_count;
+    (void) use_cores_per_numa;
+    (void) allow_asynchronous_threadpool;
+
+    // Init the array of locks used for arbitrarily sized atomics
+    Impl::init_lock_array_host_space();
+    #if (KOKKOS_ENABLE_PROFILING)
+      Kokkos::Profiling::initialize();
+    #endif
+  }
+
+  static int is_initialized() { return 1 ; }
+
+  /** \brief  Return the maximum amount of concurrency.  */
+  static int concurrency() {return 1;};
+
+  //! Free any resources being consumed by the device.
+  static void finalize() {
+    #if (KOKKOS_ENABLE_PROFILING)
+      Kokkos::Profiling::finalize();
+    #endif
+  }
+
+  //! Print configuration information to the given output stream.
+  static void print_configuration( std::ostream & , const bool /* detail */ = false ) {}
+
+  //--------------------------------------------------------------------------
+
+  inline static int thread_pool_size( int = 0 ) { return 1 ; }
+  KOKKOS_INLINE_FUNCTION static int thread_pool_rank() { return 0 ; }
+
+  //--------------------------------------------------------------------------
+
+  KOKKOS_INLINE_FUNCTION static unsigned hardware_thread_id() { return thread_pool_rank(); }
+  inline static unsigned max_hardware_threads() { return thread_pool_size(0); }
+
+  //--------------------------------------------------------------------------
+
+  static void * scratch_memory_resize( unsigned reduce_size , unsigned shared_size );
+
+  //--------------------------------------------------------------------------
+};
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+struct VerifyExecutionCanAccessMemorySpace
+  < Kokkos::Serial::memory_space
+  , Kokkos::Serial::scratch_memory_space
+  >
+{
+  enum { value = true };
+  inline static void verify( void ) { }
+  inline static void verify( const void * ) { }
+};
+
+namespace SerialImpl {
+
+struct Sentinel {
+
+  void *   m_scratch ;
+  unsigned m_reduce_end ;
+  unsigned m_shared_end ;
+
+  Sentinel();
+  ~Sentinel();
+  static Sentinel & singleton();
+};
+
+inline
+unsigned align( unsigned n );
+}
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+class SerialTeamMember {
+private:
+  typedef Kokkos::ScratchMemorySpace< Kokkos::Serial > scratch_memory_space ;
+  const scratch_memory_space  m_space ;
+  const int                   m_league_rank ;
+  const int                   m_league_size ;
+
+  SerialTeamMember & operator = ( const SerialTeamMember & );
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  const scratch_memory_space & team_shmem() const { return m_space ; }
+
+  KOKKOS_INLINE_FUNCTION
+  const scratch_memory_space & team_scratch(int) const
+    { return m_space ; }
+
+  KOKKOS_INLINE_FUNCTION
+  const scratch_memory_space & thread_scratch(int) const
+    { return m_space ; }
+
+
+  KOKKOS_INLINE_FUNCTION int league_rank() const { return m_league_rank ; }
+  KOKKOS_INLINE_FUNCTION int league_size() const { return m_league_size ; }
+  KOKKOS_INLINE_FUNCTION int team_rank() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION int team_size() const { return 1 ; }
+
+  KOKKOS_INLINE_FUNCTION void team_barrier() const {}
+
+  template<class ValueType>
+  KOKKOS_INLINE_FUNCTION
+  void team_broadcast(const ValueType& , const int& ) const {}
+
+  template< class ValueType, class JoinOp >
+  KOKKOS_INLINE_FUNCTION
+  ValueType team_reduce( const ValueType & value , const JoinOp & ) const
+    {
+      return value ;
+    }
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering
+   *          with intra-team non-deterministic ordering accumulation.
+   *
+   *  The global inter-team accumulation value will, at the end of the
+   *  league's parallel execution, be the scan's total.
+   *  Parallel execution ordering of the league's teams is non-deterministic.
+   *  As such the base value for each team's scan operation is similarly
+   *  non-deterministic.
+   */
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION Type team_scan( const Type & value , Type * const global_accum ) const
+    {
+      const Type tmp = global_accum ? *global_accum : Type(0) ;
+      if ( global_accum ) { *global_accum += value ; }
+      return tmp ;
+    }
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering.
+   *
+   *  The highest rank thread can compute the reduction total as
+   *    reduction_total = dev.team_scan( value ) + value ;
+   */
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION Type team_scan( const Type & ) const
+    { return Type(0); }
+
+  //----------------------------------------
+  // Execution space specific:
+
+  SerialTeamMember( int arg_league_rank
+                  , int arg_league_size
+                  , int arg_shared_size
+                  );
+};
+
+} // namespace Impl
+
+
+/*
+ * < Kokkos::Serial , WorkArgTag >
+ * < WorkArgTag , Impl::enable_if< Impl::is_same< Kokkos::Serial , Kokkos::DefaultExecutionSpace >::value >::type >
+ *
+ */
+namespace Impl {
+template< class ... Properties >
+class TeamPolicyInternal< Kokkos::Serial , Properties ... >:public PolicyTraits<Properties...>
+{
+private:
+
+  size_t m_team_scratch_size[2] ;
+  size_t m_thread_scratch_size[2] ;
+  int    m_league_size ;
+  int    m_chunk_size;
+
+public:
+
+  //! Tag this class as a kokkos execution policy
+  typedef TeamPolicyInternal      execution_policy ;
+
+  typedef PolicyTraits<Properties ... > traits;
+
+  //! Execution space of this execution policy:
+  typedef Kokkos::Serial  execution_space ;
+
+  TeamPolicyInternal& operator = (const TeamPolicyInternal& p) {
+    m_league_size = p.m_league_size;
+    m_team_scratch_size[0] = p.m_team_scratch_size[0];
+    m_thread_scratch_size[0] = p.m_thread_scratch_size[0];
+    m_team_scratch_size[1] = p.m_team_scratch_size[1];
+    m_thread_scratch_size[1] = p.m_thread_scratch_size[1];
+    m_chunk_size = p.m_chunk_size;
+    return *this;
+  }
+
+  //----------------------------------------
+
+  template< class FunctorType >
+  static
+  int team_size_max( const FunctorType & ) { return 1 ; }
+
+  template< class FunctorType >
+  static
+  int team_size_recommended( const FunctorType & ) { return 1 ; }
+
+  template< class FunctorType >
+  static
+  int team_size_recommended( const FunctorType & , const int& ) { return 1 ; }
+
+  //----------------------------------------
+
+  inline int team_size() const { return 1 ; }
+  inline int league_size() const { return m_league_size ; }
+  inline size_t scratch_size(const int& level, int = 0) const { return m_team_scratch_size[level] + m_thread_scratch_size[level]; }
+
+  /** \brief  Specify league size, request team size */
+  TeamPolicyInternal( execution_space &
+            , int league_size_request
+            , int /* team_size_request */
+            , int /* vector_length_request */ = 1 )
+    : m_team_scratch_size { 0 , 0 }
+    , m_thread_scratch_size { 0 , 0 }
+    , m_league_size( league_size_request )
+    , m_chunk_size ( 32 )
+    {}
+
+  TeamPolicyInternal( execution_space &
+            , int league_size_request
+            , const Kokkos::AUTO_t & /* team_size_request */
+            , int /* vector_length_request */ = 1 )
+    : m_team_scratch_size { 0 , 0 }
+    , m_thread_scratch_size { 0 , 0 }
+    , m_league_size( league_size_request )
+    , m_chunk_size ( 32 )
+    {}
+
+  TeamPolicyInternal( int league_size_request
+            , int /* team_size_request */
+            , int /* vector_length_request */ = 1 )
+    : m_team_scratch_size { 0 , 0 }
+    , m_thread_scratch_size { 0 , 0 }
+    , m_league_size( league_size_request )
+    , m_chunk_size ( 32 )
+    {}
+
+  TeamPolicyInternal( int league_size_request
+            , const Kokkos::AUTO_t & /* team_size_request */
+            , int /* vector_length_request */ = 1 )
+    : m_team_scratch_size { 0 , 0 }
+    , m_thread_scratch_size { 0 , 0 }
+    , m_league_size( league_size_request )
+    , m_chunk_size ( 32 )
+    {}
+
+
+  inline int chunk_size() const { return m_chunk_size ; }
+
+  /** \brief set chunk_size to a discrete value*/
+  inline TeamPolicyInternal set_chunk_size(typename traits::index_type chunk_size_) const {
+    TeamPolicyInternal p = *this;
+    p.m_chunk_size = chunk_size_;
+    return p;
+  }
+
+  /** \brief set per team scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerTeamValue& per_team) const {
+    TeamPolicyInternal p = *this;
+    p.m_team_scratch_size[level] = per_team.value;
+    return p;
+  };
+
+  /** \brief set per thread scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerThreadValue& per_thread) const {
+    TeamPolicyInternal p = *this;
+    p.m_thread_scratch_size[level] = per_thread.value;
+    return p;
+  };
+
+  /** \brief set per thread and per team scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerTeamValue& per_team, const PerThreadValue& per_thread) const {
+    TeamPolicyInternal p = *this;
+    p.m_team_scratch_size[level] = per_team.value;
+    p.m_thread_scratch_size[level] = per_thread.value;
+    return p;
+  };
+
+  typedef Impl::SerialTeamMember  member_type ;
+};
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/* Parallel patterns for Kokkos::Serial with RangePolicy */
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ... Traits >
+class ParallelFor< FunctorType ,
+                   Kokkos::RangePolicy< Traits ... > ,
+                   Kokkos::Serial
+                 >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy ;
+
+  const FunctorType m_functor ;
+  const Policy      m_policy ;
+
+  template< class TagType >
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec() const
+    {
+      const typename Policy::member_type e = m_policy.end();
+      for ( typename Policy::member_type i = m_policy.begin() ; i < e ; ++i ) {
+        m_functor( i );
+      }
+    }
+
+  template< class TagType >
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec() const
+    {
+      const TagType t{} ;
+      const typename Policy::member_type e = m_policy.end();
+      for ( typename Policy::member_type i = m_policy.begin() ; i < e ; ++i ) {
+        m_functor( t , i );
+      }
+    }
+
+public:
+
+  inline
+  void execute() const
+    { this-> template exec< typename Policy::work_tag >(); }
+
+  inline
+  ParallelFor( const FunctorType & arg_functor
+             , const Policy      & arg_policy )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    {}
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< class FunctorType , class ReducerType , class ... Traits >
+class ParallelReduce< FunctorType
+                    , Kokkos::RangePolicy< Traits ... >
+                    , ReducerType
+                    , Kokkos::Serial
+                    >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy ;
+  typedef typename Policy::work_tag                                  WorkTag ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd , WorkTag >  ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd , WorkTag >  ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType   m_functor ;
+  const Policy        m_policy ;
+  const ReducerType   m_reducer ;
+  const pointer_type  m_result_ptr ;
+
+
+  template< class TagType >
+  inline
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec( pointer_type ptr ) const
+    {
+      reference_type update = ValueInit::init(  ReducerConditional::select(m_functor , m_reducer) , ptr );
+
+      const typename Policy::member_type e = m_policy.end();
+      for ( typename Policy::member_type i = m_policy.begin() ; i < e ; ++i ) {
+        m_functor( i , update );
+      }
+
+      Kokkos::Impl::FunctorFinal< ReducerTypeFwd , TagType >::
+        final(  ReducerConditional::select(m_functor , m_reducer) , ptr );
+    }
+
+  template< class TagType >
+  inline
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec( pointer_type ptr ) const
+    {
+      const TagType t{} ;
+      reference_type update = ValueInit::init(  ReducerConditional::select(m_functor , m_reducer) , ptr );
+
+      const typename Policy::member_type e = m_policy.end();
+      for ( typename Policy::member_type i = m_policy.begin() ; i < e ; ++i ) {
+        m_functor( t , i , update );
+      }
+
+      Kokkos::Impl::FunctorFinal< ReducerTypeFwd , TagType >::
+        final(  ReducerConditional::select(m_functor , m_reducer) , ptr );
+    }
+
+public:
+
+  inline
+  void execute() const
+    {
+      pointer_type ptr = (pointer_type) Kokkos::Serial::scratch_memory_resize
+           ( ValueTraits::value_size(  ReducerConditional::select(m_functor , m_reducer) ) , 0 );
+
+      this-> template exec< WorkTag >( m_result_ptr ? m_result_ptr : ptr );
+    }
+
+  template< class HostViewType >
+  ParallelReduce( const FunctorType  & arg_functor ,
+                  const Policy       & arg_policy ,
+                  const HostViewType & arg_result_view ,
+                  typename std::enable_if<
+                               Kokkos::is_view< HostViewType >::value &&
+                              !Kokkos::is_reducer_type<ReducerType>::value
+                  ,void*>::type = NULL)
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    , m_reducer( InvalidType() )
+    , m_result_ptr( arg_result_view.ptr_on_device() )
+    {
+      static_assert( Kokkos::is_view< HostViewType >::value
+        , "Kokkos::Serial reduce result must be a View" );
+
+      static_assert( std::is_same< typename HostViewType::memory_space , HostSpace >::value
+        , "Kokkos::Serial reduce result must be a View in HostSpace" );
+    }
+
+  inline
+  ParallelReduce( const FunctorType & arg_functor
+                , Policy       arg_policy
+                , const ReducerType& reducer )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    , m_reducer( reducer )
+    , m_result_ptr(  reducer.result_view().data() )
+    {
+      /*static_assert( std::is_same< typename ViewType::memory_space
+                                      , Kokkos::HostSpace >::value
+        , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace" );*/
+    }
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< class FunctorType , class ... Traits >
+class ParallelScan< FunctorType
+                  , Kokkos::RangePolicy< Traits ... >
+                  , Kokkos::Serial
+                  >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy ;
+  typedef typename Policy::work_tag                                  WorkTag ;
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , WorkTag >  ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   FunctorType , WorkTag >  ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType   m_functor ;
+  const Policy        m_policy ;
+
+  template< class TagType >
+  inline
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec( pointer_type ptr ) const
+    {
+      reference_type update = ValueInit::init( m_functor , ptr );
+
+      const typename Policy::member_type e = m_policy.end();
+      for ( typename Policy::member_type i = m_policy.begin() ; i < e ; ++i ) {
+        m_functor( i , update , true );
+      }
+    }
+
+  template< class TagType >
+  inline
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec( pointer_type ptr ) const
+    {
+      const TagType t{} ;
+      reference_type update = ValueInit::init( m_functor , ptr );
+
+      const typename Policy::member_type e = m_policy.end();
+      for ( typename Policy::member_type i = m_policy.begin() ; i < e ; ++i ) {
+        m_functor( t , i , update , true );
+      }
+    }
+
+public:
+
+  inline
+  void execute() const
+    {
+      pointer_type ptr = (pointer_type)
+        Kokkos::Serial::scratch_memory_resize( ValueTraits::value_size( m_functor ) , 0 );
+      this-> template exec< WorkTag >( ptr );
+    }
+
+  inline
+  ParallelScan( const FunctorType & arg_functor
+              , const Policy      & arg_policy
+              )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    {}
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/* Parallel patterns for Kokkos::Serial with TeamPolicy */
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ... Properties >
+class ParallelFor< FunctorType
+                 , Kokkos::TeamPolicy< Properties ... >
+                 , Kokkos::Serial
+                 >
+{
+private:
+
+  typedef TeamPolicyInternal< Kokkos::Serial , Properties ...> Policy ;
+  typedef typename Policy::member_type                       Member ;
+
+  const FunctorType  m_functor ;
+  const int          m_league ;
+  const int          m_shared ;
+
+  template< class TagType >
+  inline
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec() const
+    {
+      for ( int ileague = 0 ; ileague < m_league ; ++ileague ) {
+        m_functor( Member(ileague,m_league,m_shared) );
+      }
+    }
+
+  template< class TagType >
+  inline
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec() const
+    {
+      const TagType t{} ;
+      for ( int ileague = 0 ; ileague < m_league ; ++ileague ) {
+        m_functor( t , Member(ileague,m_league,m_shared) );
+      }
+    }
+
+public:
+
+  inline
+  void execute() const
+    {
+      Kokkos::Serial::scratch_memory_resize( 0 , m_shared );
+      this-> template exec< typename Policy::work_tag >();
+    }
+
+  ParallelFor( const FunctorType & arg_functor
+             , const Policy      & arg_policy )
+    : m_functor( arg_functor )
+    , m_league(  arg_policy.league_size() )
+    , m_shared( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , 1 ) )
+    { }
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< class FunctorType , class ReducerType , class ... Properties >
+class ParallelReduce< FunctorType
+                    , Kokkos::TeamPolicy< Properties ... >
+                    , ReducerType
+                    , Kokkos::Serial
+                    >
+{
+private:
+
+  typedef TeamPolicyInternal< Kokkos::Serial, Properties ... > Policy ;
+  typedef typename Policy::member_type                       Member ;
+  typedef typename Policy::work_tag                          WorkTag ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd , WorkTag >  ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd , WorkTag >  ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType  m_functor ;
+  const int          m_league ;
+  const ReducerType  m_reducer ;
+        pointer_type m_result_ptr ;
+  const int          m_shared ;
+
+  template< class TagType >
+  inline
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec( pointer_type ptr ) const
+    {
+      reference_type update = ValueInit::init(  ReducerConditional::select(m_functor , m_reducer) , ptr );
+
+      for ( int ileague = 0 ; ileague < m_league ; ++ileague ) {
+        m_functor( Member(ileague,m_league,m_shared) , update );
+      }
+
+      Kokkos::Impl::FunctorFinal< ReducerTypeFwd , TagType >::
+        final(  ReducerConditional::select(m_functor , m_reducer) , ptr );
+    }
+
+  template< class TagType >
+  inline
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec( pointer_type ptr ) const
+    {
+      const TagType t{} ;
+
+      reference_type update = ValueInit::init(  ReducerConditional::select(m_functor , m_reducer) , ptr );
+
+      for ( int ileague = 0 ; ileague < m_league ; ++ileague ) {
+        m_functor( t , Member(ileague,m_league,m_shared) , update );
+      }
+
+      Kokkos::Impl::FunctorFinal< ReducerTypeFwd , TagType >::
+        final(  ReducerConditional::select(m_functor , m_reducer) , ptr );
+    }
+
+public:
+
+  inline
+  void execute() const
+    {
+      pointer_type ptr = (pointer_type) Kokkos::Serial::scratch_memory_resize
+           ( ValueTraits::value_size(  ReducerConditional::select(m_functor , m_reducer) ) , m_shared );
+
+      this-> template exec< WorkTag >( m_result_ptr ? m_result_ptr : ptr );
+    }
+
+  template< class ViewType >
+  ParallelReduce( const FunctorType  & arg_functor
+                , const Policy       & arg_policy
+                , const ViewType     & arg_result ,
+                typename std::enable_if<
+                  Kokkos::is_view< ViewType >::value &&
+                  !Kokkos::is_reducer_type<ReducerType>::value
+                  ,void*>::type = NULL)
+    : m_functor( arg_functor )
+    , m_league( arg_policy.league_size() )
+    , m_reducer( InvalidType() )
+    , m_result_ptr( arg_result.ptr_on_device() )
+    , m_shared( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( m_functor , 1 ) )
+    {
+      static_assert( Kokkos::is_view< ViewType >::value
+        , "Reduction result on Kokkos::Serial must be a Kokkos::View" );
+
+      static_assert( std::is_same< typename ViewType::memory_space
+                                      , Kokkos::HostSpace >::value
+        , "Reduction result on Kokkos::Serial must be a Kokkos::View in HostSpace" );
+    }
+
+  inline
+  ParallelReduce( const FunctorType & arg_functor
+    , Policy       arg_policy
+    , const ReducerType& reducer )
+  : m_functor( arg_functor )
+  , m_league(  arg_policy.league_size() )
+  , m_reducer( reducer )
+  , m_result_ptr(  reducer.result_view().data() )
+  , m_shared( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , arg_policy.team_size() ) )
+  {
+  /*static_assert( std::is_same< typename ViewType::memory_space
+                          , Kokkos::HostSpace >::value
+  , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace" );*/
+  }
+
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+/* Nested parallel patterns for Kokkos::Serial with TeamPolicy */
+
+namespace Kokkos {
+namespace Impl {
+
+template<typename iType>
+struct TeamThreadRangeBoundariesStruct<iType,SerialTeamMember> {
+  typedef iType index_type;
+  const iType begin ;
+  const iType end ;
+  enum {increment = 1};
+  const SerialTeamMember& thread;
+
+  KOKKOS_INLINE_FUNCTION
+  TeamThreadRangeBoundariesStruct (const SerialTeamMember& arg_thread, const iType& arg_count)
+    : begin(0)
+    , end(arg_count)
+    , thread(arg_thread)
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  TeamThreadRangeBoundariesStruct (const SerialTeamMember& arg_thread, const iType& arg_begin, const iType & arg_end )
+    : begin( arg_begin )
+    , end(   arg_end)
+    , thread( arg_thread )
+    {}
+};
+
+  template<typename iType>
+  struct ThreadVectorRangeBoundariesStruct<iType,SerialTeamMember> {
+    typedef iType index_type;
+    enum {start = 0};
+    const iType end;
+    enum {increment = 1};
+
+    KOKKOS_INLINE_FUNCTION
+    ThreadVectorRangeBoundariesStruct (const SerialTeamMember& thread, const iType& count):
+      end( count )
+    {}
+  };
+
+} // namespace Impl
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::SerialTeamMember>
+TeamThreadRange( const Impl::SerialTeamMember& thread, const iType & count )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::SerialTeamMember>(thread,count);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::SerialTeamMember>
+TeamThreadRange( const Impl::SerialTeamMember& thread, const iType & begin , const iType & end )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::SerialTeamMember>(thread,begin,end);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::SerialTeamMember >
+  ThreadVectorRange(const Impl::SerialTeamMember& thread, const iType& count) {
+  return Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::SerialTeamMember >(thread,count);
+}
+
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadSingleStruct<Impl::SerialTeamMember> PerTeam(const Impl::SerialTeamMember& thread) {
+  return Impl::ThreadSingleStruct<Impl::SerialTeamMember>(thread);
+}
+
+KOKKOS_INLINE_FUNCTION
+Impl::VectorSingleStruct<Impl::SerialTeamMember> PerThread(const Impl::SerialTeamMember& thread) {
+  return Impl::VectorSingleStruct<Impl::SerialTeamMember>(thread);
+}
+
+} // namespace Kokkos
+
+namespace Kokkos {
+
+  /** \brief  Inter-thread parallel_for. Executes lambda(iType i) for each i=0..N-1.
+   *
+   * The range i=0..N-1 is mapped to all threads of the the calling thread team.
+   * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::SerialTeamMember>& loop_boundaries, const Lambda& lambda) {
+  for( iType i = loop_boundaries.begin; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+/** \brief  Inter-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all threads of the the calling thread team and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::SerialTeamMember>& loop_boundaries,
+                     const Lambda & lambda, ValueType& result) {
+
+  result = ValueType();
+
+  for( iType i = loop_boundaries.begin; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    result+=tmp;
+  }
+
+  result = loop_boundaries.thread.team_reduce(result,Impl::JoinAdd<ValueType>());
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::SerialTeamMember>& loop_boundaries,
+                     const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+  ValueType result = init_result;
+
+  for( iType i = loop_boundaries.begin; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    join(result,tmp);
+  }
+
+  init_result = loop_boundaries.thread.team_reduce(result,Impl::JoinLambdaAdapter<ValueType,JoinType>(join));
+}
+
+} //namespace Kokkos
+
+namespace Kokkos {
+/** \brief  Intra-thread vector parallel_for. Executes lambda(iType i) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread.
+ * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::SerialTeamMember >&
+    loop_boundaries, const Lambda& lambda) {
+  #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+  #pragma ivdep
+  #endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::SerialTeamMember >&
+      loop_boundaries, const Lambda & lambda, ValueType& result) {
+  result = ValueType();
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    result+=tmp;
+  }
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::SerialTeamMember >&
+      loop_boundaries, const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+  ValueType result = init_result;
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    join(result,tmp);
+  }
+  init_result = result;
+}
+
+/** \brief  Intra-thread vector parallel exclusive prefix sum. Executes lambda(iType i, ValueType & val, bool final)
+ *          for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes in the thread and a scan operation is performed.
+ * Depending on the target execution space the operator might be called twice: once with final=false
+ * and once with final=true. When final==true val contains the prefix sum value. The contribution of this
+ * "i" needs to be added to val no matter whether final==true or not. In a serial execution
+ * (i.e. team_size==1) the operator is only called once with final==true. Scan_val will be set
+ * to the final sum value over all vector lanes.
+ * This functionality requires C++11 support.*/
+template< typename iType, class FunctorType >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::SerialTeamMember >&
+      loop_boundaries, const FunctorType & lambda) {
+
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
+  typedef typename ValueTraits::value_type value_type ;
+
+  value_type scan_val = value_type();
+
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,scan_val,true);
+  }
+}
+
+} // namespace Kokkos
+
+namespace Kokkos {
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::SerialTeamMember>& , const FunctorType& lambda) {
+  lambda();
+}
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::SerialTeamMember>& , const FunctorType& lambda) {
+  lambda();
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::SerialTeamMember>& , const FunctorType& lambda, ValueType& val) {
+  lambda(val);
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::SerialTeamMember>& , const FunctorType& lambda, ValueType& val) {
+  lambda(val);
+}
+}
+
+//----------------------------------------------------------------------------
+
+#include <impl/Kokkos_Serial_Task.hpp>
+
+#endif // defined( KOKKOS_HAVE_SERIAL )
+#endif /* #define KOKKOS_SERIAL_HPP */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/core/src/Kokkos_TaskPolicy.hpp b/lib/kokkos/core/src/Kokkos_TaskPolicy.hpp
new file mode 100644
index 0000000000..fc9113b750
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_TaskPolicy.hpp
@@ -0,0 +1,1109 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#ifndef KOKKOS_TASKPOLICY_HPP
+#define KOKKOS_TASKPOLICY_HPP
+
+//----------------------------------------------------------------------------
+
+#include <Kokkos_Core_fwd.hpp>
+
+// If compiling with CUDA then must be using CUDA 8 or better
+// and use relocateable device code to enable the task policy.
+// nvcc relocatable device code option: --relocatable-device-code=true
+
+#if ( defined( KOKKOS_COMPILER_NVCC ) )
+  #if ( 8000 <= CUDA_VERSION ) && \
+      defined( KOKKOS_CUDA_USE_RELOCATABLE_DEVICE_CODE )
+
+  #define KOKKOS_ENABLE_TASKPOLICY
+
+  #endif
+#else
+
+#define KOKKOS_ENABLE_TASKPOLICY
+
+#endif
+
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+
+#include <Kokkos_MemoryPool.hpp>
+#include <impl/Kokkos_Tags.hpp>
+#include <impl/Kokkos_TaskQueue.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+enum TaskType { TaskTeam   = Impl::TaskBase<void,void,void>::TaskTeam
+              , TaskSingle = Impl::TaskBase<void,void,void>::TaskSingle };
+
+enum TaskPriority { TaskHighPriority    = 0
+                  , TaskRegularPriority = 1
+                  , TaskLowPriority     = 2 };
+
+template< typename Space >
+class TaskPolicy ;
+
+template< typename Space >
+void wait( TaskPolicy< Space > const & );
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+/*\brief  Implementation data for task data management, access, and execution.
+ *
+ *  CRTP Inheritance structure to allow static_cast from the
+ *  task root type and a task's FunctorType.
+ *
+ *    TaskBase< Space , ResultType , FunctorType >
+ *      : TaskBase< Space , ResultType , void >
+ *      , FunctorType
+ *      { ... };
+ *
+ *    TaskBase< Space , ResultType , void >
+ *      : TaskBase< Space , void , void >
+ *      { ... };
+ */
+template< typename Space , typename ResultType , typename FunctorType >
+class TaskBase ;
+
+template< typename Space >
+class TaskExec ;
+
+}} // namespace Kokkos::Impl
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+/**
+ *
+ *  Future< space >  // value_type == void
+ *  Future< value >  // space == Default
+ *  Future< value , space >
+ *
+ */
+template< typename Arg1 /* = void */ , typename Arg2 /* = void */ >
+class Future {
+private:
+
+  template< typename > friend class TaskPolicy ;
+  template< typename , typename > friend class Future ;
+  template< typename , typename , typename > friend class Impl::TaskBase ;
+
+  enum { Arg1_is_space  = Kokkos::Impl::is_space< Arg1 >::value };
+  enum { Arg2_is_space  = Kokkos::Impl::is_space< Arg2 >::value };
+  enum { Arg1_is_value  = ! Arg1_is_space &&
+                          ! std::is_same< Arg1 , void >::value };
+  enum { Arg2_is_value  = ! Arg2_is_space &&
+                          ! std::is_same< Arg2 , void >::value };
+
+  static_assert( ! ( Arg1_is_space && Arg2_is_space )
+               , "Future cannot be given two spaces" );
+
+  static_assert( ! ( Arg1_is_value && Arg2_is_value )
+               , "Future cannot be given two value types" );
+
+  using ValueType =
+    typename std::conditional< Arg1_is_value , Arg1 ,
+    typename std::conditional< Arg2_is_value , Arg2 , void
+    >::type >::type ;
+
+  using Space =
+    typename std::conditional< Arg1_is_space , Arg1 ,
+    typename std::conditional< Arg2_is_space , Arg2 , void
+    >::type >::type ;
+
+  using task_base  = Impl::TaskBase< Space , ValueType , void > ;
+  using queue_type = Impl::TaskQueue< Space > ;
+
+  task_base * m_task ;
+
+  KOKKOS_INLINE_FUNCTION explicit
+  Future( task_base * task ) : m_task(0)
+    { if ( task ) queue_type::assign( & m_task , task ); }
+
+  //----------------------------------------
+
+public:
+
+  using execution_space = typename Space::execution_space ;
+  using value_type      = ValueType ;
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  bool is_null() const { return 0 == m_task ; }
+
+  KOKKOS_INLINE_FUNCTION
+  int reference_count() const
+    { return 0 != m_task ? m_task->reference_count() : 0 ; }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  ~Future() { if ( m_task ) queue_type::assign( & m_task , (task_base*)0 ); }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr Future() noexcept : m_task(0) {}
+
+  KOKKOS_INLINE_FUNCTION
+  Future( Future && rhs )
+    : m_task( rhs.m_task ) { rhs.m_task = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  Future( const Future & rhs )
+    : m_task(0)
+    { if ( rhs.m_task ) queue_type::assign( & m_task , rhs.m_task ); }
+
+  KOKKOS_INLINE_FUNCTION
+  Future & operator = ( Future && rhs )
+    {
+      if ( m_task ) queue_type::assign( & m_task , (task_base*)0 );
+      m_task = rhs.m_task ;
+      rhs.m_task = 0 ;
+      return *this ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  Future & operator = ( const Future & rhs )
+    {
+      if ( m_task || rhs.m_task ) queue_type::assign( & m_task , rhs.m_task );
+      return *this ;
+    }
+
+  //----------------------------------------
+
+  template< class A1 , class A2 >
+  KOKKOS_INLINE_FUNCTION
+  Future( Future<A1,A2> && rhs )
+    : m_task( rhs.m_task )
+    {
+      static_assert
+        ( std::is_same< Space , void >::value ||
+          std::is_same< Space , typename Future<A1,A2>::Space >::value
+        , "Assigned Futures must have the same space" );
+
+      static_assert
+        ( std::is_same< value_type , void >::value ||
+          std::is_same< value_type , typename Future<A1,A2>::value_type >::value
+        , "Assigned Futures must have the same value_type" );
+
+      rhs.m_task = 0 ;
+    }
+
+  template< class A1 , class A2 >
+  KOKKOS_INLINE_FUNCTION
+  Future( const Future<A1,A2> & rhs )
+    : m_task(0)
+    {
+      static_assert
+        ( std::is_same< Space , void >::value ||
+          std::is_same< Space , typename Future<A1,A2>::Space >::value
+        , "Assigned Futures must have the same space" );
+
+      static_assert
+        ( std::is_same< value_type , void >::value ||
+          std::is_same< value_type , typename Future<A1,A2>::value_type >::value
+        , "Assigned Futures must have the same value_type" );
+
+      if ( rhs.m_task ) queue_type::assign( & m_task , rhs.m_task );
+    }
+
+  template< class A1 , class A2 >
+  KOKKOS_INLINE_FUNCTION
+  Future & operator = ( const Future<A1,A2> & rhs )
+    {
+      static_assert
+        ( std::is_same< Space , void >::value ||
+          std::is_same< Space , typename Future<A1,A2>::Space >::value
+        , "Assigned Futures must have the same space" );
+
+      static_assert
+        ( std::is_same< value_type , void >::value ||
+          std::is_same< value_type , typename Future<A1,A2>::value_type >::value
+        , "Assigned Futures must have the same value_type" );
+
+      if ( m_task || rhs.m_task ) queue_type::assign( & m_task , rhs.m_task );
+      return *this ;
+    }
+
+  template< class A1 , class A2 >
+  KOKKOS_INLINE_FUNCTION
+  Future & operator = ( Future<A1,A2> && rhs )
+    {
+      static_assert
+        ( std::is_same< Space , void >::value ||
+          std::is_same< Space , typename Future<A1,A2>::Space >::value
+        , "Assigned Futures must have the same space" );
+
+      static_assert
+        ( std::is_same< value_type , void >::value ||
+          std::is_same< value_type , typename Future<A1,A2>::value_type >::value
+        , "Assigned Futures must have the same value_type" );
+
+      if ( m_task ) queue_type::assign( & m_task , (task_base*) 0 );
+      m_task = rhs.m_task ;
+      rhs.m_task = 0 ;
+      return *this ;
+    }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  typename task_base::get_return_type
+  get() const
+    {
+      if ( 0 == m_task ) {
+        Kokkos::abort( "Kokkos:::Future::get ERROR: is_null()");
+      }
+      return m_task->get();
+    }
+};
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template< typename ExecSpace >
+class TaskPolicy
+{
+private:
+
+  using track_type = Kokkos::Experimental::Impl::SharedAllocationTracker ;
+  using queue_type = Kokkos::Impl::TaskQueue< ExecSpace > ;
+  using task_base  = Impl::TaskBase< ExecSpace , void , void > ;
+
+  track_type   m_track ;
+  queue_type * m_queue ;
+
+  //----------------------------------------
+  // Process optional arguments to spawn and respawn functions
+
+  KOKKOS_INLINE_FUNCTION static
+  void assign( task_base * const ) {}
+
+  // TaskTeam or TaskSingle
+  template< typename ... Options >
+  KOKKOS_INLINE_FUNCTION static
+  void assign( task_base * const task
+             , TaskType const & arg
+             , Options const & ... opts )
+    {
+      task->m_task_type = arg ;
+      assign( task , opts ... );
+    }
+
+  // TaskHighPriority or TaskRegularPriority or TaskLowPriority
+  template< typename ... Options >
+  KOKKOS_INLINE_FUNCTION static
+  void assign( task_base * const task
+             , TaskPriority const & arg
+             , Options const & ... opts )
+    {
+      task->m_priority = arg ;
+      assign( task , opts ... );
+    }
+
+  // Future for a dependence
+  template< typename A1 , typename A2 , typename ... Options >
+  KOKKOS_INLINE_FUNCTION static
+  void assign( task_base * const task
+             , Future< A1 , A2 > const & arg 
+             , Options const & ... opts )
+    {
+      // Assign dependence to task->m_next
+      // which will be processed within subsequent call to schedule.
+      // Error if the dependence is reset.
+
+      if ( 0 != Kokkos::atomic_exchange(& task->m_next, arg.m_task) ) {
+        Kokkos::abort("TaskPolicy ERROR: resetting task dependence");
+      }
+
+      if ( 0 != arg.m_task ) {
+        // The future may be destroyed upon returning from this call
+        // so increment reference count to track this assignment.
+        Kokkos::atomic_fetch_add( &(arg.m_task->m_ref_count) , 1 );
+      }
+
+      assign( task , opts ... );
+    }
+
+  //----------------------------------------
+
+public:
+
+  using execution_policy = TaskPolicy ;
+  using execution_space  = ExecSpace ;
+  using memory_space     = typename queue_type::memory_space ;
+  using member_type      = Kokkos::Impl::TaskExec< ExecSpace > ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskPolicy() : m_track(), m_queue(0) {}
+
+  KOKKOS_INLINE_FUNCTION
+  TaskPolicy( TaskPolicy && rhs ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskPolicy( TaskPolicy const & rhs ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskPolicy & operator = ( TaskPolicy && rhs ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskPolicy & operator = ( TaskPolicy const & rhs ) = default ;
+
+  TaskPolicy( memory_space const & arg_memory_space
+            , unsigned const arg_memory_pool_capacity
+            , unsigned const arg_memory_pool_log2_superblock = 12 )
+    : m_track()
+    , m_queue(0)
+    {
+      typedef Kokkos::Experimental::Impl::SharedAllocationRecord
+        < memory_space , typename queue_type::Destroy >
+          record_type ;
+
+      record_type * record =
+        record_type::allocate( arg_memory_space
+                             , "TaskQueue"
+                             , sizeof(queue_type)
+                             );
+
+      m_queue = new( record->data() )
+        queue_type( arg_memory_space
+                  , arg_memory_pool_capacity
+                  , arg_memory_pool_log2_superblock );
+
+      record->m_destroy.m_queue = m_queue ;
+
+      m_track.assign_allocated_record_to_uninitialized( record );
+    }
+
+  //----------------------------------------
+  /**\brief  Allocation size for a spawned task */
+  template< typename FunctorType >
+  KOKKOS_FUNCTION
+  size_t spawn_allocation_size() const
+    {
+      using task_type  = Impl::TaskBase< execution_space
+                                       , typename FunctorType::value_type
+                                       , FunctorType > ;
+
+      return m_queue->allocate_block_size( sizeof(task_type) );
+    }
+
+  /**\brief  Allocation size for a when_all aggregate */
+  KOKKOS_FUNCTION
+  size_t when_all_allocation_size( int narg ) const
+    {
+      using task_base  = Kokkos::Impl::TaskBase< ExecSpace , void , void > ;
+
+      return m_queue->allocate_block_size( sizeof(task_base) + narg * sizeof(task_base*) );
+    }
+
+  //----------------------------------------
+
+  /**\brief  A task spawns a task with options
+   *
+   *  1) High, Normal, or Low priority
+   *  2) With or without dependence
+   *  3) Team or Serial
+   */
+  template< typename FunctorType , typename ... Options >
+  KOKKOS_FUNCTION
+  Future< typename FunctorType::value_type , ExecSpace >
+  task_spawn( FunctorType const & arg_functor 
+            , Options const & ... arg_options
+            ) const
+    {
+      using value_type  = typename FunctorType::value_type ;
+      using future_type = Future< value_type , execution_space > ;
+      using task_type   = Impl::TaskBase< execution_space
+                                        , value_type
+                                        , FunctorType > ;
+
+      //----------------------------------------
+      // Give single-thread back-ends an opportunity to clear
+      // queue of ready tasks before allocating a new task
+
+      m_queue->iff_single_thread_recursive_execute();
+
+      //----------------------------------------
+
+      future_type f ;
+
+      // Allocate task from memory pool
+      f.m_task =
+        reinterpret_cast< task_type * >(m_queue->allocate(sizeof(task_type)));
+
+      if ( f.m_task ) {
+
+        // Placement new construction
+        new ( f.m_task ) task_type( arg_functor );
+
+        // Reference count starts at two
+        // +1 for matching decrement when task is complete
+        // +1 for future
+        f.m_task->m_queue      = m_queue ;
+        f.m_task->m_ref_count  = 2 ;
+        f.m_task->m_alloc_size = sizeof(task_type);
+
+        assign( f.m_task , arg_options... );
+
+        // Spawning from within the execution space so the
+        // apply function pointer is guaranteed to be valid
+        f.m_task->m_apply = task_type::apply ;
+
+        m_queue->schedule( f.m_task );
+        // this task may be updated or executed at any moment
+      }
+
+      return f ;
+    }
+
+  /**\brief  The host process spawns a task with options
+   *
+   *  1) High, Normal, or Low priority
+   *  2) With or without dependence
+   *  3) Team or Serial
+   */
+  template< typename FunctorType , typename ... Options >
+  inline
+  Future< typename FunctorType::value_type , ExecSpace >
+  host_spawn( FunctorType const & arg_functor 
+            , Options const & ... arg_options
+            ) const
+    {
+      using value_type  = typename FunctorType::value_type ;
+      using future_type = Future< value_type , execution_space > ;
+      using task_type   = Impl::TaskBase< execution_space
+                                        , value_type
+                                        , FunctorType > ;
+
+      future_type f ;
+
+      // Allocate task from memory pool
+      f.m_task = 
+        reinterpret_cast<task_type*>( m_queue->allocate(sizeof(task_type)) );
+
+      if ( f.m_task ) {
+
+        // Placement new construction
+        new( f.m_task ) task_type( arg_functor );
+
+        // Reference count starts at two:
+        // +1 to match decrement when task completes
+        // +1 for the future
+        f.m_task->m_queue      = m_queue ;
+        f.m_task->m_ref_count  = 2 ;
+        f.m_task->m_alloc_size = sizeof(task_type);
+
+        assign( f.m_task , arg_options... );
+
+        // Potentially spawning outside execution space so the
+        // apply function pointer must be obtained from execution space.
+        // Required for Cuda execution space function pointer.
+        queue_type::specialization::template
+          proc_set_apply< FunctorType >( & f.m_task->m_apply );
+
+        m_queue->schedule( f.m_task );
+      }
+      return f ;
+    }
+
+  /**\brief  Return a future that is complete
+   *         when all input futures are complete.
+   */
+  template< typename A1 , typename A2 >
+  KOKKOS_FUNCTION
+  Future< ExecSpace >
+  when_all( int narg , Future< A1 , A2 > const * const arg ) const
+    {
+      static_assert
+        ( std::is_same< execution_space
+                      , typename Future< A1 , A2 >::execution_space
+                      >::value
+        , "Future must have same execution space" );
+
+      using future_type = Future< ExecSpace > ;
+      using task_base   = Kokkos::Impl::TaskBase< ExecSpace , void , void > ;
+
+      future_type f ;
+
+      size_t const size  = sizeof(task_base) + narg * sizeof(task_base*);
+
+      f.m_task =
+        reinterpret_cast< task_base * >( m_queue->allocate( size ) );
+
+      if ( f.m_task ) {
+
+        new( f.m_task ) task_base();
+
+        // Reference count starts at two:
+        // +1 to match decrement when task completes
+        // +1 for the future
+        f.m_task->m_queue      = m_queue ;
+        f.m_task->m_ref_count  = 2 ;
+        f.m_task->m_alloc_size = size ;
+        f.m_task->m_dep_count  = narg ;
+        f.m_task->m_task_type  = task_base::Aggregate ;
+
+        task_base ** const dep = f.m_task->aggregate_dependences();
+
+        // Assign dependences to increment their reference count
+        // The futures may be destroyed upon returning from this call
+        // so increment reference count to track this assignment.
+
+        for ( int i = 0 ; i < narg ; ++i ) {
+          task_base * const t = dep[i] = arg[i].m_task ;
+          if ( 0 != t ) {
+            Kokkos::atomic_fetch_add( &(t->m_ref_count) , 1 );
+          }
+        }
+
+        m_queue->schedule( f.m_task );
+        // this when_all may be processed at any moment
+      }
+
+      return f ;
+    }
+
+  /**\brief  An executing task respawns itself with options
+   *
+   *  1) High, Normal, or Low priority
+   *  2) With or without dependence
+   */
+  template< class FunctorType , typename ... Options >
+  KOKKOS_FUNCTION
+  void respawn( FunctorType * task_self
+              , Options const & ... arg_options ) const
+    {
+      using value_type  = typename FunctorType::value_type ;
+      using task_type   = Impl::TaskBase< execution_space
+                                        , value_type
+                                        , FunctorType > ;
+
+      task_base * const zero = (task_base *) 0 ;
+      task_base * const lock = (task_base *) task_base::LockTag ;
+      task_type * const task = static_cast< task_type * >( task_self );
+
+      // Precondition:
+      //   task is in Executing state
+      //   therefore  m_next == LockTag
+      //
+      // Change to m_next == 0 for no dependence
+
+      if ( lock != Kokkos::atomic_exchange( & task->m_next, zero ) ) {
+        Kokkos::abort("TaskPolicy::respawn ERROR: already respawned");
+      }
+
+      assign( task , arg_options... );
+
+      // Postcondition:
+      //   task is in Executing-Respawn state
+      //   therefore  m_next == dependece or 0
+    }
+
+  //----------------------------------------
+
+  template< typename S >
+  friend
+  void Kokkos::wait( Kokkos::TaskPolicy< S > const & );
+
+  //----------------------------------------
+
+  inline
+  int allocation_capacity() const noexcept
+    { return m_queue->m_memory.get_mem_size(); }
+
+  KOKKOS_INLINE_FUNCTION
+  int allocated_task_count() const noexcept
+    { return m_queue->m_count_alloc ; }
+
+  KOKKOS_INLINE_FUNCTION
+  int allocated_task_count_max() const noexcept
+    { return m_queue->m_max_alloc ; }
+
+  KOKKOS_INLINE_FUNCTION
+  long allocated_task_count_accum() const noexcept
+    { return m_queue->m_accum_alloc ; }
+
+};
+
+template< typename ExecSpace >
+inline
+void wait( TaskPolicy< ExecSpace > const & policy )
+{ policy.m_queue->execute(); }
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+struct FutureValueTypeIsVoidError {};
+
+template < class ExecSpace , class ResultType , class FunctorType >
+class TaskMember ;
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+/**\brief  States of a task */
+enum TaskState
+  { TASK_STATE_NULL         = 0  ///<  Does not exist
+  , TASK_STATE_CONSTRUCTING = 1  ///<  Is under construction
+  , TASK_STATE_WAITING      = 2  ///<  Is waiting for execution
+  , TASK_STATE_EXECUTING    = 4  ///<  Is executing
+  , TASK_STATE_COMPLETE     = 8  ///<  Execution is complete
+  };
+
+/**\brief  Tag for Future<Latch,Space>
+ */
+struct Latch {};
+
+/**
+ *
+ *  Future< space >  // value_type == void
+ *  Future< value >  // space == Default
+ *  Future< value , space >
+ *
+ */
+template< class Arg1 = void , class Arg2 = void >
+class Future {
+private:
+
+  template< class , class , class > friend class Impl::TaskMember ;
+  template< class > friend class TaskPolicy ;
+  template< class , class > friend class Future ;
+
+  // Argument #2, if not void, must be the space.
+  enum { Arg1_is_space  = Kokkos::Impl::is_execution_space< Arg1 >::value };
+  enum { Arg2_is_space  = Kokkos::Impl::is_execution_space< Arg2 >::value };
+  enum { Arg2_is_void   = std::is_same< Arg2 , void >::value };
+
+  struct ErrorNoExecutionSpace {};
+
+  enum { Opt1  =   Arg1_is_space && Arg2_is_void
+       , Opt2  = ! Arg1_is_space && Arg2_is_void
+       , Opt3  = ! Arg1_is_space && Arg2_is_space
+       , OptOK = Kokkos::Impl::StaticAssert< Opt1 || Opt2 || Opt3 , ErrorNoExecutionSpace >::value
+       };
+
+  typedef typename
+    Kokkos::Impl::if_c< Opt2 || Opt3 , Arg1 , void >::type
+      ValueType ;
+
+  typedef typename
+    Kokkos::Impl::if_c< Opt1 , Arg1 , typename
+    Kokkos::Impl::if_c< Opt2 , Kokkos::DefaultExecutionSpace , typename
+    Kokkos::Impl::if_c< Opt3 , Arg2 , void
+    >::type >::type >::type
+      ExecutionSpace ;
+
+  typedef Impl::TaskMember< ExecutionSpace , void , void >       TaskRoot ;
+  typedef Impl::TaskMember< ExecutionSpace , ValueType , void >  TaskValue ;
+
+  TaskRoot * m_task ;
+
+  KOKKOS_INLINE_FUNCTION explicit
+  Future( TaskRoot * task )
+    : m_task(0)
+    { TaskRoot::assign( & m_task , TaskRoot::template verify_type< ValueType >( task ) ); }
+
+  //----------------------------------------
+
+public:
+
+  typedef ValueType       value_type;
+  typedef ExecutionSpace  execution_space ;
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  TaskState get_task_state() const
+    { return 0 != m_task ? m_task->get_state() : TASK_STATE_NULL ; }
+
+  KOKKOS_INLINE_FUNCTION
+  bool is_null() const { return 0 == m_task ; }
+
+  KOKKOS_INLINE_FUNCTION
+  int reference_count() const
+    { return 0 != m_task ? m_task->reference_count() : 0 ; }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  ~Future() { TaskRoot::assign( & m_task , 0 ); }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  Future() : m_task(0) {}
+
+  KOKKOS_INLINE_FUNCTION
+  Future( const Future & rhs )
+    : m_task(0)
+    { TaskRoot::assign( & m_task , rhs.m_task ); }
+
+  KOKKOS_INLINE_FUNCTION
+  Future & operator = ( const Future & rhs )
+    { TaskRoot::assign( & m_task , rhs.m_task ); return *this ; }
+
+  //----------------------------------------
+
+  template< class A1 , class A2 >
+  KOKKOS_INLINE_FUNCTION
+  Future( const Future<A1,A2> & rhs )
+    : m_task(0)
+    { TaskRoot::assign( & m_task , TaskRoot::template verify_type< value_type >( rhs.m_task ) ); }
+
+  template< class A1 , class A2 >
+  KOKKOS_INLINE_FUNCTION
+  Future & operator = ( const Future<A1,A2> & rhs )
+    { TaskRoot::assign( & m_task , TaskRoot::template verify_type< value_type >( rhs.m_task ) ); return *this ; }
+
+  //----------------------------------------
+
+  typedef typename TaskValue::get_result_type get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const
+    {
+      if ( 0 == m_task ) {
+        Kokkos::abort( "Kokkos::Experimental::Future::get ERROR: is_null()");
+      }
+      return static_cast<TaskValue*>( m_task )->get();  
+    }
+
+  //----------------------------------------
+};
+
+template< class Arg2 >
+class Future< Latch , Arg2 > {
+private:
+
+  template< class , class , class > friend class Impl::TaskMember ;
+  template< class > friend class TaskPolicy ;
+  template< class , class > friend class Future ;
+
+  // Argument #2, if not void, must be the space.
+  enum { Arg2_is_space  = Kokkos::Impl::is_execution_space< Arg2 >::value };
+  enum { Arg2_is_void   = std::is_same< Arg2 , void >::value };
+
+  static_assert( Arg2_is_space || Arg2_is_void 
+               , "Future template argument #2 must be a space" );
+
+  typedef typename
+    std::conditional< Arg2_is_space , Arg2 , Kokkos::DefaultExecutionSpace >
+     ::type ExecutionSpace ;
+
+  typedef Impl::TaskMember< ExecutionSpace , void , void >  TaskRoot ;
+
+  TaskRoot * m_task ;
+
+  KOKKOS_INLINE_FUNCTION explicit
+  Future( TaskRoot * task )
+    : m_task(0)
+    { TaskRoot::assign( & m_task , task ); }
+
+  //----------------------------------------
+
+public:
+
+  typedef void            value_type;
+  typedef ExecutionSpace  execution_space ;
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void add( const int k ) const
+    { if ( 0 != m_task ) m_task->latch_add(k); }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  TaskState get_task_state() const
+    { return 0 != m_task ? m_task->get_state() : TASK_STATE_NULL ; }
+
+  KOKKOS_INLINE_FUNCTION
+  bool is_null() const { return 0 == m_task ; }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  ~Future() { TaskRoot::assign( & m_task , 0 ); }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  Future() : m_task(0) {}
+
+  KOKKOS_INLINE_FUNCTION
+  Future( const Future & rhs )
+    : m_task(0)
+    { TaskRoot::assign( & m_task , rhs.m_task ); }
+
+  KOKKOS_INLINE_FUNCTION
+  Future & operator = ( const Future & rhs )
+    { TaskRoot::assign( & m_task , rhs.m_task ); return *this ; }
+
+  //----------------------------------------
+
+  typedef void get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  void get() const {}
+
+  //----------------------------------------
+
+};
+
+namespace Impl {
+
+template< class T >
+struct is_future : public std::false_type {};
+
+template< class Arg0 , class Arg1 >
+struct is_future< Kokkos::Experimental::Future<Arg0,Arg1> >
+  : public std::true_type {};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+/** \brief  If the argument is an execution space then a serial task in that space */
+template< class Arg0 = Kokkos::DefaultExecutionSpace >
+class TaskPolicy {
+public:
+
+  typedef typename Arg0::execution_space  execution_space ;
+
+  //----------------------------------------
+
+  TaskPolicy
+    ( const unsigned arg_task_max_count
+    , const unsigned arg_task_max_size
+    , const unsigned arg_task_default_dependence_capacity = 4
+    , const unsigned arg_task_team_size = 0 /* choose default */
+    );
+
+  TaskPolicy() = default ;
+  TaskPolicy( TaskPolicy && rhs ) = default ;
+  TaskPolicy( const TaskPolicy & rhs ) = default ;
+  TaskPolicy & operator = ( TaskPolicy && rhs ) = default ;
+  TaskPolicy & operator = ( const TaskPolicy & rhs ) = default ;
+
+  //----------------------------------------
+  /** \brief  Create a serial task with storage for dependences.
+   *
+   *  Postcondition: Task is in the 'constructing' state.
+   */
+  template< class FunctorType >
+  Future< typename FunctorType::value_type , execution_space >
+  create( const FunctorType & functor
+        , const unsigned      dependence_capacity /* = default */ );
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  create_team( const FunctorType & functor
+             , const unsigned dependence_capacity /* = default */ );
+
+  /** \brief  Set dependence that 'after' cannot start execution
+   *          until 'before' has completed.
+   *
+   *  Precondition: The 'after' task must be in then 'Constructing' state.
+   */
+  template< class TA , class TB >
+  void add_dependence( const Future<TA,execution_space> & after
+                     , const Future<TB,execution_space> & before ) const ;
+
+  /** \brief  Spawn a task in the 'Constructing' state
+   *
+   *  Precondition:  Task is in the 'constructing' state.
+   *  Postcondition: Task is waiting, executing, or complete.
+   */
+  template< class T >
+  const Future<T,execution_space> &
+  spawn( const Future<T,execution_space> & ) const ;
+
+  //----------------------------------------
+  /** \brief  Query dependence of an executing task */
+
+  template< class FunctorType >
+  Future< execution_space >
+  get_dependence( FunctorType * , const int ) const ;
+
+  //----------------------------------------
+  /** \brief  Clear current dependences of an executing task
+   *          in preparation for setting new dependences and
+   *          respawning.
+   *
+   * Precondition: The functor must be a task in the executing state.
+   */
+  template< class FunctorType >
+  void clear_dependence( FunctorType * ) const ;
+
+  /** \brief  Set dependence that 'after' cannot resume execution
+   *          until 'before' has completed.
+   *
+   *  The 'after' functor must be in the executing state
+   */
+  template< class FunctorType , class TB >
+  void add_dependence( FunctorType * after
+                     , const Future<TB,execution_space> & before ) const ;
+
+  /** \brief  Respawn (reschedule) an executing task to be called again
+   *          after all dependences have completed.
+   */
+  template< class FunctorType >
+  void respawn( FunctorType * ) const ;
+};
+
+//----------------------------------------------------------------------------
+/** \brief  Create and spawn a single-thread task */
+template< class ExecSpace , class FunctorType >
+inline
+Future< typename FunctorType::value_type , ExecSpace >
+spawn( TaskPolicy<ExecSpace> & policy , const FunctorType & functor )
+{ return policy.spawn( policy.create( functor ) ); }
+
+/** \brief  Create and spawn a single-thread task with dependences */
+template< class ExecSpace , class FunctorType , class Arg0 , class Arg1 >
+inline
+Future< typename FunctorType::value_type , ExecSpace >
+spawn( TaskPolicy<ExecSpace>   & policy
+     , const FunctorType       & functor
+     , const Future<Arg0,Arg1> & before_0
+     , const Future<Arg0,Arg1> & before_1 )
+{
+  Future< typename FunctorType::value_type , ExecSpace > f ;
+  f = policy.create( functor , 2 );
+  policy.add_dependence( f , before_0 );
+  policy.add_dependence( f , before_1 );
+  policy.spawn( f );
+  return f ;
+}
+
+//----------------------------------------------------------------------------
+/** \brief  Create and spawn a parallel_for task */
+template< class ExecSpace , class ParallelPolicyType , class FunctorType >
+inline
+Future< typename FunctorType::value_type , ExecSpace >
+spawn_foreach( TaskPolicy<ExecSpace>     & task_policy
+             , const ParallelPolicyType  & parallel_policy
+             , const FunctorType         & functor )
+{ return task_policy.spawn( task_policy.create_foreach( parallel_policy , functor ) ); }
+
+/** \brief  Create and spawn a parallel_reduce task */
+template< class ExecSpace , class ParallelPolicyType , class FunctorType >
+inline
+Future< typename FunctorType::value_type , ExecSpace >
+spawn_reduce( TaskPolicy<ExecSpace>     & task_policy
+            , const ParallelPolicyType  & parallel_policy
+            , const FunctorType         & functor )
+{ return task_policy.spawn( task_policy.create_reduce( parallel_policy , functor ) ); }
+
+//----------------------------------------------------------------------------
+/** \brief  Respawn a task functor with dependences */
+template< class ExecSpace , class FunctorType , class Arg0 , class Arg1 >
+inline
+void respawn( TaskPolicy<ExecSpace>   & policy
+            , FunctorType *             functor
+            , const Future<Arg0,Arg1> & before_0
+            , const Future<Arg0,Arg1> & before_1
+            )
+{
+  policy.clear_dependence( functor );
+  policy.add_dependence( functor , before_0 );
+  policy.add_dependence( functor , before_1 );
+  policy.respawn( functor );
+}
+
+//----------------------------------------------------------------------------
+
+template< class ExecSpace >
+void wait( TaskPolicy< ExecSpace > & );
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #ifndef KOKKOS_TASKPOLICY_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_Threads.hpp b/lib/kokkos/core/src/Kokkos_Threads.hpp
new file mode 100644
index 0000000000..c9ebbf9265
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Threads.hpp
@@ -0,0 +1,222 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_THREADS_HPP
+#define KOKKOS_THREADS_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+
+#include <cstddef>
+#include <iosfwd>
+#include <Kokkos_HostSpace.hpp>
+#include <Kokkos_ScratchSpace.hpp>
+#include <Kokkos_Layout.hpp>
+#include <Kokkos_MemoryTraits.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+class ThreadsExec ;
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/** \brief  Execution space for a pool of Pthreads or C11 threads on a CPU. */
+class Threads {
+public:
+  //! \name Type declarations that all Kokkos devices must provide.
+  //@{
+  //! Tag this class as a kokkos execution space
+  typedef Threads                  execution_space ;
+  typedef Kokkos::HostSpace        memory_space ;
+
+  //! This execution space preferred device_type
+  typedef Kokkos::Device<execution_space,memory_space> device_type;
+
+  typedef Kokkos::LayoutRight      array_layout ;
+  typedef memory_space::size_type  size_type ;
+
+  typedef ScratchMemorySpace< Threads >  scratch_memory_space ;
+
+
+  //@}
+  /*------------------------------------------------------------------------*/
+  //! \name Static functions that all Kokkos devices must implement.
+  //@{
+
+  /// \brief True if and only if this method is being called in a
+  ///   thread-parallel function.
+  static int in_parallel();
+
+  /** \brief  Set the device in a "sleep" state.
+   *
+   * This function sets the device in a "sleep" state in which it is
+   * not ready for work.  This may consume less resources than if the
+   * device were in an "awake" state, but it may also take time to
+   * bring the device from a sleep state to be ready for work.
+   *
+   * \return True if the device is in the "sleep" state, else false if
+   *   the device is actively working and could not enter the "sleep"
+   *   state.
+   */
+  static bool sleep();
+
+  /// \brief Wake the device from the 'sleep' state so it is ready for work.
+  ///
+  /// \return True if the device is in the "ready" state, else "false"
+  ///  if the device is actively working (which also means that it's
+  ///  awake).
+  static bool wake();
+
+  /// \brief Wait until all dispatched functors complete.
+  ///
+  /// The parallel_for or parallel_reduce dispatch of a functor may
+  /// return asynchronously, before the functor completes.  This
+  /// method does not return until all dispatched functors on this
+  /// device have completed.
+  static void fence();
+
+  /// \brief Free any resources being consumed by the device.
+  ///
+  /// For the Threads device, this terminates spawned worker threads.
+  static void finalize();
+
+  /// \brief Print configuration information to the given output stream.
+  static void print_configuration( std::ostream & , const bool detail = false );
+
+  //@}
+  /*------------------------------------------------------------------------*/
+  /*------------------------------------------------------------------------*/
+  //! \name Space-specific functions
+  //@{
+
+  /** \brief Initialize the device in the "ready to work" state.
+   *
+   *  The device is initialized in a "ready to work" or "awake" state.
+   *  This state reduces latency and thus improves performance when
+   *  dispatching work.  However, the "awake" state consumes resources
+   *  even when no work is being done.  You may call sleep() to put
+   *  the device in a "sleeping" state that does not consume as many
+   *  resources, but it will take time (latency) to awaken the device
+   *  again (via the wake()) method so that it is ready for work.
+   *
+   *  Teams of threads are distributed as evenly as possible across
+   *  the requested number of numa regions and cores per numa region.
+   *  A team will not be split across a numa region.
+   *
+   *  If the 'use_' arguments are not supplied the hwloc is queried
+   *  to use all available cores.
+   */
+  static void initialize( unsigned threads_count = 0 ,
+                          unsigned use_numa_count = 0 ,
+                          unsigned use_cores_per_numa = 0 ,
+                          bool allow_asynchronous_threadpool = false );
+
+  static int is_initialized();
+
+  /** \brief  Return the maximum amount of concurrency.  */
+  static int concurrency();
+
+  static Threads & instance( int = 0 );
+
+  //----------------------------------------
+
+  static int thread_pool_size( int depth = 0 );
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+  static int thread_pool_rank();
+#else
+  KOKKOS_INLINE_FUNCTION static int thread_pool_rank() { return 0 ; }
+#endif
+
+  inline static unsigned max_hardware_threads() { return thread_pool_size(0); }
+  KOKKOS_INLINE_FUNCTION static unsigned hardware_thread_id() { return thread_pool_rank(); }
+
+  //@}
+  //----------------------------------------
+};
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+struct VerifyExecutionCanAccessMemorySpace
+  < Kokkos::Threads::memory_space
+  , Kokkos::Threads::scratch_memory_space
+  >
+{
+  enum { value = true };
+  inline static void verify( void ) { }
+  inline static void verify( const void * ) { }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+
+#include <Kokkos_ExecPolicy.hpp>
+#include <Kokkos_Parallel.hpp>
+#include <Threads/Kokkos_ThreadsExec.hpp>
+#include <Threads/Kokkos_ThreadsTeam.hpp>
+#include <Threads/Kokkos_Threads_Parallel.hpp>
+
+#include <KokkosExp_MDRangePolicy.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_PTHREAD ) */
+#endif /* #define KOKKOS_THREADS_HPP */
+
+
diff --git a/lib/kokkos/core/src/Kokkos_Vectorization.hpp b/lib/kokkos/core/src/Kokkos_Vectorization.hpp
new file mode 100644
index 0000000000..a60c0ecaa7
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_Vectorization.hpp
@@ -0,0 +1,53 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/// \file Kokkos_Vectorization.hpp
+/// \brief Declaration and definition of Kokkos::Vectorization interface.
+#ifndef KOKKOS_VECTORIZATION_HPP
+#define KOKKOS_VECTORIZATION_HPP
+
+#if defined( KOKKOS_HAVE_CUDA )
+#include <Cuda/Kokkos_Cuda_Vectorization.hpp>
+#endif
+
+#endif
diff --git a/lib/kokkos/core/src/Kokkos_View.hpp b/lib/kokkos/core/src/Kokkos_View.hpp
new file mode 100644
index 0000000000..1cc8b03381
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_View.hpp
@@ -0,0 +1,2384 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_VIEW_HPP
+#define KOKKOS_VIEW_HPP
+
+#include <type_traits>
+#include <string>
+#include <algorithm>
+#include <initializer_list>
+
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_HostSpace.hpp>
+#include <Kokkos_MemoryTraits.hpp>
+#include <Kokkos_ExecPolicy.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template< class DstMemorySpace , class SrcMemorySpace >
+struct DeepCopy ;
+
+template< class DataType >
+struct ViewArrayAnalysis ;
+
+template< class DataType , class ArrayLayout
+        , typename ValueType =
+          typename ViewArrayAnalysis< DataType >::non_const_value_type
+        >
+struct ViewDataAnalysis ;
+
+template< class , class ... >
+class ViewMapping { public: enum { is_assignable = false }; };
+
+template< class MemorySpace >
+struct ViewOperatorBoundsErrorAbort ;
+
+template<>
+struct ViewOperatorBoundsErrorAbort< Kokkos::HostSpace > {
+  static void apply( const size_t rank
+                   , const size_t n0 , const size_t n1
+                   , const size_t n2 , const size_t n3
+                   , const size_t n4 , const size_t n5
+                   , const size_t n6 , const size_t n7
+                   , const size_t i0 , const size_t i1
+                   , const size_t i2 , const size_t i3
+                   , const size_t i4 , const size_t i5
+                   , const size_t i6 , const size_t i7 );
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+/** \class ViewTraits
+ *  \brief Traits class for accessing attributes of a View.
+ *
+ * This is an implementation detail of View.  It is only of interest
+ * to developers implementing a new specialization of View.
+ *
+ * Template argument options:
+ *   - View< DataType >
+ *   - View< DataType , Space >
+ *   - View< DataType , Space , MemoryTraits >
+ *   - View< DataType , ArrayLayout >
+ *   - View< DataType , ArrayLayout , Space >
+ *   - View< DataType , ArrayLayout , MemoryTraits >
+ *   - View< DataType , ArrayLayout , Space , MemoryTraits >
+ *   - View< DataType , MemoryTraits >
+ */
+
+template< class DataType , class ... Properties >
+struct ViewTraits ;
+
+template<>
+struct ViewTraits< void >
+{
+  typedef void  execution_space ;
+  typedef void  memory_space ;
+  typedef void  HostMirrorSpace ;
+  typedef void  array_layout ;
+  typedef void  memory_traits ;
+};
+
+template< class ... Prop >
+struct ViewTraits< void , void , Prop ... >
+{
+  // Ignore an extraneous 'void'
+  typedef typename ViewTraits<void,Prop...>::execution_space  execution_space ;
+  typedef typename ViewTraits<void,Prop...>::memory_space     memory_space ;
+  typedef typename ViewTraits<void,Prop...>::HostMirrorSpace  HostMirrorSpace ;
+  typedef typename ViewTraits<void,Prop...>::array_layout     array_layout ;
+  typedef typename ViewTraits<void,Prop...>::memory_traits    memory_traits ;
+};
+
+template< class ArrayLayout , class ... Prop >
+struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_array_layout<ArrayLayout>::value >::type , ArrayLayout , Prop ... >
+{
+  // Specify layout, keep subsequent space and memory traits arguments
+
+  typedef typename ViewTraits<void,Prop...>::execution_space  execution_space ;
+  typedef typename ViewTraits<void,Prop...>::memory_space     memory_space ;
+  typedef typename ViewTraits<void,Prop...>::HostMirrorSpace  HostMirrorSpace ;
+  typedef          ArrayLayout                                array_layout ;
+  typedef typename ViewTraits<void,Prop...>::memory_traits    memory_traits ;
+};
+
+template< class Space , class ... Prop >
+struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_space<Space>::value >::type , Space , Prop ... >
+{
+  // Specify Space, memory traits should be the only subsequent argument.
+
+  static_assert( std::is_same< typename ViewTraits<void,Prop...>::execution_space , void >::value &&
+                 std::is_same< typename ViewTraits<void,Prop...>::memory_space    , void >::value &&
+                 std::is_same< typename ViewTraits<void,Prop...>::HostMirrorSpace , void >::value &&
+                 std::is_same< typename ViewTraits<void,Prop...>::array_layout    , void >::value
+               , "Only one View Execution or Memory Space template argument" );
+
+  typedef typename Space::execution_space                   execution_space ;
+  typedef typename Space::memory_space                      memory_space ;
+  typedef typename Kokkos::Impl::is_space< Space >::host_mirror_space
+      HostMirrorSpace ;
+  typedef typename execution_space::array_layout            array_layout ;
+  typedef typename ViewTraits<void,Prop...>::memory_traits  memory_traits ;
+};
+
+template< class MemoryTraits , class ... Prop >
+struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_memory_traits<MemoryTraits>::value >::type , MemoryTraits , Prop ... >
+{
+  // Specify memory trait, should not be any subsequent arguments
+
+  static_assert( std::is_same< typename ViewTraits<void,Prop...>::execution_space , void >::value &&
+                 std::is_same< typename ViewTraits<void,Prop...>::memory_space    , void >::value &&
+                 std::is_same< typename ViewTraits<void,Prop...>::array_layout    , void >::value &&
+                 std::is_same< typename ViewTraits<void,Prop...>::memory_traits   , void >::value
+               , "MemoryTrait is the final optional template argument for a View" );
+
+  typedef void          execution_space ;
+  typedef void          memory_space ;
+  typedef void          HostMirrorSpace ;
+  typedef void          array_layout ;
+  typedef MemoryTraits  memory_traits ;
+};
+
+
+template< class DataType , class ... Properties >
+struct ViewTraits {
+private:
+
+  // Unpack the properties arguments
+  typedef ViewTraits< void , Properties ... >  prop ;
+
+  typedef typename
+    std::conditional< ! std::is_same< typename prop::execution_space , void >::value
+                    , typename prop::execution_space
+                    , Kokkos::DefaultExecutionSpace
+                    >::type
+      ExecutionSpace ;
+
+  typedef typename
+    std::conditional< ! std::is_same< typename prop::memory_space , void >::value
+                    , typename prop::memory_space
+                    , typename ExecutionSpace::memory_space
+                    >::type
+      MemorySpace ;
+
+  typedef typename
+    std::conditional< ! std::is_same< typename prop::array_layout , void >::value
+                    , typename prop::array_layout
+                    , typename ExecutionSpace::array_layout
+                    >::type
+      ArrayLayout ;
+
+  typedef typename
+    std::conditional
+      < ! std::is_same< typename prop::HostMirrorSpace , void >::value
+      , typename prop::HostMirrorSpace
+      , typename Kokkos::Impl::is_space< ExecutionSpace >::host_mirror_space
+      >::type
+      HostMirrorSpace ;
+
+  typedef typename
+    std::conditional< ! std::is_same< typename prop::memory_traits , void >::value
+                    , typename prop::memory_traits
+                    , typename Kokkos::MemoryManaged
+                    >::type
+      MemoryTraits ;
+
+  // Analyze data type's properties,
+  // May be specialized based upon the layout and value type
+  typedef Kokkos::Experimental::Impl::ViewDataAnalysis< DataType , ArrayLayout > data_analysis ;
+
+public:
+
+  //------------------------------------
+  // Data type traits:
+
+  typedef typename data_analysis::type            data_type ;
+  typedef typename data_analysis::const_type      const_data_type ;
+  typedef typename data_analysis::non_const_type  non_const_data_type ;
+
+  //------------------------------------
+  // Compatible array of trivial type traits:
+
+  typedef typename data_analysis::scalar_array_type            scalar_array_type ;
+  typedef typename data_analysis::const_scalar_array_type      const_scalar_array_type ;
+  typedef typename data_analysis::non_const_scalar_array_type  non_const_scalar_array_type ;
+
+  //------------------------------------
+  // Value type traits:
+
+  typedef typename data_analysis::value_type            value_type ;
+  typedef typename data_analysis::const_value_type      const_value_type ;
+  typedef typename data_analysis::non_const_value_type  non_const_value_type ;
+
+  //------------------------------------
+  // Mapping traits:
+
+  typedef ArrayLayout                         array_layout ;
+  typedef typename data_analysis::dimension   dimension ;
+  typedef typename data_analysis::specialize  specialize /* mapping specialization tag */ ;
+
+  enum { rank         = dimension::rank };
+  enum { rank_dynamic = dimension::rank_dynamic };
+
+  //------------------------------------
+  // Execution space, memory space, memory access traits, and host mirror space.
+
+  typedef ExecutionSpace                              execution_space ;
+  typedef MemorySpace                                 memory_space ;
+  typedef Kokkos::Device<ExecutionSpace,MemorySpace>  device_type ;
+  typedef MemoryTraits                                memory_traits ;
+  typedef HostMirrorSpace                             host_mirror_space ;
+
+  typedef typename MemorySpace::size_type  size_type ;
+
+  enum { is_hostspace      = std::is_same< MemorySpace , HostSpace >::value };
+  enum { is_managed        = MemoryTraits::Unmanaged    == 0 };
+  enum { is_random_access  = MemoryTraits::RandomAccess == 1 };
+
+  //------------------------------------
+};
+
+/** \class View
+ *  \brief View to an array of data.
+ *
+ * A View represents an array of one or more dimensions.
+ * For details, please refer to Kokkos' tutorial materials.
+ *
+ * \section Kokkos_View_TemplateParameters Template parameters
+ *
+ * This class has both required and optional template parameters.  The
+ * \c DataType parameter must always be provided, and must always be
+ * first. The parameters \c Arg1Type, \c Arg2Type, and \c Arg3Type are
+ * placeholders for different template parameters.  The default value
+ * of the fifth template parameter \c Specialize suffices for most use
+ * cases.  When explaining the template parameters, we won't refer to
+ * \c Arg1Type, \c Arg2Type, and \c Arg3Type; instead, we will refer
+ * to the valid categories of template parameters, in whatever order
+ * they may occur.
+ *
+ * Valid ways in which template arguments may be specified:
+ *   - View< DataType >
+ *   - View< DataType , Layout >
+ *   - View< DataType , Layout , Space >
+ *   - View< DataType , Layout , Space , MemoryTraits >
+ *   - View< DataType , Space >
+ *   - View< DataType , Space , MemoryTraits >
+ *   - View< DataType , MemoryTraits >
+ *
+ * \tparam DataType (required) This indicates both the type of each
+ *   entry of the array, and the combination of compile-time and
+ *   run-time array dimension(s).  For example, <tt>double*</tt>
+ *   indicates a one-dimensional array of \c double with run-time
+ *   dimension, and <tt>int*[3]</tt> a two-dimensional array of \c int
+ *   with run-time first dimension and compile-time second dimension
+ *   (of 3).  In general, the run-time dimensions (if any) must go
+ *   first, followed by zero or more compile-time dimensions.  For
+ *   more examples, please refer to the tutorial materials.
+ *
+ * \tparam Space (required) The memory space.
+ *
+ * \tparam Layout (optional) The array's layout in memory.  For
+ *   example, LayoutLeft indicates a column-major (Fortran style)
+ *   layout, and LayoutRight a row-major (C style) layout.  If not
+ *   specified, this defaults to the preferred layout for the
+ *   <tt>Space</tt>.
+ *
+ * \tparam MemoryTraits (optional) Assertion of the user's intended
+ *   access behavior.  For example, RandomAccess indicates read-only
+ *   access with limited spatial locality, and Unmanaged lets users
+ *   wrap externally allocated memory in a View without automatic
+ *   deallocation.
+ *
+ * \section Kokkos_View_MT MemoryTraits discussion
+ *
+ * \subsection Kokkos_View_MT_Interp MemoryTraits interpretation depends on Space
+ *
+ * Some \c MemoryTraits options may have different interpretations for
+ * different \c Space types.  For example, with the Cuda device,
+ * \c RandomAccess tells Kokkos to fetch the data through the texture
+ * cache, whereas the non-GPU devices have no such hardware construct.
+ *
+ * \subsection Kokkos_View_MT_PrefUse Preferred use of MemoryTraits
+ *
+ * Users should defer applying the optional \c MemoryTraits parameter
+ * until the point at which they actually plan to rely on it in a
+ * computational kernel.  This minimizes the number of template
+ * parameters exposed in their code, which reduces the cost of
+ * compilation.  Users may always assign a View without specified
+ * \c MemoryTraits to a compatible View with that specification.
+ * For example:
+ * \code
+ * // Pass in the simplest types of View possible.
+ * void
+ * doSomething (View<double*, Cuda> out,
+ *              View<const double*, Cuda> in)
+ * {
+ *   // Assign the "generic" View in to a RandomAccess View in_rr.
+ *   // Note that RandomAccess View objects must have const data.
+ *   View<const double*, Cuda, RandomAccess> in_rr = in;
+ *   // ... do something with in_rr and out ...
+ * }
+ * \endcode
+ */
+template< class DataType , class ... Properties >
+class View ;
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#include <impl/KokkosExp_ViewMapping.hpp>
+#include <impl/KokkosExp_ViewArray.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+namespace {
+
+constexpr Kokkos::Experimental::Impl::ALL_t
+  ALL = Kokkos::Experimental::Impl::ALL_t();
+
+constexpr Kokkos::Experimental::Impl::WithoutInitializing_t
+  WithoutInitializing = Kokkos::Experimental::Impl::WithoutInitializing_t();
+
+constexpr Kokkos::Experimental::Impl::AllowPadding_t
+  AllowPadding        = Kokkos::Experimental::Impl::AllowPadding_t();
+
+}
+
+/** \brief  Create View allocation parameter bundle from argument list.
+ *
+ *  Valid argument list members are:
+ *    1) label as a "string" or std::string
+ *    2) memory space instance of the View::memory_space type
+ *    3) execution space instance compatible with the View::memory_space
+ *    4) Kokkos::WithoutInitializing to bypass initialization
+ *    4) Kokkos::AllowPadding to allow allocation to pad dimensions for memory alignment
+ */
+template< class ... Args >
+inline
+Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... >
+view_alloc( Args const & ... args )
+{
+  typedef
+    Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... >
+      return_type ;
+
+  static_assert( ! return_type::has_pointer
+               , "Cannot give pointer-to-memory for view allocation" );
+
+  return return_type( args... );
+}
+
+template< class ... Args >
+inline
+Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... >
+view_wrap( Args const & ... args )
+{
+  typedef
+    Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... >
+      return_type ;
+
+  static_assert( ! return_type::has_memory_space &&
+                 ! return_type::has_execution_space &&
+                 ! return_type::has_label &&
+                 return_type::has_pointer
+               , "Must only give pointer-to-memory for view wrapping" );
+
+  return return_type( args... );
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+template< class DataType , class ... Properties >
+class View ;
+
+template< class > struct is_view : public std::false_type {};
+
+template< class D, class ... P >
+struct is_view< View<D,P...> > : public std::true_type {};
+
+template< class D, class ... P >
+struct is_view< const View<D,P...> > : public std::true_type {};
+
+template< class DataType , class ... Properties >
+class View : public ViewTraits< DataType , Properties ... > {
+private:
+
+  template< class , class ... > friend class View ;
+  template< class , class ... > friend class Impl::ViewMapping ;
+
+public:
+
+  typedef ViewTraits< DataType , Properties ... > traits ;
+
+private:
+
+  typedef Kokkos::Experimental::Impl::ViewMapping< traits , void > map_type ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker      track_type ;
+
+  track_type  m_track ;
+  map_type    m_map ;
+
+public:
+
+  //----------------------------------------
+  /** \brief  Compatible view of array of scalar types */
+  typedef View< typename traits::scalar_array_type ,
+                typename traits::array_layout ,
+                typename traits::device_type ,
+                typename traits::memory_traits >
+    array_type ;
+
+  /** \brief  Compatible view of const data type */
+  typedef View< typename traits::const_data_type ,
+                typename traits::array_layout ,
+                typename traits::device_type ,
+                typename traits::memory_traits >
+    const_type ;
+
+  /** \brief  Compatible view of non-const data type */
+  typedef View< typename traits::non_const_data_type ,
+                typename traits::array_layout ,
+                typename traits::device_type ,
+                typename traits::memory_traits >
+    non_const_type ;
+
+  /** \brief  Compatible HostMirror view */
+  typedef View< typename traits::non_const_data_type ,
+                typename traits::array_layout ,
+                typename traits::host_mirror_space >
+    HostMirror ;
+
+  //----------------------------------------
+  // Domain rank and extents
+
+  enum { Rank = map_type::Rank };
+
+ /** \brief rank() to be implemented
+  */
+  //KOKKOS_INLINE_FUNCTION
+  //static
+  //constexpr unsigned rank() { return map_type::Rank; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename std::enable_if< std::is_integral<iType>::value , size_t >::type
+  extent( const iType & r ) const
+    { return m_map.extent(r); }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename std::enable_if< std::is_integral<iType>::value , int >::type
+  extent_int( const iType & r ) const
+    { return static_cast<int>(m_map.extent(r)); }
+
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename traits::array_layout layout() const
+    { return m_map.layout(); }
+
+  //----------------------------------------
+  /*  Deprecate all 'dimension' functions in favor of
+   *  ISO/C++ vocabulary 'extent'.
+   */
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename std::enable_if< std::is_integral<iType>::value , size_t >::type
+  dimension( const iType & r ) const { return extent( r ); }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_0() const { return m_map.dimension_0(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return m_map.dimension_1(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return m_map.dimension_2(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return m_map.dimension_3(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return m_map.dimension_4(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return m_map.dimension_5(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return m_map.dimension_6(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return m_map.dimension_7(); }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t size() const { return m_map.dimension_0() *
+                                                                m_map.dimension_1() *
+                                                                m_map.dimension_2() *
+                                                                m_map.dimension_3() *
+                                                                m_map.dimension_4() *
+                                                                m_map.dimension_5() *
+                                                                m_map.dimension_6() *
+                                                                m_map.dimension_7(); }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return m_map.stride_0(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return m_map.stride_1(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return m_map.stride_2(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return m_map.stride_3(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return m_map.stride_4(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return m_map.stride_5(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return m_map.stride_6(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return m_map.stride_7(); }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION void stride( iType * const s ) const { m_map.stride(s); }
+
+  //----------------------------------------
+  // Range span is the span which contains all members.
+
+  typedef typename map_type::reference_type  reference_type ;
+  typedef typename map_type::pointer_type    pointer_type ;
+
+  enum { reference_type_is_lvalue_reference = std::is_lvalue_reference< reference_type >::value };
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return m_map.span(); }
+  // Deprecated, use 'span()' instead
+  KOKKOS_INLINE_FUNCTION constexpr size_t capacity() const { return m_map.span(); }
+  KOKKOS_INLINE_FUNCTION constexpr bool   span_is_contiguous() const { return m_map.span_is_contiguous(); }
+  KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const { return m_map.data(); }
+
+  // Deprecated, use 'span_is_contigous()' instead
+  KOKKOS_INLINE_FUNCTION constexpr bool   is_contiguous() const { return m_map.span_is_contiguous(); }
+  // Deprecated, use 'data()' instead
+  KOKKOS_INLINE_FUNCTION constexpr pointer_type ptr_on_device() const { return m_map.data(); }
+
+  //----------------------------------------
+  // Allow specializations to query their specialized map
+
+  KOKKOS_INLINE_FUNCTION
+  const Kokkos::Experimental::Impl::ViewMapping< traits , void > &
+  implementation_map() const { return m_map ; }
+
+  //----------------------------------------
+
+private:
+
+  enum {
+    is_layout_left = std::is_same< typename traits::array_layout
+                                  , Kokkos::LayoutLeft >::value ,
+
+    is_layout_right = std::is_same< typename traits::array_layout
+                                  , Kokkos::LayoutRight >::value ,
+
+    is_layout_stride = std::is_same< typename traits::array_layout
+                                   , Kokkos::LayoutStride >::value ,
+
+    is_default_map =
+      std::is_same< typename traits::specialize , void >::value &&
+      ( is_layout_left || is_layout_right || is_layout_stride )
+  };
+
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+
+#define KOKKOS_VIEW_OPERATOR_VERIFY( ARG ) \
+  Kokkos::Impl::VerifyExecutionCanAccessMemorySpace \
+    < Kokkos::Impl::ActiveExecutionMemorySpace , typename traits::memory_space >::verify(); \
+  Kokkos::Experimental::Impl::view_verify_operator_bounds ARG ;
+
+#else
+
+#define KOKKOS_VIEW_OPERATOR_VERIFY( ARG ) \
+  Kokkos::Impl::VerifyExecutionCanAccessMemorySpace \
+    < Kokkos::Impl::ActiveExecutionMemorySpace , typename traits::memory_space >::verify();
+
+#endif
+
+public:
+
+  //------------------------------
+  // Rank 0 operator()
+
+  template< class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<( Kokkos::Impl::are_integral<Args...>::value
+                            && ( 0 == Rank )
+                          ), reference_type >::type
+  operator()( Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,args...) )
+
+      return m_map.reference();
+    }
+
+  //------------------------------
+  // Rank 1 operator()
+
+  template< typename I0
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,Args...>::value
+      && ( 1 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,args...) )
+
+      return m_map.reference(i0);
+    }
+
+  template< typename I0
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,Args...>::value
+      && ( 1 == Rank )
+      && is_default_map
+      && ! is_layout_stride
+    ), reference_type >::type
+  operator()( const I0 & i0
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,args...) )
+
+      return m_map.m_handle[ i0 ];
+    }
+
+  template< typename I0
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,Args...>::value
+      && ( 1 == Rank )
+      && is_default_map
+      && is_layout_stride
+    ), reference_type >::type
+  operator()( const I0 & i0
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,args...) )
+
+      return m_map.m_handle[ m_map.m_offset.m_stride.S0 * i0 ];
+    }
+
+  //------------------------------
+  // Rank 1 operator[]
+
+  template< typename I0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0>::value
+      && ( 1 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator[]( const I0 & i0 ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0) )
+
+      return m_map.reference(i0);
+    }
+
+  template< typename I0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0>::value
+      && ( 1 == Rank )
+      && is_default_map
+      && ! is_layout_stride
+    ), reference_type >::type
+  operator[]( const I0 & i0 ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0) )
+
+      return m_map.m_handle[ i0 ];
+    }
+
+  template< typename I0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0>::value
+      && ( 1 == Rank )
+      && is_default_map
+      && is_layout_stride
+    ), reference_type >::type
+  operator[]( const I0 & i0 ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0) )
+
+      return m_map.m_handle[ m_map.m_offset.m_stride.S0 * i0 ];
+    }
+
+  //------------------------------
+  // Rank 2
+
+  template< typename I0 , typename I1
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
+      && ( 2 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,args...) )
+
+      return m_map.reference(i0,i1);
+    }
+
+  template< typename I0 , typename I1
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
+      && ( 2 == Rank )
+      && is_default_map
+      && is_layout_left && ( traits::rank_dynamic == 0 )
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,args...) )
+
+      return m_map.m_handle[ i0 + m_map.m_offset.m_dim.N0 * i1 ];
+    }
+
+  template< typename I0 , typename I1
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
+      && ( 2 == Rank )
+      && is_default_map
+      && is_layout_left && ( traits::rank_dynamic != 0 )
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,args...) )
+
+      return m_map.m_handle[ i0 + m_map.m_offset.m_stride * i1 ];
+    }
+
+  template< typename I0 , typename I1
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
+      && ( 2 == Rank )
+      && is_default_map
+      && is_layout_right && ( traits::rank_dynamic == 0 )
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,args...) )
+
+      return m_map.m_handle[ i1 + m_map.m_offset.m_dim.N1 * i0 ];
+    }
+
+  template< typename I0 , typename I1
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
+      && ( 2 == Rank )
+      && is_default_map
+      && is_layout_right && ( traits::rank_dynamic != 0 )
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,args...) )
+
+      return m_map.m_handle[ i1 + m_map.m_offset.m_stride * i0 ];
+    }
+
+  template< typename I0 , typename I1
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,Args...>::value
+      && ( 2 == Rank )
+      && is_default_map
+      && is_layout_stride
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,args...) )
+
+      return m_map.m_handle[ i0 * m_map.m_offset.m_stride.S0 +
+                             i1 * m_map.m_offset.m_stride.S1 ];
+    }
+
+  //------------------------------
+  // Rank 3
+
+  template< typename I0 , typename I1 , typename I2
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,Args...>::value
+      && ( 3 == Rank )
+      && is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,args...) )
+
+      return m_map.m_handle[ m_map.m_offset(i0,i1,i2) ];
+    }
+
+  template< typename I0 , typename I1 , typename I2
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,Args...>::value
+      && ( 3 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,args...) )
+
+      return m_map.reference(i0,i1,i2);
+    }
+
+  //------------------------------
+  // Rank 4
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,Args...>::value
+      && ( 4 == Rank )
+      && is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,args...) )
+
+      return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3) ];
+    }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,Args...>::value
+      && ( 4 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,args...) )
+
+      return m_map.reference(i0,i1,i2,i3);
+    }
+
+  //------------------------------
+  // Rank 5
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,Args...>::value
+      && ( 5 == Rank )
+      && is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , const I4 & i4
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,i4,args...) )
+
+      return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3,i4) ];
+    }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,Args...>::value
+      && ( 5 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , const I4 & i4
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,i4,args...) )
+
+      return m_map.reference(i0,i1,i2,i3,i4);
+    }
+
+  //------------------------------
+  // Rank 6
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,Args...>::value
+      && ( 6 == Rank )
+      && is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , const I4 & i4 , const I5 & i5
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,i4,i5,args...) )
+
+      return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3,i4,i5) ];
+    }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,Args...>::value
+      && ( 6 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , const I4 & i4 , const I5 & i5
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,i4,i5,args...) )
+
+      return m_map.reference(i0,i1,i2,i3,i4,i5);
+    }
+
+  //------------------------------
+  // Rank 7
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 , typename I6
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,Args...>::value
+      && ( 7 == Rank )
+      && is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , const I4 & i4 , const I5 & i5 , const I6 & i6
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,i4,i5,i6,args...) )
+
+      return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3,i4,i5,i6) ];
+    }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 , typename I6
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,Args...>::value
+      && ( 7 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , const I4 & i4 , const I5 & i5 , const I6 & i6
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,i4,i5,i6,args...) )
+
+      return m_map.reference(i0,i1,i2,i3,i4,i5,i6);
+    }
+
+  //------------------------------
+  // Rank 8
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 , typename I6 , typename I7
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,I7,Args...>::value
+      && ( 8 == Rank )
+      && is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,i4,i5,i6,i7,args...) )
+
+      return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3,i4,i5,i6,i7) ];
+    }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 , typename I6 , typename I7
+          , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if<
+    ( Kokkos::Impl::are_integral<I0,I1,I2,I3,I4,I5,I6,I7,Args...>::value
+      && ( 8 == Rank )
+      && ! is_default_map
+    ), reference_type >::type
+  operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+            , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7
+            , Args ... args ) const
+    {
+      KOKKOS_VIEW_OPERATOR_VERIFY( (m_map,i0,i1,i2,i3,i4,i5,i6,i7,args...) )
+
+      return m_map.reference(i0,i1,i2,i3,i4,i5,i6,i7);
+    }
+
+#undef KOKKOS_VIEW_OPERATOR_VERIFY
+
+  //----------------------------------------
+  // Standard destructor, constructors, and assignment operators
+
+  KOKKOS_INLINE_FUNCTION
+  ~View() {}
+
+  KOKKOS_INLINE_FUNCTION
+  View() : m_track(), m_map() {}
+
+  KOKKOS_INLINE_FUNCTION
+  View( const View & rhs ) : m_track( rhs.m_track ), m_map( rhs.m_map ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  View( View && rhs ) : m_track( rhs.m_track ), m_map( rhs.m_map ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  View & operator = ( const View & rhs ) { m_track = rhs.m_track ; m_map = rhs.m_map ; return *this ; }
+
+  KOKKOS_INLINE_FUNCTION
+  View & operator = ( View && rhs ) { m_track = rhs.m_track ; m_map = rhs.m_map ; return *this ; }
+
+  //----------------------------------------
+  // Compatible view copy constructor and assignment
+  // may assign unmanaged from managed.
+
+  template< class RT , class ... RP >
+  KOKKOS_INLINE_FUNCTION
+  View( const View<RT,RP...> & rhs )
+    : m_track( rhs.m_track , traits::is_managed )
+    , m_map()
+    {
+      typedef typename View<RT,RP...>::traits  SrcTraits ;
+      typedef Kokkos::Experimental::Impl::ViewMapping< traits , SrcTraits , void >  Mapping ;
+      static_assert( Mapping::is_assignable , "Incompatible View copy construction" );
+      Mapping::assign( m_map , rhs.m_map , rhs.m_track );
+    }
+
+  template< class RT , class ... RP >
+  KOKKOS_INLINE_FUNCTION
+  View & operator = ( const View<RT,RP...> & rhs )
+    {
+      typedef typename View<RT,RP...>::traits  SrcTraits ;
+      typedef Kokkos::Experimental::Impl::ViewMapping< traits , SrcTraits , void >  Mapping ;
+      static_assert( Mapping::is_assignable , "Incompatible View copy assignment" );
+      Mapping::assign( m_map , rhs.m_map , rhs.m_track );
+      m_track.assign( rhs.m_track , traits::is_managed );
+      return *this ;
+    }
+
+  //----------------------------------------
+  // Compatible subview constructor
+  // may assign unmanaged from managed.
+
+  template< class RT , class ... RP , class Arg0 , class ... Args >
+  KOKKOS_INLINE_FUNCTION
+  View( const View< RT , RP... > & src_view
+      , const Arg0 & arg0 , Args ... args )
+    : m_track( src_view.m_track , traits::is_managed )
+    , m_map()
+    {
+      typedef View< RT , RP... > SrcType ;
+
+      typedef Kokkos::Experimental::Impl::ViewMapping
+        < void /* deduce destination view type from source view traits */
+        , typename SrcType::traits
+        , Arg0 , Args... > Mapping ;
+
+      typedef typename Mapping::type DstType ;
+
+      static_assert( Kokkos::Experimental::Impl::ViewMapping< traits , typename DstType::traits , void >::is_assignable
+        , "Subview construction requires compatible view and subview arguments" );
+
+      Mapping::assign( m_map, src_view.m_map, arg0 , args... );
+    }
+
+  //----------------------------------------
+  // Allocation tracking properties
+
+  KOKKOS_INLINE_FUNCTION
+  int use_count() const
+    { return m_track.use_count(); }
+
+  inline
+  const std::string label() const
+    { return m_track.template get_label< typename traits::memory_space >(); }
+
+  //----------------------------------------
+  // Allocation according to allocation properties and array layout
+
+  template< class ... P >
+  explicit inline
+  View( const Impl::ViewCtorProp< P ... > & arg_prop
+      , typename std::enable_if< ! Impl::ViewCtorProp< P... >::has_pointer
+                               , typename traits::array_layout
+                               >::type const & arg_layout
+      )
+    : m_track()
+    , m_map()
+    {
+      // Append layout and spaces if not input
+      typedef Impl::ViewCtorProp< P ... > alloc_prop_input ;
+
+      // use 'std::integral_constant<unsigned,I>' for non-types
+      // to avoid duplicate class error.
+      typedef Impl::ViewCtorProp
+        < P ...
+        , typename std::conditional
+            < alloc_prop_input::has_label
+            , std::integral_constant<unsigned,0>
+            , typename std::string
+            >::type
+        , typename std::conditional
+            < alloc_prop_input::has_memory_space
+            , std::integral_constant<unsigned,1>
+            , typename traits::device_type::memory_space
+            >::type
+        , typename std::conditional
+            < alloc_prop_input::has_execution_space
+            , std::integral_constant<unsigned,2>
+            , typename traits::device_type::execution_space
+            >::type
+        > alloc_prop ;
+
+      static_assert( traits::is_managed
+                   , "View allocation constructor requires managed memory" );
+
+      if ( alloc_prop::initialize &&
+           ! alloc_prop::execution_space::is_initialized() ) {
+        // If initializing view data then
+        // the execution space must be initialized.
+        Kokkos::Impl::throw_runtime_exception("Constructing View and initializing data with uninitialized execution space");
+      }
+
+      // Copy the input allocation properties with possibly defaulted properties
+      alloc_prop prop( arg_prop );
+
+//------------------------------------------------------------
+#if defined( KOKKOS_HAVE_CUDA )
+      // If allocating in CudaUVMSpace must fence before and after
+      // the allocation to protect against possible concurrent access
+      // on the CPU and the GPU.
+      // Fence using the trait's executon space (which will be Kokkos::Cuda)
+      // to avoid incomplete type errors from usng Kokkos::Cuda directly.
+      if ( std::is_same< Kokkos::CudaUVMSpace , typename traits::device_type::memory_space >::value ) {
+        traits::device_type::memory_space::execution_space::fence();
+      }
+#endif
+//------------------------------------------------------------
+
+      Kokkos::Experimental::Impl::SharedAllocationRecord<> *
+        record = m_map.allocate_shared( prop , arg_layout );
+
+//------------------------------------------------------------
+#if defined( KOKKOS_HAVE_CUDA )
+      if ( std::is_same< Kokkos::CudaUVMSpace , typename traits::device_type::memory_space >::value ) {
+        traits::device_type::memory_space::execution_space::fence();
+      }
+#endif
+//------------------------------------------------------------
+
+      // Setup and initialization complete, start tracking
+      m_track.assign_allocated_record_to_uninitialized( record );
+    }
+
+  // Wrap memory according to properties and array layout
+  template< class ... P >
+  explicit KOKKOS_INLINE_FUNCTION
+  View( const Impl::ViewCtorProp< P ... > & arg_prop
+      , typename std::enable_if< Impl::ViewCtorProp< P... >::has_pointer
+                               , typename traits::array_layout
+                               >::type const & arg_layout
+      )
+    : m_track() // No memory tracking
+    , m_map( arg_prop , arg_layout )
+    {
+      static_assert(
+        std::is_same< pointer_type
+                    , typename Impl::ViewCtorProp< P... >::pointer_type
+                    >::value ,
+        "Constructing View to wrap user memory must supply matching pointer type" );
+    }
+
+  // Simple dimension-only layout
+  template< class ... P >
+  explicit inline
+  View( const Impl::ViewCtorProp< P ... > & arg_prop
+      , typename std::enable_if< ! Impl::ViewCtorProp< P... >::has_pointer
+                               , size_t
+                               >::type const arg_N0 = 0
+      , const size_t arg_N1 = 0
+      , const size_t arg_N2 = 0
+      , const size_t arg_N3 = 0
+      , const size_t arg_N4 = 0
+      , const size_t arg_N5 = 0
+      , const size_t arg_N6 = 0
+      , const size_t arg_N7 = 0
+      )
+    : View( arg_prop
+          , typename traits::array_layout
+              ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+              , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+          )
+    {}
+
+  template< class ... P >
+  explicit KOKKOS_INLINE_FUNCTION
+  View( const Impl::ViewCtorProp< P ... > & arg_prop
+      , typename std::enable_if< Impl::ViewCtorProp< P... >::has_pointer
+                               , size_t
+                               >::type const arg_N0 = 0
+      , const size_t arg_N1 = 0
+      , const size_t arg_N2 = 0
+      , const size_t arg_N3 = 0
+      , const size_t arg_N4 = 0
+      , const size_t arg_N5 = 0
+      , const size_t arg_N6 = 0
+      , const size_t arg_N7 = 0
+      )
+    : View( arg_prop
+          , typename traits::array_layout
+              ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+              , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+          )
+    {}
+
+  // Allocate with label and layout
+  template< typename Label >
+  explicit inline
+  View( const Label & arg_label
+      , typename std::enable_if<
+          Kokkos::Experimental::Impl::is_view_label<Label>::value ,
+          typename traits::array_layout >::type const & arg_layout
+      )
+    : View( Impl::ViewCtorProp< std::string >( arg_label ) , arg_layout )
+    {}
+
+  // Allocate label and layout, must disambiguate from subview constructor.
+  template< typename Label >
+  explicit inline
+  View( const Label & arg_label
+      , typename std::enable_if<
+          Kokkos::Experimental::Impl::is_view_label<Label>::value ,
+        const size_t >::type arg_N0 = 0
+      , const size_t arg_N1 = 0
+      , const size_t arg_N2 = 0
+      , const size_t arg_N3 = 0
+      , const size_t arg_N4 = 0
+      , const size_t arg_N5 = 0
+      , const size_t arg_N6 = 0
+      , const size_t arg_N7 = 0
+      )
+    : View( Impl::ViewCtorProp< std::string >( arg_label )
+          , typename traits::array_layout
+              ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+              , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+          )
+    {}
+
+  // For backward compatibility
+  explicit inline
+  View( const ViewAllocateWithoutInitializing & arg_prop
+      , const typename traits::array_layout & arg_layout
+      )
+    : View( Impl::ViewCtorProp< std::string , Kokkos::Experimental::Impl::WithoutInitializing_t >( arg_prop.label , Kokkos::Experimental::WithoutInitializing )
+          , arg_layout
+          )
+    {}
+
+  explicit inline
+  View( const ViewAllocateWithoutInitializing & arg_prop
+      , const size_t arg_N0 = 0
+      , const size_t arg_N1 = 0
+      , const size_t arg_N2 = 0
+      , const size_t arg_N3 = 0
+      , const size_t arg_N4 = 0
+      , const size_t arg_N5 = 0
+      , const size_t arg_N6 = 0
+      , const size_t arg_N7 = 0
+      )
+    : View( Impl::ViewCtorProp< std::string , Kokkos::Experimental::Impl::WithoutInitializing_t >( arg_prop.label , Kokkos::Experimental::WithoutInitializing )
+          , typename traits::array_layout
+              ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+              , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+          )
+    {}
+
+  //----------------------------------------
+  // Memory span required to wrap these dimensions.
+  static constexpr size_t required_allocation_size(
+                                       const size_t arg_N0 = 0
+                                     , const size_t arg_N1 = 0
+                                     , const size_t arg_N2 = 0
+                                     , const size_t arg_N3 = 0
+                                     , const size_t arg_N4 = 0
+                                     , const size_t arg_N5 = 0
+                                     , const size_t arg_N6 = 0
+                                     , const size_t arg_N7 = 0
+                                     )
+    {
+      return map_type::memory_span(
+        typename traits::array_layout
+          ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+          , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) );
+    }
+
+  explicit KOKKOS_INLINE_FUNCTION
+  View( pointer_type arg_ptr
+      , const size_t arg_N0 = 0
+      , const size_t arg_N1 = 0
+      , const size_t arg_N2 = 0
+      , const size_t arg_N3 = 0
+      , const size_t arg_N4 = 0
+      , const size_t arg_N5 = 0
+      , const size_t arg_N6 = 0
+      , const size_t arg_N7 = 0
+      )
+    : View( Impl::ViewCtorProp<pointer_type>(arg_ptr)
+          , typename traits::array_layout
+             ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+             , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+          )
+    {}
+
+  explicit KOKKOS_INLINE_FUNCTION
+  View( pointer_type arg_ptr
+      , const typename traits::array_layout & arg_layout
+      )
+    : View( Impl::ViewCtorProp<pointer_type>(arg_ptr) , arg_layout )
+    {}
+
+  //----------------------------------------
+  // Shared scratch memory constructor
+
+  static inline
+  size_t shmem_size( const size_t arg_N0 = ~size_t(0) ,
+                     const size_t arg_N1 = ~size_t(0) ,
+                     const size_t arg_N2 = ~size_t(0) ,
+                     const size_t arg_N3 = ~size_t(0) ,
+                     const size_t arg_N4 = ~size_t(0) ,
+                     const size_t arg_N5 = ~size_t(0) ,
+                     const size_t arg_N6 = ~size_t(0) ,
+                     const size_t arg_N7 = ~size_t(0) )
+  {
+    const size_t num_passed_args =
+      ( arg_N0 != ~size_t(0) ) + ( arg_N1 != ~size_t(0) ) + ( arg_N2 != ~size_t(0) ) +
+      ( arg_N3 != ~size_t(0) ) + ( arg_N4 != ~size_t(0) ) + ( arg_N5 != ~size_t(0) ) +
+      ( arg_N6 != ~size_t(0) ) + ( arg_N7 != ~size_t(0) );
+
+    if ( std::is_same<typename traits::specialize,void>::value && num_passed_args != traits::rank_dynamic ) {
+      Kokkos::abort( "Kokkos::View::shmem_size() rank_dynamic != number of arguments.\n" );
+    }
+
+    return map_type::memory_span(
+           typename traits::array_layout
+            ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+            , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) );
+  }
+
+  explicit KOKKOS_INLINE_FUNCTION
+  View( const typename traits::execution_space::scratch_memory_space & arg_space
+      , const typename traits::array_layout & arg_layout )
+    : View( Impl::ViewCtorProp<pointer_type>(
+              reinterpret_cast<pointer_type>(
+                arg_space.get_shmem( map_type::memory_span( arg_layout ) ) ) )
+         , arg_layout )
+    {}
+
+  explicit KOKKOS_INLINE_FUNCTION
+  View( const typename traits::execution_space::scratch_memory_space & arg_space
+      , const size_t arg_N0 = 0
+      , const size_t arg_N1 = 0
+      , const size_t arg_N2 = 0
+      , const size_t arg_N3 = 0
+      , const size_t arg_N4 = 0
+      , const size_t arg_N5 = 0
+      , const size_t arg_N6 = 0
+      , const size_t arg_N7 = 0 )
+    : View( Impl::ViewCtorProp<pointer_type>(
+              reinterpret_cast<pointer_type>(
+                arg_space.get_shmem(
+                  map_type::memory_span(
+                    typename traits::array_layout
+                     ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+                     , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) ) ) ) )
+          , typename traits::array_layout
+             ( arg_N0 , arg_N1 , arg_N2 , arg_N3
+             , arg_N4 , arg_N5 , arg_N6 , arg_N7 )
+       )
+    {}
+};
+
+
+ /** \brief Temporary free function rank()
+  *         until rank() is implemented
+  *         in the View
+  */
+  template < typename D , class ... P >
+  KOKKOS_INLINE_FUNCTION
+  constexpr unsigned rank( const View<D , P...> & V ) { return V.Rank; } //Temporary until added to view
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+template< class V , class ... Args >
+using Subview =
+  typename Kokkos::Experimental::Impl::ViewMapping
+    < void /* deduce subview type from source view traits */
+    , typename V::traits
+    , Args ...
+    >::type ;
+
+template< class D, class ... P , class ... Args >
+KOKKOS_INLINE_FUNCTION
+typename Kokkos::Experimental::Impl::ViewMapping
+  < void /* deduce subview type from source view traits */
+  , ViewTraits< D , P... >
+  , Args ...
+  >::type
+subview( const View< D, P... > & src , Args ... args )
+{
+  static_assert( View< D , P... >::Rank == sizeof...(Args) ,
+    "subview requires one argument for each source View rank" );
+
+  return typename
+    Kokkos::Experimental::Impl::ViewMapping
+      < void /* deduce subview type from source view traits */
+      , ViewTraits< D , P ... >
+      , Args ... >::type( src , args ... );
+}
+
+template< class MemoryTraits , class D, class ... P , class ... Args >
+KOKKOS_INLINE_FUNCTION
+typename Kokkos::Experimental::Impl::ViewMapping
+  < void /* deduce subview type from source view traits */
+  , ViewTraits< D , P... >
+  , Args ...
+  >::template apply< MemoryTraits >::type
+subview( const View< D, P... > & src , Args ... args )
+{
+  static_assert( View< D , P... >::Rank == sizeof...(Args) ,
+    "subview requires one argument for each source View rank" );
+
+  return typename
+    Kokkos::Experimental::Impl::ViewMapping
+      < void /* deduce subview type from source view traits */
+      , ViewTraits< D , P ... >
+      , Args ... >
+      ::template apply< MemoryTraits >
+      ::type( src , args ... );
+}
+
+
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+template< class LT , class ... LP , class RT , class ... RP >
+KOKKOS_INLINE_FUNCTION
+bool operator == ( const View<LT,LP...> & lhs ,
+                   const View<RT,RP...> & rhs )
+{
+  // Same data, layout, dimensions
+  typedef ViewTraits<LT,LP...>  lhs_traits ;
+  typedef ViewTraits<RT,RP...>  rhs_traits ;
+
+  return
+    std::is_same< typename lhs_traits::const_value_type ,
+                  typename rhs_traits::const_value_type >::value &&
+    std::is_same< typename lhs_traits::array_layout ,
+                  typename rhs_traits::array_layout >::value &&
+    std::is_same< typename lhs_traits::memory_space ,
+                  typename rhs_traits::memory_space >::value &&
+    unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
+    lhs.data()        == rhs.data() &&
+    lhs.span()        == rhs.span() &&
+    lhs.dimension_0() == rhs.dimension_0() &&
+    lhs.dimension_1() == rhs.dimension_1() &&
+    lhs.dimension_2() == rhs.dimension_2() &&
+    lhs.dimension_3() == rhs.dimension_3() &&
+    lhs.dimension_4() == rhs.dimension_4() &&
+    lhs.dimension_5() == rhs.dimension_5() &&
+    lhs.dimension_6() == rhs.dimension_6() &&
+    lhs.dimension_7() == rhs.dimension_7();
+}
+
+template< class LT , class ... LP , class RT , class ... RP >
+KOKKOS_INLINE_FUNCTION
+bool operator != ( const View<LT,LP...> & lhs ,
+                   const View<RT,RP...> & rhs )
+{
+  return ! ( operator==(lhs,rhs) );
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+inline
+void shared_allocation_tracking_claim_and_disable()
+{ Kokkos::Experimental::Impl::SharedAllocationRecord<void,void>::tracking_claim_and_disable(); }
+
+inline
+void shared_allocation_tracking_release_and_enable()
+{ Kokkos::Experimental::Impl::SharedAllocationRecord<void,void>::tracking_release_and_enable(); }
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template< class OutputView , typename Enable = void >
+struct ViewFill {
+
+  typedef typename OutputView::const_value_type  const_value_type ;
+
+  const OutputView output ;
+  const_value_type input ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_t i0 ) const
+  {
+    const size_t n1 = output.dimension_1();
+    const size_t n2 = output.dimension_2();
+    const size_t n3 = output.dimension_3();
+    const size_t n4 = output.dimension_4();
+    const size_t n5 = output.dimension_5();
+    const size_t n6 = output.dimension_6();
+    const size_t n7 = output.dimension_7();
+
+    for ( size_t i1 = 0 ; i1 < n1 ; ++i1 ) {
+    for ( size_t i2 = 0 ; i2 < n2 ; ++i2 ) {
+    for ( size_t i3 = 0 ; i3 < n3 ; ++i3 ) {
+    for ( size_t i4 = 0 ; i4 < n4 ; ++i4 ) {
+    for ( size_t i5 = 0 ; i5 < n5 ; ++i5 ) {
+    for ( size_t i6 = 0 ; i6 < n6 ; ++i6 ) {
+    for ( size_t i7 = 0 ; i7 < n7 ; ++i7 ) {
+      output(i0,i1,i2,i3,i4,i5,i6,i7) = input ;
+    }}}}}}}
+  }
+
+  ViewFill( const OutputView & arg_out , const_value_type & arg_in )
+    : output( arg_out ), input( arg_in )
+    {
+      typedef typename OutputView::execution_space  execution_space ;
+      typedef Kokkos::RangePolicy< execution_space > Policy ;
+
+      const Kokkos::Impl::ParallelFor< ViewFill , Policy > closure( *this , Policy( 0 , output.dimension_0() ) );
+
+      closure.execute();
+
+      execution_space::fence();
+    }
+};
+
+template< class OutputView >
+struct ViewFill< OutputView , typename std::enable_if< OutputView::Rank == 0 >::type > {
+  ViewFill( const OutputView & dst , const typename OutputView::const_value_type & src )
+    {
+      Kokkos::Impl::DeepCopy< typename OutputView::memory_space , Kokkos::HostSpace >
+        ( dst.data() , & src , sizeof(typename OutputView::const_value_type) );
+    }
+};
+
+template< class OutputView , class InputView , class ExecSpace = typename OutputView::execution_space >
+struct ViewRemap {
+
+  const OutputView output ;
+  const InputView  input ;
+  const size_t n0 ;
+  const size_t n1 ;
+  const size_t n2 ;
+  const size_t n3 ;
+  const size_t n4 ;
+  const size_t n5 ;
+  const size_t n6 ;
+  const size_t n7 ;
+
+  ViewRemap( const OutputView & arg_out , const InputView & arg_in )
+    : output( arg_out ), input( arg_in )
+    , n0( std::min( (size_t)arg_out.dimension_0() , (size_t)arg_in.dimension_0() ) )
+    , n1( std::min( (size_t)arg_out.dimension_1() , (size_t)arg_in.dimension_1() ) )
+    , n2( std::min( (size_t)arg_out.dimension_2() , (size_t)arg_in.dimension_2() ) )
+    , n3( std::min( (size_t)arg_out.dimension_3() , (size_t)arg_in.dimension_3() ) )
+    , n4( std::min( (size_t)arg_out.dimension_4() , (size_t)arg_in.dimension_4() ) )
+    , n5( std::min( (size_t)arg_out.dimension_5() , (size_t)arg_in.dimension_5() ) )
+    , n6( std::min( (size_t)arg_out.dimension_6() , (size_t)arg_in.dimension_6() ) )
+    , n7( std::min( (size_t)arg_out.dimension_7() , (size_t)arg_in.dimension_7() ) )
+    {
+      typedef Kokkos::RangePolicy< ExecSpace > Policy ;
+      const Kokkos::Impl::ParallelFor< ViewRemap , Policy > closure( *this , Policy( 0 , n0 ) );
+      closure.execute();
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_t i0 ) const
+  {
+    for ( size_t i1 = 0 ; i1 < n1 ; ++i1 ) {
+    for ( size_t i2 = 0 ; i2 < n2 ; ++i2 ) {
+    for ( size_t i3 = 0 ; i3 < n3 ; ++i3 ) {
+    for ( size_t i4 = 0 ; i4 < n4 ; ++i4 ) {
+    for ( size_t i5 = 0 ; i5 < n5 ; ++i5 ) {
+    for ( size_t i6 = 0 ; i6 < n6 ; ++i6 ) {
+    for ( size_t i7 = 0 ; i7 < n7 ; ++i7 ) {
+      output(i0,i1,i2,i3,i4,i5,i6,i7) = input(i0,i1,i2,i3,i4,i5,i6,i7);
+    }}}}}}}
+  }
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+/** \brief  Deep copy a value from Host memory into a view.  */
+template< class DT , class ... DP >
+inline
+void deep_copy
+  ( const View<DT,DP...> & dst
+  , typename ViewTraits<DT,DP...>::const_value_type & value
+  , typename std::enable_if<
+    std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value
+    >::type * = 0 )
+{
+  static_assert(
+    std::is_same< typename ViewTraits<DT,DP...>::non_const_value_type ,
+                  typename ViewTraits<DT,DP...>::value_type >::value
+    , "deep_copy requires non-const type" );
+
+  Kokkos::Experimental::Impl::ViewFill< View<DT,DP...> >( dst , value );
+}
+
+/** \brief  Deep copy into a value in Host memory from a view.  */
+template< class ST , class ... SP >
+inline
+void deep_copy
+  ( typename ViewTraits<ST,SP...>::non_const_value_type & dst
+  , const View<ST,SP...> & src
+  , typename std::enable_if<
+    std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value
+    >::type * = 0 )
+{
+  static_assert( ViewTraits<ST,SP...>::rank == 0
+               , "ERROR: Non-rank-zero view in deep_copy( value , View )" );
+
+  typedef ViewTraits<ST,SP...>               src_traits ;
+  typedef typename src_traits::memory_space  src_memory_space ;
+  Kokkos::Impl::DeepCopy< HostSpace , src_memory_space >( & dst , src.data() , sizeof(ST) );
+}
+
+//----------------------------------------------------------------------------
+/** \brief  A deep copy between views of compatible type, and rank zero.  */
+template< class DT , class ... DP , class ST , class ... SP >
+inline
+void deep_copy
+  ( const View<DT,DP...> & dst
+  , const View<ST,SP...> & src
+  , typename std::enable_if<(
+    std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value &&
+    std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value &&
+    ( unsigned(ViewTraits<DT,DP...>::rank) == unsigned(0) &&
+      unsigned(ViewTraits<ST,SP...>::rank) == unsigned(0) )
+  )>::type * = 0 )
+{
+  static_assert(
+    std::is_same< typename ViewTraits<DT,DP...>::value_type ,
+                  typename ViewTraits<ST,SP...>::non_const_value_type >::value
+    , "deep_copy requires matching non-const destination type" );
+
+  typedef View<DT,DP...>  dst_type ;
+  typedef View<ST,SP...>  src_type ;
+
+  typedef typename dst_type::value_type    value_type ;
+  typedef typename dst_type::memory_space  dst_memory_space ;
+  typedef typename src_type::memory_space  src_memory_space ;
+
+  if ( dst.data() != src.data() ) {
+    Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , sizeof(value_type) );
+  }
+}
+
+//----------------------------------------------------------------------------
+/** \brief  A deep copy between views of the default specialization, compatible type,
+ *          same non-zero rank, same contiguous layout.
+ */
+template< class DT , class ... DP , class ST , class ... SP >
+inline
+void deep_copy
+  ( const View<DT,DP...> & dst
+  , const View<ST,SP...> & src
+  , typename std::enable_if<(
+    std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value &&
+    std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value &&
+    ( unsigned(ViewTraits<DT,DP...>::rank) != 0 ||
+      unsigned(ViewTraits<ST,SP...>::rank) != 0 )
+  )>::type * = 0 )
+{
+  static_assert(
+    std::is_same< typename ViewTraits<DT,DP...>::value_type ,
+                  typename ViewTraits<DT,DP...>::non_const_value_type >::value
+    , "deep_copy requires non-const destination type" );
+
+  static_assert(
+    ( unsigned(ViewTraits<DT,DP...>::rank) ==
+      unsigned(ViewTraits<ST,SP...>::rank) )
+    , "deep_copy requires Views of equal rank" );
+
+  typedef View<DT,DP...>  dst_type ;
+  typedef View<ST,SP...>  src_type ;
+
+  typedef typename dst_type::execution_space  dst_execution_space ;
+  typedef typename src_type::execution_space  src_execution_space ;
+  typedef typename dst_type::memory_space     dst_memory_space ;
+  typedef typename src_type::memory_space     src_memory_space ;
+
+  enum { DstExecCanAccessSrc =
+   Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename dst_execution_space::memory_space , src_memory_space >::value };
+
+  enum { SrcExecCanAccessDst =
+   Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename src_execution_space::memory_space , dst_memory_space >::value };
+
+
+  if ( (void *) dst.data() != (void*) src.data() ) {
+
+    // Concern: If overlapping views then a parallel copy will be erroneous.
+    // ...
+
+    // If same type, equal layout, equal dimensions, equal span, and contiguous memory then can byte-wise copy
+
+    if ( std::is_same< typename ViewTraits<DT,DP...>::value_type ,
+                       typename ViewTraits<ST,SP...>::non_const_value_type >::value &&
+         (
+           ( std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
+                           typename ViewTraits<ST,SP...>::array_layout >::value
+             &&
+             ( std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
+                             typename Kokkos::LayoutLeft>::value
+             ||
+               std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
+                             typename Kokkos::LayoutRight>::value
+             )
+           )
+           ||
+           ( ViewTraits<DT,DP...>::rank == 1 &&
+             ViewTraits<ST,SP...>::rank == 1 )
+         ) &&
+         dst.span_is_contiguous() &&
+         src.span_is_contiguous() &&
+         dst.span() == src.span() &&
+         dst.dimension_0() == src.dimension_0() &&
+         dst.dimension_1() == src.dimension_1() &&
+         dst.dimension_2() == src.dimension_2() &&
+         dst.dimension_3() == src.dimension_3() &&
+         dst.dimension_4() == src.dimension_4() &&
+         dst.dimension_5() == src.dimension_5() &&
+         dst.dimension_6() == src.dimension_6() &&
+         dst.dimension_7() == src.dimension_7() ) {
+
+      const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
+
+      Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , nbytes );
+    }
+    else if ( std::is_same< typename ViewTraits<DT,DP...>::value_type ,
+                            typename ViewTraits<ST,SP...>::non_const_value_type >::value &&
+         (
+           ( std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
+                           typename ViewTraits<ST,SP...>::array_layout >::value
+             &&
+             std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
+                          typename Kokkos::LayoutStride>::value
+           )
+           ||
+           ( ViewTraits<DT,DP...>::rank == 1 &&
+             ViewTraits<ST,SP...>::rank == 1 )
+         ) &&
+         dst.span_is_contiguous() &&
+         src.span_is_contiguous() &&
+         dst.span() == src.span() &&
+         dst.dimension_0() == src.dimension_0() &&
+         dst.dimension_1() == src.dimension_1() &&
+         dst.dimension_2() == src.dimension_2() &&
+         dst.dimension_3() == src.dimension_3() &&
+         dst.dimension_4() == src.dimension_4() &&
+         dst.dimension_5() == src.dimension_5() &&
+         dst.dimension_6() == src.dimension_6() &&
+         dst.dimension_7() == src.dimension_7() &&
+         dst.stride_0() == src.stride_0() &&
+         dst.stride_1() == src.stride_1() &&
+         dst.stride_2() == src.stride_2() &&
+         dst.stride_3() == src.stride_3() &&
+         dst.stride_4() == src.stride_4() &&
+         dst.stride_5() == src.stride_5() &&
+         dst.stride_6() == src.stride_6() &&
+         dst.stride_7() == src.stride_7()
+         ) {
+
+      const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
+
+      Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , nbytes );
+    }
+    else if ( DstExecCanAccessSrc ) {
+      // Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
+      Kokkos::Experimental::Impl::ViewRemap< dst_type , src_type >( dst , src );
+    }
+    else if ( SrcExecCanAccessDst ) {
+      // Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
+      Kokkos::Experimental::Impl::ViewRemap< dst_type , src_type , src_execution_space >( dst , src );
+    }
+    else {
+      Kokkos::Impl::throw_runtime_exception("deep_copy given views that would require a temporary allocation");
+    }
+  }
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+/** \brief  Deep copy a value from Host memory into a view.  */
+template< class ExecSpace ,class DT , class ... DP >
+inline
+void deep_copy
+  ( const ExecSpace &
+  , const View<DT,DP...> & dst
+  , typename ViewTraits<DT,DP...>::const_value_type & value
+  , typename std::enable_if<
+    Kokkos::Impl::is_execution_space< ExecSpace >::value &&
+    std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value
+    >::type * = 0 )
+{
+  static_assert(
+    std::is_same< typename ViewTraits<DT,DP...>::non_const_value_type ,
+                  typename ViewTraits<DT,DP...>::value_type >::value
+    , "deep_copy requires non-const type" );
+
+  Kokkos::Experimental::Impl::ViewFill< View<DT,DP...> >( dst , value );
+}
+
+/** \brief  Deep copy into a value in Host memory from a view.  */
+template< class ExecSpace , class ST , class ... SP >
+inline
+void deep_copy
+  ( const ExecSpace & exec_space
+  , typename ViewTraits<ST,SP...>::non_const_value_type & dst
+  , const View<ST,SP...> & src
+  , typename std::enable_if<
+    Kokkos::Impl::is_execution_space< ExecSpace >::value &&
+    std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value
+    >::type * = 0 )
+{
+  static_assert( ViewTraits<ST,SP...>::rank == 0
+               , "ERROR: Non-rank-zero view in deep_copy( value , View )" );
+
+  typedef ViewTraits<ST,SP...>               src_traits ;
+  typedef typename src_traits::memory_space  src_memory_space ;
+  Kokkos::Impl::DeepCopy< HostSpace , src_memory_space , ExecSpace >
+    ( exec_space , & dst , src.data() , sizeof(ST) );
+}
+
+//----------------------------------------------------------------------------
+/** \brief  A deep copy between views of compatible type, and rank zero.  */
+template< class ExecSpace , class DT , class ... DP , class ST , class ... SP >
+inline
+void deep_copy
+  ( const ExecSpace & exec_space
+  , const View<DT,DP...> & dst
+  , const View<ST,SP...> & src
+  , typename std::enable_if<(
+    Kokkos::Impl::is_execution_space< ExecSpace >::value &&
+    std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value &&
+    std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value &&
+    ( unsigned(ViewTraits<DT,DP...>::rank) == unsigned(0) &&
+      unsigned(ViewTraits<ST,SP...>::rank) == unsigned(0) )
+  )>::type * = 0 )
+{
+  static_assert(
+    std::is_same< typename ViewTraits<DT,DP...>::value_type ,
+                  typename ViewTraits<ST,SP...>::non_const_value_type >::value
+    , "deep_copy requires matching non-const destination type" );
+
+  typedef View<DT,DP...>  dst_type ;
+  typedef View<ST,SP...>  src_type ;
+
+  typedef typename dst_type::value_type    value_type ;
+  typedef typename dst_type::memory_space  dst_memory_space ;
+  typedef typename src_type::memory_space  src_memory_space ;
+
+  if ( dst.data() != src.data() ) {
+    Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space , ExecSpace >
+      ( exec_space , dst.data() , src.data() , sizeof(value_type) );
+  }
+}
+
+//----------------------------------------------------------------------------
+/** \brief  A deep copy between views of the default specialization, compatible type,
+ *          same non-zero rank, same contiguous layout.
+ */
+template< class ExecSpace , class DT, class ... DP, class ST, class ... SP >
+inline
+void deep_copy
+  ( const ExecSpace & exec_space
+  , const View<DT,DP...> & dst
+  , const View<ST,SP...> & src
+  , typename std::enable_if<(
+    Kokkos::Impl::is_execution_space< ExecSpace >::value &&
+    std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value &&
+    std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value &&
+    ( unsigned(ViewTraits<DT,DP...>::rank) != 0 ||
+      unsigned(ViewTraits<ST,SP...>::rank) != 0 )
+  )>::type * = 0 )
+{
+  static_assert(
+    std::is_same< typename ViewTraits<DT,DP...>::value_type ,
+                  typename ViewTraits<DT,DP...>::non_const_value_type >::value
+    , "deep_copy requires non-const destination type" );
+
+  static_assert(
+    ( unsigned(ViewTraits<DT,DP...>::rank) ==
+      unsigned(ViewTraits<ST,SP...>::rank) )
+    , "deep_copy requires Views of equal rank" );
+
+  typedef View<DT,DP...>  dst_type ;
+  typedef View<ST,SP...>  src_type ;
+
+  typedef typename dst_type::execution_space  dst_execution_space ;
+  typedef typename src_type::execution_space  src_execution_space ;
+  typedef typename dst_type::memory_space     dst_memory_space ;
+  typedef typename src_type::memory_space     src_memory_space ;
+
+  enum { DstExecCanAccessSrc =
+   Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename dst_execution_space::memory_space , src_memory_space >::value };
+
+  enum { SrcExecCanAccessDst =
+   Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename src_execution_space::memory_space , dst_memory_space >::value };
+
+  if ( (void *) dst.data() != (void*) src.data() ) {
+
+    // Concern: If overlapping views then a parallel copy will be erroneous.
+    // ...
+
+    // If same type, equal layout, equal dimensions, equal span, and contiguous memory then can byte-wise copy
+
+    if ( std::is_same< typename ViewTraits<DT,DP...>::value_type ,
+                       typename ViewTraits<ST,SP...>::non_const_value_type >::value &&
+         (
+           std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
+                         typename ViewTraits<ST,SP...>::array_layout >::value
+           ||
+           ( ViewTraits<DT,DP...>::rank == 1 &&
+             ViewTraits<ST,SP...>::rank == 1 )
+         ) &&
+         dst.span_is_contiguous() &&
+         src.span_is_contiguous() &&
+         dst.span() == src.span() &&
+         dst.dimension_0() == src.dimension_0() &&
+         dst.dimension_1() == src.dimension_1() &&
+         dst.dimension_2() == src.dimension_2() &&
+         dst.dimension_3() == src.dimension_3() &&
+         dst.dimension_4() == src.dimension_4() &&
+         dst.dimension_5() == src.dimension_5() &&
+         dst.dimension_6() == src.dimension_6() &&
+         dst.dimension_7() == src.dimension_7() ) {
+
+      const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
+
+      Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space , ExecSpace >
+        ( exec_space , dst.data() , src.data() , nbytes );
+    }
+    else if ( DstExecCanAccessSrc ) {
+      // Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
+      Kokkos::Experimental::Impl::ViewRemap< dst_type , src_type >( dst , src );
+    }
+    else if ( SrcExecCanAccessDst ) {
+      // Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
+      Kokkos::Experimental::Impl::ViewRemap< dst_type , src_type , src_execution_space >( dst , src );
+    }
+    else {
+      Kokkos::Impl::throw_runtime_exception("deep_copy given views that would require a temporary allocation");
+    }
+  }
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+// Deduce Mirror Types
+template<class Space, class T, class ... P>
+struct MirrorViewType {
+  // The incoming view_type
+  typedef typename Kokkos::Experimental::View<T,P...> src_view_type;
+  // The memory space for the mirror view
+  typedef typename Space::memory_space memory_space;
+  // Check whether it is the same memory space
+  enum { is_same_memspace = std::is_same<memory_space,typename src_view_type::memory_space>::value };
+  // The array_layout
+  typedef typename src_view_type::array_layout array_layout;
+  // The data type (we probably want it non-const since otherwise we can't even deep_copy to it.
+  typedef typename src_view_type::non_const_data_type data_type;
+  // The destination view type if it is not the same memory space
+  typedef Kokkos::Experimental::View<data_type,array_layout,Space> dest_view_type;
+  // If it is the same memory_space return the existsing view_type
+  // This will also keep the unmanaged trait if necessary
+  typedef typename std::conditional<is_same_memspace,src_view_type,dest_view_type>::type view_type;
+};
+
+template<class Space, class T, class ... P>
+struct MirrorType {
+  // The incoming view_type
+  typedef typename Kokkos::Experimental::View<T,P...> src_view_type;
+  // The memory space for the mirror view
+  typedef typename Space::memory_space memory_space;
+  // Check whether it is the same memory space
+  enum { is_same_memspace = std::is_same<memory_space,typename src_view_type::memory_space>::value };
+  // The array_layout
+  typedef typename src_view_type::array_layout array_layout;
+  // The data type (we probably want it non-const since otherwise we can't even deep_copy to it.
+  typedef typename src_view_type::non_const_data_type data_type;
+  // The destination view type if it is not the same memory space
+  typedef Kokkos::Experimental::View<data_type,array_layout,Space> view_type;
+};
+
+}
+
+template< class T , class ... P >
+inline
+typename Kokkos::Experimental::View<T,P...>::HostMirror
+create_mirror( const Kokkos::Experimental::View<T,P...> & src
+             , typename std::enable_if<
+                 ! std::is_same< typename Kokkos::Experimental::ViewTraits<T,P...>::array_layout
+                               , Kokkos::LayoutStride >::value
+               >::type * = 0
+             )
+{
+  typedef View<T,P...>                   src_type ;
+  typedef typename src_type::HostMirror  dst_type ;
+
+  return dst_type( std::string( src.label() ).append("_mirror")
+                 , src.dimension_0()
+                 , src.dimension_1()
+                 , src.dimension_2()
+                 , src.dimension_3()
+                 , src.dimension_4()
+                 , src.dimension_5()
+                 , src.dimension_6()
+                 , src.dimension_7() );
+}
+
+template< class T , class ... P >
+inline
+typename Kokkos::Experimental::View<T,P...>::HostMirror
+create_mirror( const Kokkos::Experimental::View<T,P...> & src
+             , typename std::enable_if<
+                 std::is_same< typename Kokkos::Experimental::ViewTraits<T,P...>::array_layout
+                             , Kokkos::LayoutStride >::value
+               >::type * = 0
+             )
+{
+  typedef View<T,P...>                   src_type ;
+  typedef typename src_type::HostMirror  dst_type ;
+
+  Kokkos::LayoutStride layout ;
+
+  layout.dimension[0] = src.dimension_0();
+  layout.dimension[1] = src.dimension_1();
+  layout.dimension[2] = src.dimension_2();
+  layout.dimension[3] = src.dimension_3();
+  layout.dimension[4] = src.dimension_4();
+  layout.dimension[5] = src.dimension_5();
+  layout.dimension[6] = src.dimension_6();
+  layout.dimension[7] = src.dimension_7();
+
+  layout.stride[0] = src.stride_0();
+  layout.stride[1] = src.stride_1();
+  layout.stride[2] = src.stride_2();
+  layout.stride[3] = src.stride_3();
+  layout.stride[4] = src.stride_4();
+  layout.stride[5] = src.stride_5();
+  layout.stride[6] = src.stride_6();
+  layout.stride[7] = src.stride_7();
+
+  return dst_type( std::string( src.label() ).append("_mirror") , layout );
+}
+
+
+// Create a mirror in a new space (specialization for different space)
+template<class Space, class T, class ... P>
+typename Impl::MirrorType<Space,T,P ...>::view_type create_mirror(const Space& , const Kokkos::Experimental::View<T,P...> & src) {
+  return typename Impl::MirrorType<Space,T,P ...>::view_type(src.label(),src.layout());
+}
+
+template< class T , class ... P >
+inline
+typename Kokkos::Experimental::View<T,P...>::HostMirror
+create_mirror_view( const Kokkos::Experimental::View<T,P...> & src
+                  , typename std::enable_if<(
+                      std::is_same< typename Kokkos::Experimental::View<T,P...>::memory_space
+                                  , typename Kokkos::Experimental::View<T,P...>::HostMirror::memory_space
+                                  >::value
+                      &&
+                      std::is_same< typename Kokkos::Experimental::View<T,P...>::data_type
+                                  , typename Kokkos::Experimental::View<T,P...>::HostMirror::data_type
+                                  >::value
+                    )>::type * = 0
+                  )
+{
+  return src ;
+}
+
+template< class T , class ... P >
+inline
+typename Kokkos::Experimental::View<T,P...>::HostMirror
+create_mirror_view( const Kokkos::Experimental::View<T,P...> & src
+                  , typename std::enable_if< ! (
+                      std::is_same< typename Kokkos::Experimental::View<T,P...>::memory_space
+                                  , typename Kokkos::Experimental::View<T,P...>::HostMirror::memory_space
+                                  >::value
+                      &&
+                      std::is_same< typename Kokkos::Experimental::View<T,P...>::data_type
+                                  , typename Kokkos::Experimental::View<T,P...>::HostMirror::data_type
+                                  >::value
+                    )>::type * = 0
+                  )
+{
+  return Kokkos::Experimental::create_mirror( src );
+}
+
+// Create a mirror view in a new space (specialization for same space)
+template<class Space, class T, class ... P>
+typename Impl::MirrorViewType<Space,T,P ...>::view_type
+create_mirror_view(const Space& , const Kokkos::Experimental::View<T,P...> & src
+  , typename std::enable_if<Impl::MirrorViewType<Space,T,P ...>::is_same_memspace>::type* = 0 ) {
+  return src;
+}
+
+// Create a mirror view in a new space (specialization for different space)
+template<class Space, class T, class ... P>
+typename Impl::MirrorViewType<Space,T,P ...>::view_type
+create_mirror_view(const Space& , const Kokkos::Experimental::View<T,P...> & src
+  , typename std::enable_if<!Impl::MirrorViewType<Space,T,P ...>::is_same_memspace>::type* = 0 ) {
+  return typename Impl::MirrorViewType<Space,T,P ...>::view_type(src.label(),src.layout());
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+/** \brief  Resize a view with copying old data to new data at the corresponding indices. */
+template< class T , class ... P >
+inline
+void resize( Kokkos::Experimental::View<T,P...> & v ,
+             const size_t n0 = 0 ,
+             const size_t n1 = 0 ,
+             const size_t n2 = 0 ,
+             const size_t n3 = 0 ,
+             const size_t n4 = 0 ,
+             const size_t n5 = 0 ,
+             const size_t n6 = 0 ,
+             const size_t n7 = 0 )
+{
+  typedef Kokkos::Experimental::View<T,P...>  view_type ;
+
+  static_assert( Kokkos::Experimental::ViewTraits<T,P...>::is_managed , "Can only resize managed views" );
+
+  view_type v_resized( v.label(), n0, n1, n2, n3, n4, n5, n6, n7 );
+
+  Kokkos::Experimental::Impl::ViewRemap< view_type , view_type >( v_resized , v );
+
+  v = v_resized ;
+}
+
+/** \brief  Resize a view with copying old data to new data at the corresponding indices. */
+template< class T , class ... P >
+inline
+void realloc( Kokkos::Experimental::View<T,P...> & v ,
+              const size_t n0 = 0 ,
+              const size_t n1 = 0 ,
+              const size_t n2 = 0 ,
+              const size_t n3 = 0 ,
+              const size_t n4 = 0 ,
+              const size_t n5 = 0 ,
+              const size_t n6 = 0 ,
+              const size_t n7 = 0 )
+{
+  typedef Kokkos::Experimental::View<T,P...>  view_type ;
+
+  static_assert( Kokkos::Experimental::ViewTraits<T,P...>::is_managed , "Can only realloc managed views" );
+
+  const std::string label = v.label();
+
+  v = view_type(); // Deallocate first, if the only view to allocation
+  v = view_type( label, n0, n1, n2, n3, n4, n5, n6, n7 );
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template< class D , class ... P >
+using ViewTraits = Kokkos::Experimental::ViewTraits<D,P...> ;
+
+using Experimental::View ; //modified due to gcc parser bug 
+//template< class D , class ... P >
+//using View = Kokkos::Experimental::View<D,P...> ;
+
+using Kokkos::Experimental::ALL ;
+using Kokkos::Experimental::WithoutInitializing ;
+using Kokkos::Experimental::AllowPadding ;
+using Kokkos::Experimental::view_alloc ;
+using Kokkos::Experimental::view_wrap ;
+
+using Kokkos::Experimental::deep_copy ;
+using Kokkos::Experimental::create_mirror ;
+using Kokkos::Experimental::create_mirror_view ;
+using Kokkos::Experimental::subview ;
+using Kokkos::Experimental::resize ;
+using Kokkos::Experimental::realloc ;
+using Kokkos::Experimental::is_view ;
+
+namespace Impl {
+
+using Kokkos::Experimental::is_view ;
+
+class ViewDefault {};
+
+template< class SrcViewType
+        , class Arg0Type
+        , class Arg1Type
+        , class Arg2Type
+        , class Arg3Type
+        , class Arg4Type
+        , class Arg5Type
+        , class Arg6Type
+        , class Arg7Type
+        >
+struct ViewSubview /* { typedef ... type ; } */ ;
+
+}
+
+} /* namespace Kokkos */
+
+#include <impl/Kokkos_Atomic_View.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_VIEW_HPP */
+
diff --git a/lib/kokkos/core/src/Kokkos_hwloc.hpp b/lib/kokkos/core/src/Kokkos_hwloc.hpp
new file mode 100644
index 0000000000..ff713c9523
--- /dev/null
+++ b/lib/kokkos/core/src/Kokkos_hwloc.hpp
@@ -0,0 +1,144 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_HWLOC_HPP
+#define KOKKOS_HWLOC_HPP
+
+#include <utility>
+
+namespace Kokkos {
+
+/** \brief  Minimal subset of logical 'hwloc' functionality available
+ *          from http://www.open-mpi.org/projects/hwloc/.
+ *
+ *  The calls are NOT thread safe in order to avoid mutexes,
+ *  memory allocations, or other actions which could give the
+ *  runtime system an opportunity to migrate the threads or
+ *  touch allocated memory during the function calls.
+ *
+ *  All calls to these functions should be performed by a thread
+ *  when it has guaranteed exclusive access; e.g., for OpenMP
+ *  within a 'critical' region.
+ */
+namespace hwloc {
+
+/** \brief  Query if hwloc is available */
+bool available();
+
+/** \brief  Query number of available NUMA regions.
+ *          This will be less than the hardware capacity
+ *          if the MPI process is pinned to a NUMA region.
+ */
+unsigned get_available_numa_count();
+
+/** \brief  Query number of available cores per NUMA regions.
+ *          This will be less than the hardware capacity
+ *          if the MPI process is pinned to a set of cores.
+ */
+unsigned get_available_cores_per_numa();
+
+/** \brief  Query number of available "hard" threads per core; i.e., hyperthreads */
+unsigned get_available_threads_per_core();
+
+} /* namespace hwloc */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// Internal functions for binding persistent spawned threads.
+
+namespace Kokkos {
+namespace hwloc {
+
+/** \brief  Recommend mapping of threads onto cores.
+ *
+ * If thread_count == 0 then choose and set a value.
+ * If use_numa_count == 0 then choose and set a value.
+ * If use_cores_per_numa == 0 then choose and set a value.
+ *
+ * Return 0 if asynchronous,
+ * Return 1 if synchronous and threads_coord[0] is process core
+ */
+unsigned thread_mapping( const char * const label ,
+                         const bool allow_async ,
+                         unsigned & thread_count ,
+                         unsigned & use_numa_count ,
+                         unsigned & use_cores_per_numa ,
+                         std::pair<unsigned,unsigned> threads_coord[] );
+
+/** \brief  Query core-coordinate of the current thread
+ *          with respect to the core_topology.
+ *
+ *  As long as the thread is running within the
+ *  process binding the following condition holds.
+ *
+ *  core_coordinate.first  < core_topology.first
+ *  core_coordinate.second < core_topology.second
+ */
+std::pair<unsigned,unsigned> get_this_thread_coordinate();
+
+/** \brief  Bind the current thread to a core. */
+bool bind_this_thread( const std::pair<unsigned,unsigned> );
+
+
+/** \brief Can hwloc bind threads? */
+bool can_bind_threads();
+
+/** \brief  Bind the current thread to one of the cores in the list.
+ *          Set that entry to (~0,~0) and return the index.
+ *          If binding fails return ~0.
+ */
+unsigned bind_this_thread( const unsigned               coordinate_count ,
+                           std::pair<unsigned,unsigned> coordinate[] );
+
+/** \brief  Unbind the current thread back to the original process binding */
+bool unbind_this_thread();
+
+} /* namespace hwloc */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #define KOKKOS_HWLOC_HPP */
+
diff --git a/lib/kokkos/core/src/Makefile b/lib/kokkos/core/src/Makefile
new file mode 100644
index 0000000000..dc27d341ac
--- /dev/null
+++ b/lib/kokkos/core/src/Makefile
@@ -0,0 +1,124 @@
+KOKKOS_PATH = ../..
+
+PREFIX ?= /usr/local/lib/kokkos
+
+default: messages build-lib
+	echo "End Build"
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(NVCC_WRAPPER)
+	LINKFLAGS ?= 
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= g++
+	LINKFLAGS ?=  
+endif
+
+PWD = $(shell pwd)
+
+KOKKOS_HEADERS_INCLUDE = $(wildcard $(KOKKOS_PATH)/core/src/*.hpp)
+KOKKOS_HEADERS_INCLUDE_IMPL = $(wildcard $(KOKKOS_PATH)/core/src/impl/*.hpp)
+KOKKOS_HEADERS_INCLUDE += $(wildcard $(KOKKOS_PATH)/containers/src/*.hpp)
+KOKKOS_HEADERS_INCLUDE_IMPL += $(wildcard $(KOKKOS_PATH)/containers/src/impl/*.hpp)
+KOKKOS_HEADERS_INCLUDE += $(wildcard $(KOKKOS_PATH)/algorithms/src/*.hpp)
+
+CONDITIONAL_COPIES =
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	KOKKOS_HEADERS_CUDA += $(wildcard $(KOKKOS_PATH)/core/src/Cuda/*.hpp)
+	CONDITIONAL_COPIES += copy-cuda
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+	KOKKOS_HEADERS_THREADS += $(wildcard $(KOKKOS_PATH)/core/src/Threads/*.hpp)
+	CONDITIONAL_COPIES += copy-threads
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_QTHREAD), 1)
+	KOKKOS_HEADERS_QTHREAD += $(wildcard $(KOKKOS_PATH)/core/src/Qthread/*.hpp)
+	CONDITIONAL_COPIES += copy-qthread
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+	KOKKOS_HEADERS_OPENMP += $(wildcard $(KOKKOS_PATH)/core/src/OpenMP/*.hpp)
+	CONDITIONAL_COPIES += copy-openmp
+endif
+
+messages: 
+	echo "Start Build"
+
+build-makefile-kokkos:
+	rm -f Makefile.kokkos
+	echo "#Global Settings used to generate this library" >> Makefile.kokkos
+	echo "KOKKOS_PATH = $(PREFIX)" >> Makefile.kokkos
+	echo "KOKKOS_DEVICES = $(KOKKOS_DEVICES)" >> Makefile.kokkos
+	echo "KOKKOS_ARCH = $(KOKKOS_ARCH)" >> Makefile.kokkos
+	echo "KOKKOS_DEBUG = $(KOKKOS_DEBUG)" >> Makefile.kokkos
+	echo "KOKKOS_USE_TPLS = $(KOKKOS_USE_TPLS)" >> Makefile.kokkos
+	echo "KOKKOS_CXX_STANDARD = $(KOKKOS_CXX_STANDARD)" >> Makefile.kokkos
+	echo "KOKKOS_OPTIONS = $(KOKKOS_OPTIONS)" >> Makefile.kokkos
+	echo "KOKKOS_CUDA_OPTIONS = $(KOKKOS_CUDA_OPTIONS)" >> Makefile.kokkos
+	echo "CXX ?= $(CXX)" >> Makefile.kokkos 
+	echo "NVCC_WRAPPER ?= $(PREFIX)/bin/nvcc_wrapper" >> Makefile.kokkos
+	echo "" >> Makefile.kokkos  
+	echo "#Source and Header files of Kokkos relative to KOKKOS_PATH" >> Makefile.kokkos
+	echo "KOKKOS_HEADERS = $(KOKKOS_HEADERS)" >> Makefile.kokkos
+	echo "KOKKOS_SRC = $(KOKKOS_SRC)" >> Makefile.kokkos
+	echo "" >> Makefile.kokkos  
+	echo "#Variables used in application Makefiles" >> Makefile.kokkos
+	echo "KOKKOS_CPP_DEPENDS = $(KOKKOS_CPP_DEPENDS)" >> Makefile.kokkos
+	echo "KOKKOS_CXXFLAGS = $(KOKKOS_CXXFLAGS)" >> Makefile.kokkos
+	echo "KOKKOS_CPPFLAGS = $(KOKKOS_CPPFLAGS)" >> Makefile.kokkos
+	echo "KOKKOS_LINK_DEPENDS  = $(KOKKOS_LINK_DEPENDS)" >> Makefile.kokkos
+	echo "KOKKOS_LIBS = $(KOKKOS_LIBS)" >> Makefile.kokkos
+	echo "KOKKOS_LDFLAGS = $(KOKKOS_LDFLAGS)" >> Makefile.kokkos
+	sed \
+		-e 's|$(KOKKOS_PATH)/core/src|$(PREFIX)/include|g' \
+		-e 's|$(KOKKOS_PATH)/containers/src|$(PREFIX)/include|g' \
+		-e 's|$(KOKKOS_PATH)/algorithms/src|$(PREFIX)/include|g' \
+		-e 's|-L$(PWD)|-L$(PREFIX)/lib|g' \
+		-e 's|= libkokkos.a|= $(PREFIX)/lib/libkokkos.a|g' \
+		-e 's|= KokkosCore_config.h|= $(PREFIX)/include/KokkosCore_config.h|g' Makefile.kokkos \
+		> Makefile.kokkos.tmp
+	mv -f Makefile.kokkos.tmp Makefile.kokkos
+
+build-lib: build-makefile-kokkos $(KOKKOS_LINK_DEPENDS)
+
+mkdir: 
+	mkdir -p $(PREFIX)
+	mkdir -p $(PREFIX)/bin
+	mkdir -p $(PREFIX)/include
+	mkdir -p $(PREFIX)/lib
+	mkdir -p $(PREFIX)/include/impl
+
+copy-cuda: mkdir
+	mkdir -p $(PREFIX)/include/Cuda
+	cp $(KOKKOS_HEADERS_CUDA) $(PREFIX)/include/Cuda
+
+copy-threads: mkdir
+	mkdir -p $(PREFIX)/include/Threads
+	cp $(KOKKOS_HEADERS_THREADS) $(PREFIX)/include/Threads
+
+copy-qthread: mkdir
+	mkdir -p $(PREFIX)/include/Qthread
+	cp $(KOKKOS_HEADERS_QTHREAD) $(PREFIX)/include/Qthread
+
+copy-openmp: mkdir
+	mkdir -p $(PREFIX)/include/OpenMP
+	cp $(KOKKOS_HEADERS_OPENMP) $(PREFIX)/include/OpenMP
+
+install: mkdir $(CONDITIONAL_COPIES) build-lib 
+	cp $(NVCC_WRAPPER) $(PREFIX)/bin
+	cp $(KOKKOS_HEADERS_INCLUDE) $(PREFIX)/include
+	cp $(KOKKOS_HEADERS_INCLUDE_IMPL) $(PREFIX)/include/impl
+	cp Makefile.kokkos $(PREFIX)
+	cp libkokkos.a $(PREFIX)/lib
+	cp KokkosCore_config.h $(PREFIX)/include
+
+clean: kokkos-clean
+	rm -f Makefile.kokkos
diff --git a/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Parallel.hpp b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Parallel.hpp
new file mode 100644
index 0000000000..27ae5803ce
--- /dev/null
+++ b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Parallel.hpp
@@ -0,0 +1,750 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_OPENMP_PARALLEL_HPP
+#define KOKKOS_OPENMP_PARALLEL_HPP
+
+#include <omp.h>
+#include <iostream>
+#include <Kokkos_Parallel.hpp>
+#include <OpenMP/Kokkos_OpenMPexec.hpp>
+#include <impl/Kokkos_FunctorAdapter.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ... Traits >
+class ParallelFor< FunctorType
+                 , Kokkos::RangePolicy< Traits ... >
+                 , Kokkos::OpenMP 
+                 >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ...  > Policy ;
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::WorkRange    WorkRange ;
+  typedef typename Policy::member_type  Member ;
+
+  const FunctorType m_functor ;
+  const Policy      m_policy ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend )
+    {
+      #ifdef KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION
+      #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+      #pragma ivdep
+      #endif
+      #endif
+      for ( Member iwork = ibeg ; iwork < iend ; ++iwork ) {
+        functor( iwork );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend )
+    {
+      const TagType t{} ;
+      #ifdef KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION
+      #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+      #pragma ivdep
+      #endif
+      #endif
+      for ( Member iwork = ibeg ; iwork < iend ; ++iwork ) {
+        functor( t , iwork );
+      }
+    }
+
+public:
+
+  inline void execute() const {
+    this->template execute_schedule<typename Policy::schedule_type::type>();
+  }
+
+  template<class Schedule>
+  inline
+  typename std::enable_if< std::is_same<Schedule,Kokkos::Static>::value >::type
+    execute_schedule() const
+    {
+      OpenMPexec::verify_is_process("Kokkos::OpenMP parallel_for");
+      OpenMPexec::verify_initialized("Kokkos::OpenMP parallel_for");
+
+#pragma omp parallel
+      {
+        OpenMPexec & exec = * OpenMPexec::get_thread_omp();
+
+        const WorkRange range( m_policy, exec.pool_rank(), exec.pool_size() );
+
+        ParallelFor::template exec_range< WorkTag >( m_functor , range.begin() , range.end() );
+      }
+/* END #pragma omp parallel */
+    }
+
+  template<class Schedule>
+  inline
+  typename std::enable_if< std::is_same<Schedule,Kokkos::Dynamic>::value >::type
+    execute_schedule() const
+    {
+      OpenMPexec::verify_is_process("Kokkos::OpenMP parallel_for");
+      OpenMPexec::verify_initialized("Kokkos::OpenMP parallel_for");
+
+#pragma omp parallel
+      {
+        OpenMPexec & exec = * OpenMPexec::get_thread_omp();
+
+        const WorkRange range( m_policy, exec.pool_rank(), exec.pool_size() );
+
+        exec.set_work_range(range.begin(),range.end(),m_policy.chunk_size());
+        exec.reset_steal_target();
+        #pragma omp barrier
+        
+        long work_index = exec.get_work_index();
+
+        while(work_index != -1) {
+          const Member begin = static_cast<Member>(work_index) * m_policy.chunk_size();
+          const Member end = begin + m_policy.chunk_size() < m_policy.end()?begin+m_policy.chunk_size():m_policy.end();
+          ParallelFor::template exec_range< WorkTag >( m_functor , begin, end );
+          work_index = exec.get_work_index();
+        }
+
+      }
+/* END #pragma omp parallel */
+    }
+
+  inline
+  ParallelFor( const FunctorType & arg_functor
+             , Policy arg_policy )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    {}
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ReducerType, class ... Traits >
+class ParallelReduce< FunctorType
+                    , Kokkos::RangePolicy< Traits ...>
+                    , ReducerType
+                    , Kokkos::OpenMP
+                    >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy ;
+
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::WorkRange    WorkRange ;
+  typedef typename Policy::member_type  Member ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  // Static Assert WorkTag void if ReducerType not InvalidType
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd, WorkTag > ValueInit ;
+  typedef Kokkos::Impl::FunctorValueJoin<   ReducerTypeFwd, WorkTag > ValueJoin ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType   m_functor ;
+  const Policy        m_policy ;
+  const ReducerType   m_reducer ;
+  const pointer_type  m_result_ptr ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend
+            , reference_type update )
+    {
+      #ifdef KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION
+      #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+      #pragma ivdep
+      #endif
+      #endif
+      for ( Member iwork = ibeg ; iwork < iend ; ++iwork ) {
+        functor( iwork , update );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend
+            , reference_type update )
+    {
+      const TagType t{} ;
+      #ifdef KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION
+      #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+      #pragma ivdep
+      #endif
+      #endif
+      for ( Member iwork = ibeg ; iwork < iend ; ++iwork ) {
+        functor( t , iwork , update );
+      }
+    }
+
+public:
+
+  inline void execute() const {
+    this->template execute_schedule<typename Policy::schedule_type::type>();
+  }
+
+  template<class Schedule>
+  inline
+  typename std::enable_if< std::is_same<Schedule,Kokkos::Static>::value >::type
+    execute_schedule() const
+    {
+      OpenMPexec::verify_is_process("Kokkos::OpenMP parallel_reduce");
+      OpenMPexec::verify_initialized("Kokkos::OpenMP parallel_reduce");
+
+      OpenMPexec::resize_scratch( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) , 0 );
+
+#pragma omp parallel
+      {
+        OpenMPexec & exec = * OpenMPexec::get_thread_omp();
+        const WorkRange range( m_policy, exec.pool_rank(), exec.pool_size() );
+        ParallelReduce::template exec_range< WorkTag >
+          ( m_functor , range.begin() , range.end()
+          , ValueInit::init( ReducerConditional::select(m_functor , m_reducer), exec.scratch_reduce() ) );
+      }
+/* END #pragma omp parallel */
+
+      // Reduction:
+
+      const pointer_type ptr = pointer_type( OpenMPexec::pool_rev(0)->scratch_reduce() );
+
+      for ( int i = 1 ; i < OpenMPexec::pool_size() ; ++i ) {
+        ValueJoin::join( ReducerConditional::select(m_functor , m_reducer) , ptr , OpenMPexec::pool_rev(i)->scratch_reduce() );
+      }
+
+      Kokkos::Impl::FunctorFinal<  ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer) , ptr );
+
+      if ( m_result_ptr ) {
+        const int n = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer) );
+
+        for ( int j = 0 ; j < n ; ++j ) { m_result_ptr[j] = ptr[j] ; }
+      }
+    }
+
+  template<class Schedule>
+  inline
+  typename std::enable_if< std::is_same<Schedule,Kokkos::Dynamic>::value >::type
+    execute_schedule() const
+    {
+      OpenMPexec::verify_is_process("Kokkos::OpenMP parallel_reduce");
+      OpenMPexec::verify_initialized("Kokkos::OpenMP parallel_reduce");
+
+      OpenMPexec::resize_scratch( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) , 0 );
+
+#pragma omp parallel
+      {
+        OpenMPexec & exec = * OpenMPexec::get_thread_omp();
+        const WorkRange range( m_policy, exec.pool_rank(), exec.pool_size() );
+
+        exec.set_work_range(range.begin(),range.end(),m_policy.chunk_size());
+        exec.reset_steal_target();
+        #pragma omp barrier
+
+        long work_index = exec.get_work_index();
+
+        reference_type update = ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , exec.scratch_reduce() );
+        while(work_index != -1) {
+          const Member begin = static_cast<Member>(work_index) * m_policy.chunk_size();
+          const Member end = begin + m_policy.chunk_size() < m_policy.end()?begin+m_policy.chunk_size():m_policy.end();
+          ParallelReduce::template exec_range< WorkTag >
+            ( m_functor , begin,end
+            , update );
+          work_index = exec.get_work_index();
+        }
+      }
+/* END #pragma omp parallel */
+
+      // Reduction:
+
+      const pointer_type ptr = pointer_type( OpenMPexec::pool_rev(0)->scratch_reduce() );
+
+      for ( int i = 1 ; i < OpenMPexec::pool_size() ; ++i ) {
+        ValueJoin::join( ReducerConditional::select(m_functor , m_reducer) , ptr , OpenMPexec::pool_rev(i)->scratch_reduce() );
+      }
+
+      Kokkos::Impl::FunctorFinal<  ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer) , ptr );
+
+      if ( m_result_ptr ) {
+        const int n = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer) );
+
+        for ( int j = 0 ; j < n ; ++j ) { m_result_ptr[j] = ptr[j] ; }
+      }
+    }
+
+  //----------------------------------------
+
+  template< class ViewType >
+  inline
+  ParallelReduce( const FunctorType & arg_functor
+                , Policy       arg_policy
+                , const ViewType    & arg_result_view
+                , typename std::enable_if<
+                           Kokkos::is_view< ViewType >::value &&
+                           !Kokkos::is_reducer_type<ReducerType>::value
+                  ,void*>::type = NULL)
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    , m_reducer( InvalidType() )
+    , m_result_ptr(  arg_result_view.data() )
+    {
+      /*static_assert( std::is_same< typename ViewType::memory_space
+                                      , Kokkos::HostSpace >::value
+        , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace" );*/
+    }
+
+  inline
+  ParallelReduce( const FunctorType & arg_functor
+                , Policy       arg_policy
+                , const ReducerType& reducer )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    , m_reducer( reducer )
+    , m_result_ptr(  reducer.result_view().data() )
+    {
+      /*static_assert( std::is_same< typename ViewType::memory_space
+                                      , Kokkos::HostSpace >::value
+        , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace" );*/
+    }
+
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ... Traits >
+class ParallelScan< FunctorType
+                  , Kokkos::RangePolicy< Traits ... >
+                  , Kokkos::OpenMP
+                  >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy ;
+
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::WorkRange    WorkRange ;
+  typedef typename Policy::member_type  Member ;
+
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   FunctorType, WorkTag > ValueInit ;
+  typedef Kokkos::Impl::FunctorValueJoin<   FunctorType, WorkTag > ValueJoin ;
+  typedef Kokkos::Impl::FunctorValueOps<    FunctorType, WorkTag > ValueOps ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType   m_functor ;
+  const Policy        m_policy ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend
+            , reference_type update , const bool final )
+    {
+      #ifdef KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION
+      #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+      #pragma ivdep
+      #endif
+      #endif
+      for ( Member iwork = ibeg ; iwork < iend ; ++iwork ) {
+        functor( iwork , update , final );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend
+            , reference_type update , const bool final )
+    {
+      const TagType t{} ;
+      #ifdef KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION
+      #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+      #pragma ivdep
+      #endif
+      #endif
+      for ( Member iwork = ibeg ; iwork < iend ; ++iwork ) {
+        functor( t , iwork , update , final );
+      }
+    }
+
+public:
+
+  inline
+  void execute() const
+    {
+      OpenMPexec::verify_is_process("Kokkos::OpenMP parallel_scan");
+      OpenMPexec::verify_initialized("Kokkos::OpenMP parallel_scan");
+
+      OpenMPexec::resize_scratch( 2 * ValueTraits::value_size( m_functor ) , 0 );
+
+#pragma omp parallel
+      {
+        OpenMPexec & exec = * OpenMPexec::get_thread_omp();
+        const WorkRange range( m_policy, exec.pool_rank(), exec.pool_size() );
+        const pointer_type ptr =
+          pointer_type( exec.scratch_reduce() ) +
+          ValueTraits::value_count( m_functor );
+        ParallelScan::template exec_range< WorkTag >
+          ( m_functor , range.begin() , range.end()
+          , ValueInit::init( m_functor , ptr ) , false );
+      }
+/* END #pragma omp parallel */
+
+      {
+        const unsigned thread_count = OpenMPexec::pool_size();
+        const unsigned value_count  = ValueTraits::value_count( m_functor );
+
+        pointer_type ptr_prev = 0 ;
+
+        for ( unsigned rank_rev = thread_count ; rank_rev-- ; ) {
+
+          pointer_type ptr = pointer_type( OpenMPexec::pool_rev(rank_rev)->scratch_reduce() );
+
+          if ( ptr_prev ) {
+            for ( unsigned i = 0 ; i < value_count ; ++i ) { ptr[i] = ptr_prev[ i + value_count ] ; }
+            ValueJoin::join( m_functor , ptr + value_count , ptr );
+          }
+          else {
+            ValueInit::init( m_functor , ptr );
+          }
+
+          ptr_prev = ptr ;
+        }
+      }
+
+#pragma omp parallel
+      {
+        OpenMPexec & exec = * OpenMPexec::get_thread_omp();
+        const WorkRange range( m_policy, exec.pool_rank(), exec.pool_size() );
+        const pointer_type ptr = pointer_type( exec.scratch_reduce() );
+        ParallelScan::template exec_range< WorkTag >
+          ( m_functor , range.begin() , range.end()
+          , ValueOps::reference( ptr ) , true );
+      }
+/* END #pragma omp parallel */
+    }
+
+  //----------------------------------------
+
+  inline
+  ParallelScan( const FunctorType & arg_functor
+              , const Policy      & arg_policy )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+  {}
+
+  //----------------------------------------
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ... Properties >
+class ParallelFor< FunctorType
+                 , Kokkos::TeamPolicy< Properties ... >
+                 , Kokkos::OpenMP
+                 >
+{
+private:
+
+  typedef Kokkos::Impl::TeamPolicyInternal< Kokkos::OpenMP, Properties ... > Policy ;
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::member_type  Member ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+  const int          m_shmem_size ;
+
+  template< class TagType, class Schedule >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value && std::is_same<Schedule,Kokkos::Static>::value>::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      for ( ; member.valid_static() ; member.next_static() ) {
+        functor( member );
+      }
+    }
+
+  template< class TagType, class Schedule >
+  inline static
+  typename std::enable_if< (! std::is_same< TagType , void >::value) && std::is_same<Schedule,Kokkos::Static>::value >::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      const TagType t{} ;
+      for ( ; member.valid_static() ; member.next_static() ) {
+        functor( t , member );
+      }
+    }
+
+  template< class TagType, class Schedule >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value && std::is_same<Schedule,Kokkos::Dynamic>::value>::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      #pragma omp barrier
+      for ( ; member.valid_dynamic() ; member.next_dynamic() ) {
+        functor( member );
+      }
+    }
+
+  template< class TagType, class Schedule >
+  inline static
+  typename std::enable_if< (! std::is_same< TagType , void >::value) && std::is_same<Schedule,Kokkos::Dynamic>::value >::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      #pragma omp barrier
+      const TagType t{} ;
+      for ( ; member.valid_dynamic() ; member.next_dynamic() ) {
+        functor( t , member );
+      }
+    }
+
+public:
+
+  inline
+  void execute() const
+    {
+      OpenMPexec::verify_is_process("Kokkos::OpenMP parallel_for");
+      OpenMPexec::verify_initialized("Kokkos::OpenMP parallel_for");
+
+      const size_t team_reduce_size = Policy::member_type::team_reduce_size();
+
+      OpenMPexec::resize_scratch( 0 , team_reduce_size + m_shmem_size + m_policy.scratch_size(1));
+
+#pragma omp parallel
+      {
+        ParallelFor::template exec_team< WorkTag, typename Policy::schedule_type::type>
+          ( m_functor
+          , Member( * OpenMPexec::get_thread_omp(), m_policy, m_shmem_size, 0) );
+      }
+/* END #pragma omp parallel */
+    }
+
+  inline
+  ParallelFor( const FunctorType & arg_functor ,
+               const Policy      & arg_policy )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    , m_shmem_size( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , arg_policy.team_size() ) )
+    {}
+};
+
+
+template< class FunctorType , class ReducerType, class ... Properties >
+class ParallelReduce< FunctorType
+                    , Kokkos::TeamPolicy< Properties ... >
+                    , ReducerType
+                    , Kokkos::OpenMP
+                    >
+{
+private:
+
+  typedef Kokkos::Impl::TeamPolicyInternal< Kokkos::OpenMP, Properties ... >         Policy ;
+
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::member_type  Member ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd , WorkTag >  ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd , WorkTag >  ValueInit ;
+  typedef Kokkos::Impl::FunctorValueJoin<   ReducerTypeFwd , WorkTag >  ValueJoin ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+  const ReducerType  m_reducer ;
+  const pointer_type m_result_ptr ;
+  const int          m_shmem_size ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_team( const FunctorType & functor , Member member , reference_type update )
+    {
+      for ( ; member.valid_static() ; member.next_static() ) {
+        functor( member , update );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_team( const FunctorType & functor , Member member , reference_type update )
+    {
+      const TagType t{} ;
+      for ( ; member.valid_static() ; member.next_static() ) {
+        functor( t , member , update );
+      }
+    }
+
+public:
+
+  inline
+  void execute() const
+    {
+      OpenMPexec::verify_is_process("Kokkos::OpenMP parallel_reduce");
+
+      const size_t team_reduce_size = Policy::member_type::team_reduce_size();
+
+      OpenMPexec::resize_scratch( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) , team_reduce_size + m_shmem_size );
+
+#pragma omp parallel
+      {
+        OpenMPexec & exec = * OpenMPexec::get_thread_omp();
+
+        ParallelReduce::template exec_team< WorkTag >
+          ( m_functor
+          , Member( exec , m_policy , m_shmem_size, 0 )
+          , ValueInit::init( ReducerConditional::select(m_functor , m_reducer) , exec.scratch_reduce() ) );
+      }
+/* END #pragma omp parallel */
+
+      {
+        const pointer_type ptr = pointer_type( OpenMPexec::pool_rev(0)->scratch_reduce() );
+
+        int max_active_threads = OpenMPexec::pool_size();
+        if( max_active_threads > m_policy.league_size()* m_policy.team_size() )
+          max_active_threads = m_policy.league_size()* m_policy.team_size();
+
+        for ( int i = 1 ; i < max_active_threads ; ++i ) {
+          ValueJoin::join( ReducerConditional::select(m_functor , m_reducer) , ptr , OpenMPexec::pool_rev(i)->scratch_reduce() );
+        }
+
+        Kokkos::Impl::FunctorFinal< ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer) , ptr );
+
+        if ( m_result_ptr ) {
+          const int n = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer) );
+
+          for ( int j = 0 ; j < n ; ++j ) { m_result_ptr[j] = ptr[j] ; }
+        }
+      }
+    }
+
+  template< class ViewType >
+  inline
+  ParallelReduce( const FunctorType  & arg_functor ,
+                  const Policy       & arg_policy ,
+                  const ViewType     & arg_result ,
+                  typename std::enable_if<
+                    Kokkos::is_view< ViewType >::value &&
+                    !Kokkos::is_reducer_type<ReducerType>::value
+                    ,void*>::type = NULL)
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    , m_reducer( InvalidType() )
+    , m_result_ptr( arg_result.ptr_on_device() )
+    , m_shmem_size( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , arg_policy.team_size() ) )
+    {}
+
+  inline
+  ParallelReduce( const FunctorType & arg_functor
+    , Policy       arg_policy
+    , const ReducerType& reducer )
+  : m_functor( arg_functor )
+  , m_policy(  arg_policy )
+  , m_reducer( reducer )
+  , m_result_ptr(  reducer.result_view().data() )
+  , m_shmem_size( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , arg_policy.team_size() ) )
+  {
+  /*static_assert( std::is_same< typename ViewType::memory_space
+                          , Kokkos::HostSpace >::value
+  , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace" );*/
+  }
+
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* KOKKOS_OPENMP_PARALLEL_HPP */
+
diff --git a/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Task.cpp b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Task.cpp
new file mode 100644
index 0000000000..3e22033f7c
--- /dev/null
+++ b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Task.cpp
@@ -0,0 +1,329 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_OPENMP ) && defined( KOKKOS_ENABLE_TASKPOLICY )
+
+#include <impl/Kokkos_TaskQueue_impl.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template class TaskQueue< Kokkos::OpenMP > ;
+
+//----------------------------------------------------------------------------
+
+TaskExec< Kokkos::OpenMP >::
+TaskExec()
+  : m_self_exec( 0 )
+  , m_team_exec( 0 )
+  , m_sync_mask( 0 )
+  , m_sync_value( 0 )
+  , m_sync_step( 0 )
+  , m_group_rank( 0 )
+  , m_team_rank( 0 )
+  , m_team_size( 1 )
+{
+}
+
+TaskExec< Kokkos::OpenMP >::
+TaskExec( Kokkos::Impl::OpenMPexec & arg_exec , int const arg_team_size )
+  : m_self_exec( & arg_exec )
+  , m_team_exec( arg_exec.pool_rev(arg_exec.pool_rank_rev() / arg_team_size) )
+  , m_sync_mask( 0 )
+  , m_sync_value( 0 )
+  , m_sync_step( 0 )
+  , m_group_rank( arg_exec.pool_rank_rev() / arg_team_size )
+  , m_team_rank(  arg_exec.pool_rank_rev() % arg_team_size )
+  , m_team_size(  arg_team_size )
+{
+  // This team spans
+  //    m_self_exec->pool_rev( team_size * group_rank )
+  //    m_self_exec->pool_rev( team_size * ( group_rank + 1 ) - 1 )
+
+  int64_t volatile * const sync = (int64_t *) m_self_exec->scratch_reduce();
+
+  sync[0] = int64_t(0) ;
+  sync[1] = int64_t(0) ;
+
+  for ( int i = 0 ; i < m_team_size ; ++i ) {
+    m_sync_value |= int64_t(1) << (8*i);
+    m_sync_mask  |= int64_t(3) << (8*i);
+  }
+
+  Kokkos::memory_fence();
+}
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+
+void TaskExec< Kokkos::OpenMP >::team_barrier_impl() const
+{
+  if ( m_team_exec->scratch_reduce_size() < int(2 * sizeof(int64_t)) ) {
+    Kokkos::abort("TaskQueue<OpenMP> scratch_reduce memory too small");
+  }
+
+  // Use team shared memory to synchronize.
+  // Alternate memory locations between barriers to avoid a sequence
+  // of barriers overtaking one another.
+
+  int64_t volatile * const sync =
+    ((int64_t *) m_team_exec->scratch_reduce()) + ( m_sync_step & 0x01 );
+
+  // This team member sets one byte within the sync variable
+  int8_t volatile * const sync_self =
+   ((int8_t *) sync) + m_team_rank ;
+
+#if 0
+fprintf( stdout
+       , "barrier group(%d) member(%d) step(%d) wait(%lx) : before(%lx)\n"
+       , m_group_rank
+       , m_team_rank
+       , m_sync_step
+       , m_sync_value
+       , *sync
+       );
+fflush(stdout);
+#endif
+
+  *sync_self = int8_t( m_sync_value & 0x03 ); // signal arrival
+
+  while ( m_sync_value != *sync ); // wait for team to arrive
+
+#if 0
+fprintf( stdout
+       , "barrier group(%d) member(%d) step(%d) wait(%lx) : after(%lx)\n"
+       , m_group_rank
+       , m_team_rank
+       , m_sync_step
+       , m_sync_value
+       , *sync
+       );
+fflush(stdout);
+#endif
+
+  ++m_sync_step ;
+
+  if ( 0 == ( 0x01 & m_sync_step ) ) { // Every other step
+    m_sync_value ^= m_sync_mask ;
+    if ( 1000 < m_sync_step ) m_sync_step = 0 ;
+  }
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+
+void TaskQueueSpecialization< Kokkos::OpenMP >::execute
+  ( TaskQueue< Kokkos::OpenMP > * const queue )
+{
+  using execution_space = Kokkos::OpenMP ;
+  using queue_type      = TaskQueue< execution_space > ;
+  using task_root_type  = TaskBase< execution_space , void , void > ;
+  using PoolExec        = Kokkos::Impl::OpenMPexec ;
+  using Member          = TaskExec< execution_space > ;
+
+  task_root_type * const end = (task_root_type *) task_root_type::EndTag ;
+
+  // Required:  team_size <= 8
+
+  const int team_size = PoolExec::pool_size(2); // Threads per core
+  // const int team_size = PoolExec::pool_size(1); // Threads per NUMA
+
+  if ( 8 < team_size ) {
+    Kokkos::abort("TaskQueue<OpenMP> unsupported team size");
+  }
+
+#pragma omp parallel
+  {
+    PoolExec & self = *PoolExec::get_thread_omp();
+
+    Member single_exec ;
+    Member team_exec( self , team_size );
+
+    // Team shared memory
+    task_root_type * volatile * const task_shared =
+      (task_root_type **) team_exec.m_team_exec->scratch_thread();
+
+// Barrier across entire OpenMP thread pool to insure initialization
+#pragma omp barrier
+
+    // Loop until all queues are empty and no tasks in flight
+
+    do {
+
+      task_root_type * task = 0 ;
+
+      // Each team lead attempts to acquire either a thread team task
+      // or a single thread task for the team.
+
+      if ( 0 == team_exec.team_rank() ) {
+
+        task = 0 < *((volatile int *) & queue->m_ready_count) ? end : 0 ;
+
+        // Loop by priority and then type
+        for ( int i = 0 ; i < queue_type::NumQueue && end == task ; ++i ) {
+          for ( int j = 0 ; j < 2 && end == task ; ++j ) {
+            task = queue_type::pop_task( & queue->m_ready[i][j] );
+          }
+        }
+      }
+
+      // Team lead broadcast acquired task to team members:
+
+      if ( 1 < team_exec.team_size() ) {
+
+        if ( 0 == team_exec.team_rank() ) *task_shared = task ;
+
+        // Fence to be sure task_shared is stored before the barrier
+        Kokkos::memory_fence();
+
+        // Whole team waits for every team member to reach this statement
+        team_exec.team_barrier();
+
+        // Fence to be sure task_shared is stored
+        Kokkos::memory_fence();
+
+        task = *task_shared ;
+      }
+
+#if 0
+fprintf( stdout
+       , "\nexecute group(%d) member(%d) task_shared(0x%lx) task(0x%lx)\n"
+       , team_exec.m_group_rank
+       , team_exec.m_team_rank
+       , uintptr_t(task_shared)
+       , uintptr_t(task)
+       );
+fflush(stdout);
+#endif
+
+      if ( 0 == task ) break ; // 0 == m_ready_count
+
+      if ( end == task ) {
+        // All team members wait for whole team to reach this statement.
+        // Is necessary to prevent task_shared from being updated
+        // before it is read by all threads.
+        team_exec.team_barrier();
+      }
+      else if ( task_root_type::TaskTeam == task->m_task_type ) {
+        // Thread Team Task
+        (*task->m_apply)( task , & team_exec );
+
+        // The m_apply function performs a barrier
+
+        if ( 0 == team_exec.team_rank() ) {
+          // team member #0 completes the task, which may delete the task
+          queue->complete( task ); 
+        }
+      }
+      else {
+        // Single Thread Task
+
+        if ( 0 == team_exec.team_rank() ) {
+
+          (*task->m_apply)( task , & single_exec );
+
+          queue->complete( task ); 
+        }
+
+        // All team members wait for whole team to reach this statement.
+        // Not necessary to complete the task.
+        // Is necessary to prevent task_shared from being updated
+        // before it is read by all threads.
+        team_exec.team_barrier();
+      }
+    } while(1);
+  }
+// END #pragma omp parallel
+
+}
+
+void TaskQueueSpecialization< Kokkos::OpenMP >::
+  iff_single_thread_recursive_execute
+    ( TaskQueue< Kokkos::OpenMP > * const queue )
+{
+  using execution_space = Kokkos::OpenMP ;
+  using queue_type      = TaskQueue< execution_space > ;
+  using task_root_type  = TaskBase< execution_space , void , void > ;
+  using Member          = TaskExec< execution_space > ;
+
+  if ( 1 == omp_get_num_threads() ) {
+
+    task_root_type * const end = (task_root_type *) task_root_type::EndTag ;
+
+    Member single_exec ;
+
+    task_root_type * task = end ;
+
+    do {
+
+      task = end ;
+
+      // Loop by priority and then type
+      for ( int i = 0 ; i < queue_type::NumQueue && end == task ; ++i ) {
+        for ( int j = 0 ; j < 2 && end == task ; ++j ) {
+          task = queue_type::pop_task( & queue->m_ready[i][j] );
+        }
+      }
+
+      if ( end == task ) break ;
+
+      (*task->m_apply)( task , & single_exec );
+
+      queue->complete( task ); 
+
+    } while(1);
+  }
+}
+
+}} /* namespace Kokkos::Impl */
+
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_OPENMP ) && defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
+
diff --git a/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Task.hpp b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Task.hpp
new file mode 100644
index 0000000000..2761247c40
--- /dev/null
+++ b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMP_Task.hpp
@@ -0,0 +1,356 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_IMPL_OPENMP_TASK_HPP
+#define KOKKOS_IMPL_OPENMP_TASK_HPP
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+class TaskQueueSpecialization< Kokkos::OpenMP >
+{
+public:
+
+  using execution_space = Kokkos::OpenMP ;
+  using queue_type      = Kokkos::Impl::TaskQueue< execution_space > ;
+  using task_base_type  = Kokkos::Impl::TaskBase< execution_space , void , void > ;
+
+  // Must specify memory space
+  using memory_space = Kokkos::HostSpace ;
+
+  static
+  void iff_single_thread_recursive_execute( queue_type * const );
+
+  // Must provide task queue execution function
+  static void execute( queue_type * const );
+
+  // Must provide mechanism to set function pointer in
+  // execution space from the host process.
+  template< typename FunctorType >
+  static
+  void proc_set_apply( task_base_type::function_type * ptr )
+    {
+      using TaskType = TaskBase< Kokkos::OpenMP
+                               , typename FunctorType::value_type
+                               , FunctorType
+                               > ;
+       *ptr = TaskType::apply ;
+    }
+};
+
+extern template class TaskQueue< Kokkos::OpenMP > ;
+
+//----------------------------------------------------------------------------
+
+template<>
+class TaskExec< Kokkos::OpenMP >
+{
+private:
+
+  TaskExec( TaskExec && ) = delete ;
+  TaskExec( TaskExec const & ) = delete ;
+  TaskExec & operator = ( TaskExec && ) = delete ;
+  TaskExec & operator = ( TaskExec const & ) = delete ;
+
+
+  using PoolExec = Kokkos::Impl::OpenMPexec ;
+
+  friend class Kokkos::Impl::TaskQueue< Kokkos::OpenMP > ;
+  friend class Kokkos::Impl::TaskQueueSpecialization< Kokkos::OpenMP > ;
+
+  PoolExec * const m_self_exec ;  ///< This thread's thread pool data structure 
+  PoolExec * const m_team_exec ;  ///< Team thread's thread pool data structure
+  int64_t          m_sync_mask ;
+  int64_t mutable  m_sync_value ;
+  int     mutable  m_sync_step ;
+  int              m_group_rank ; ///< Which "team" subset of thread pool
+  int              m_team_rank ;  ///< Which thread within a team
+  int              m_team_size ;
+
+  TaskExec();
+  TaskExec( PoolExec & arg_exec , int arg_team_size );
+
+  void team_barrier_impl() const ;
+
+public:
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+  void * team_shared() const
+    { return m_team_exec ? m_team_exec->scratch_thread() : (void*) 0 ; }
+
+  int team_shared_size() const
+    { return m_team_exec ? m_team_exec->scratch_thread_size() : 0 ; }
+
+  /**\brief  Whole team enters this function call
+   *         before any teeam member returns from
+   *         this function call.
+   */
+  void team_barrier() const { if ( 1 < m_team_size ) team_barrier_impl(); }
+#else
+  KOKKOS_INLINE_FUNCTION void team_barrier() const {}
+  KOKKOS_INLINE_FUNCTION void * team_shared() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION int team_shared_size() const { return 0 ; }
+#endif
+
+  KOKKOS_INLINE_FUNCTION
+  int team_rank() const { return m_team_rank ; }
+
+  KOKKOS_INLINE_FUNCTION
+  int team_size() const { return m_team_size ; }
+};
+
+}} /* namespace Kokkos::Impl */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::OpenMP > >
+TeamThreadRange
+  ( Impl::TaskExec< Kokkos::OpenMP > & thread
+  , const iType & count )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::OpenMP > >(thread,count);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::OpenMP > >
+TeamThreadRange
+  ( Impl:: TaskExec< Kokkos::OpenMP > & thread
+  , const iType & start
+  , const iType & end )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::OpenMP > >(thread,start,end);
+}
+
+/** \brief  Inter-thread parallel_for. Executes lambda(iType i) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all threads of the the calling thread team.
+ * This functionality requires C++11 support.
+*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for
+  ( const Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::OpenMP > >& loop_boundaries
+  , const Lambda& lambda
+  )
+{
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i);
+  }
+}
+
+template<typename iType, class Lambda, typename ValueType>
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  ( const Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::OpenMP > >& loop_boundaries
+  , const Lambda& lambda
+  , ValueType& initialized_result)
+{
+  int team_rank = loop_boundaries.thread.team_rank(); // member num within the team
+  ValueType result = initialized_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i, result);
+  }
+
+  if ( 1 < loop_boundaries.thread.team_size() ) {
+
+    ValueType *shared = (ValueType*) loop_boundaries.thread.team_shared();
+
+    loop_boundaries.thread.team_barrier();
+    shared[team_rank] = result;
+
+    loop_boundaries.thread.team_barrier();
+
+    // reduce across threads to thread 0
+    if (team_rank == 0) {
+      for (int i = 1; i < loop_boundaries.thread.team_size(); i++) {
+        shared[0] += shared[i];
+      }
+    }
+
+    loop_boundaries.thread.team_barrier();
+
+    // broadcast result
+    initialized_result = shared[0];
+  }
+  else {
+    initialized_result = result ;
+  }
+}
+
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::OpenMP > >& loop_boundaries,
+   const Lambda & lambda,
+   const JoinType & join,
+   ValueType& initialized_result)
+{
+  int team_rank = loop_boundaries.thread.team_rank(); // member num within the team
+  ValueType result = initialized_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i, result);
+  }
+
+  if ( 1 < loop_boundaries.thread.team_size() ) {
+    ValueType *shared = (ValueType*) loop_boundaries.thread.team_shared();
+
+    loop_boundaries.thread.team_barrier();
+    shared[team_rank] = result;
+
+    loop_boundaries.thread.team_barrier();
+
+    // reduce across threads to thread 0
+    if (team_rank == 0) {
+      for (int i = 1; i < loop_boundaries.thread.team_size(); i++) {
+        join(shared[0], shared[i]);
+      }
+    }
+
+    loop_boundaries.thread.team_barrier();
+
+    // broadcast result
+    initialized_result = shared[0];
+  }
+  else {
+    initialized_result = result ;
+  }
+}
+
+// placeholder for future function
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::OpenMP > >& loop_boundaries,
+   const Lambda & lambda,
+   ValueType& initialized_result)
+{
+}
+
+// placeholder for future function
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::OpenMP > >& loop_boundaries,
+   const Lambda & lambda,
+   const JoinType & join,
+   ValueType& initialized_result)
+{
+}
+
+template< typename ValueType, typename iType, class Lambda >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan
+  (const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::OpenMP > >& loop_boundaries,
+   const Lambda & lambda)
+{
+  ValueType accum = 0 ;
+  ValueType val, local_total;
+  ValueType *shared = (ValueType*) loop_boundaries.thread.team_shared();
+  int team_size = loop_boundaries.thread.team_size();
+  int team_rank = loop_boundaries.thread.team_rank(); // member num within the team
+
+  // Intra-member scan
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    local_total = 0;
+    lambda(i,local_total,false);
+    val = accum;
+    lambda(i,val,true);
+    accum += local_total;
+  }
+
+  shared[team_rank] = accum;
+  loop_boundaries.thread.team_barrier();
+
+  // Member 0 do scan on accumulated totals
+  if (team_rank == 0) {
+    for( iType i = 1; i < team_size; i+=1) {
+      shared[i] += shared[i-1];
+    }
+    accum = 0; // Member 0 set accum to 0 in preparation for inter-member scan
+  }
+
+  loop_boundaries.thread.team_barrier();
+
+  // Inter-member scan adding in accumulated totals
+  if (team_rank != 0) { accum = shared[team_rank-1]; }
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    local_total = 0;
+    lambda(i,local_total,false);
+    val = accum;
+    lambda(i,val,true);
+    accum += local_total;
+  }
+}
+
+// placeholder for future function
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::OpenMP > >& loop_boundaries,
+   const Lambda & lambda)
+{
+}
+
+
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #ifndef KOKKOS_IMPL_OPENMP_TASK_HPP */
+
diff --git a/lib/kokkos/core/src/OpenMP/Kokkos_OpenMPexec.cpp b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMPexec.cpp
new file mode 100644
index 0000000000..7d06a2f661
--- /dev/null
+++ b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMPexec.cpp
@@ -0,0 +1,408 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdio.h>
+#include <limits>
+#include <iostream>
+#include <vector>
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <iostream>
+#include <impl/Kokkos_CPUDiscovery.hpp>
+#include <impl/Kokkos_Profiling_Interface.hpp>
+
+#ifdef KOKKOS_HAVE_OPENMP
+
+namespace Kokkos {
+namespace Impl {
+namespace {
+
+KOKKOS_INLINE_FUNCTION
+int kokkos_omp_in_parallel();
+
+int kokkos_omp_in_critical_region = ( Kokkos::HostSpace::register_in_parallel( kokkos_omp_in_parallel ) , 0 );
+
+KOKKOS_INLINE_FUNCTION
+int kokkos_omp_in_parallel()
+{
+#ifndef __CUDA_ARCH__
+  return omp_in_parallel() && ! kokkos_omp_in_critical_region ;
+#else
+  return 0;
+#endif
+}
+
+bool s_using_hwloc = false;
+
+} // namespace
+} // namespace Impl
+} // namespace Kokkos
+
+
+namespace Kokkos {
+namespace Impl {
+
+int OpenMPexec::m_map_rank[ OpenMPexec::MAX_THREAD_COUNT ] = { 0 };
+
+int OpenMPexec::m_pool_topo[ 4 ] = { 0 };
+
+OpenMPexec * OpenMPexec::m_pool[ OpenMPexec::MAX_THREAD_COUNT ] = { 0 };
+
+void OpenMPexec::verify_is_process( const char * const label )
+{
+  if ( omp_in_parallel() ) {
+    std::string msg( label );
+    msg.append( " ERROR: in parallel" );
+    Kokkos::Impl::throw_runtime_exception( msg );
+  }
+}
+
+void OpenMPexec::verify_initialized( const char * const label )
+{
+  if ( 0 == m_pool[0] ) {
+    std::string msg( label );
+    msg.append( " ERROR: not initialized" );
+    Kokkos::Impl::throw_runtime_exception( msg );
+  }
+
+  if ( omp_get_max_threads() != Kokkos::OpenMP::thread_pool_size(0) ) {
+    std::string msg( label );
+    msg.append( " ERROR: Initialized but threads modified inappropriately" );
+    Kokkos::Impl::throw_runtime_exception( msg );
+  }
+
+}
+
+void OpenMPexec::clear_scratch()
+{
+#pragma omp parallel
+  {
+    const int rank_rev = m_map_rank[ omp_get_thread_num() ];
+    typedef Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::HostSpace , void > Record ;
+    if ( m_pool[ rank_rev ] ) {
+      Record * const r = Record::get_record( m_pool[ rank_rev ] );
+      m_pool[ rank_rev ] = 0 ;
+      Record::decrement( r );
+    }
+  }
+/* END #pragma omp parallel */
+}
+
+void OpenMPexec::resize_scratch( size_t reduce_size , size_t thread_size )
+{
+  enum { ALIGN_MASK = Kokkos::Impl::MEMORY_ALIGNMENT - 1 };
+  enum { ALLOC_EXEC = ( sizeof(OpenMPexec) + ALIGN_MASK ) & ~ALIGN_MASK };
+
+  const size_t old_reduce_size = m_pool[0] ? m_pool[0]->m_scratch_reduce_end : 0 ;
+  const size_t old_thread_size = m_pool[0] ? m_pool[0]->m_scratch_thread_end - m_pool[0]->m_scratch_reduce_end : 0 ;
+
+  reduce_size = ( reduce_size + ALIGN_MASK ) & ~ALIGN_MASK ;
+  thread_size = ( thread_size + ALIGN_MASK ) & ~ALIGN_MASK ;
+
+  // Requesting allocation and old allocation is too small:
+
+  const bool allocate = ( old_reduce_size < reduce_size ) ||
+                        ( old_thread_size < thread_size );
+
+  if ( allocate ) {
+    if ( reduce_size < old_reduce_size ) { reduce_size = old_reduce_size ; }
+    if ( thread_size < old_thread_size ) { thread_size = old_thread_size ; }
+  }
+
+  const size_t alloc_size = allocate ? ALLOC_EXEC + reduce_size + thread_size : 0 ;
+  const int    pool_size  = m_pool_topo[0] ;
+
+  if ( allocate ) {
+
+    clear_scratch();
+
+#pragma omp parallel
+    {
+      const int rank_rev = m_map_rank[ omp_get_thread_num() ];
+      const int rank     = pool_size - ( rank_rev + 1 );
+
+      typedef Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::HostSpace , void > Record ;
+
+      Record * const r = Record::allocate( Kokkos::HostSpace()
+                                         , "openmp_scratch"
+                                         , alloc_size );
+
+      Record::increment( r );
+
+      m_pool[ rank_rev ] = reinterpret_cast<OpenMPexec*>( r->data() );
+
+      new ( m_pool[ rank_rev ] ) OpenMPexec( rank , ALLOC_EXEC , reduce_size , thread_size );
+    }
+/* END #pragma omp parallel */
+  }
+}
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+int OpenMP::is_initialized()
+{ return 0 != Impl::OpenMPexec::m_pool[0]; }
+
+void OpenMP::initialize( unsigned thread_count ,
+                         unsigned use_numa_count ,
+                         unsigned use_cores_per_numa )
+{
+  // Before any other call to OMP query the maximum number of threads
+  // and save the value for re-initialization unit testing.
+
+  //Using omp_get_max_threads(); is problematic in conjunction with
+  //Hwloc on Intel (essentially an initial call to the OpenMP runtime
+  //without a parallel region before will set a process mask for a single core
+  //The runtime will than bind threads for a parallel region to other cores on the
+  //entering the first parallel region and make the process mask the aggregate of
+  //the thread masks. The intend seems to be to make serial code run fast, if you
+  //compile with OpenMP enabled but don't actually use parallel regions or so
+  //static int omp_max_threads = omp_get_max_threads();
+  int nthreads = 0;
+  #pragma omp parallel
+  {
+    #pragma omp atomic
+    nthreads++;
+  }
+
+  static int omp_max_threads = nthreads;
+
+  const bool is_initialized = 0 != Impl::OpenMPexec::m_pool[0] ;
+
+  bool thread_spawn_failed = false ;
+
+  if ( ! is_initialized ) {
+
+    // Use hwloc thread pinning if concerned with locality.
+    // If spreading threads across multiple NUMA regions.
+    // If hyperthreading is enabled.
+    Impl::s_using_hwloc = hwloc::available() && (
+                            ( 1 < Kokkos::hwloc::get_available_numa_count() ) ||
+                            ( 1 < Kokkos::hwloc::get_available_threads_per_core() ) );
+
+    std::pair<unsigned,unsigned> threads_coord[ Impl::OpenMPexec::MAX_THREAD_COUNT ];
+
+    // If hwloc available then use it's maximum value.
+
+    if ( thread_count == 0 ) {
+      thread_count = Impl::s_using_hwloc
+      ? Kokkos::hwloc::get_available_numa_count() *
+        Kokkos::hwloc::get_available_cores_per_numa() *
+        Kokkos::hwloc::get_available_threads_per_core()
+      : omp_max_threads ;
+    }
+
+    if(Impl::s_using_hwloc)
+      hwloc::thread_mapping( "Kokkos::OpenMP::initialize" ,
+                           false /* do not allow asynchronous */ ,
+                           thread_count ,
+                           use_numa_count ,
+                           use_cores_per_numa ,
+                           threads_coord );
+
+    // Spawn threads:
+
+    omp_set_num_threads( thread_count );
+
+    // Verify OMP interaction:
+    if ( int(thread_count) != omp_get_max_threads() ) {
+      thread_spawn_failed = true ;
+    }
+
+    // Verify spawning and bind threads:
+#pragma omp parallel
+    {
+#pragma omp critical
+      {
+        if ( int(thread_count) != omp_get_num_threads() ) {
+          thread_spawn_failed = true ;
+        }
+
+        // Call to 'bind_this_thread' is not thread safe so place this whole block in a critical region.
+        // Call to 'new' may not be thread safe as well.
+
+        // Reverse the rank for threads so that the scan operation reduces to the highest rank thread.
+
+        const unsigned omp_rank    = omp_get_thread_num();
+        const unsigned thread_r    = Impl::s_using_hwloc && Kokkos::hwloc::can_bind_threads()
+                                   ? Kokkos::hwloc::bind_this_thread( thread_count , threads_coord )
+                                   : omp_rank ;
+
+        Impl::OpenMPexec::m_map_rank[ omp_rank ] = thread_r ;
+      }
+/* END #pragma omp critical */
+    }
+/* END #pragma omp parallel */
+
+    if ( ! thread_spawn_failed ) {
+      Impl::OpenMPexec::m_pool_topo[0] = thread_count ;
+      Impl::OpenMPexec::m_pool_topo[1] = Impl::s_using_hwloc ? thread_count / use_numa_count : thread_count;
+      Impl::OpenMPexec::m_pool_topo[2] = Impl::s_using_hwloc ? thread_count / ( use_numa_count * use_cores_per_numa ) : 1;
+
+      Impl::OpenMPexec::resize_scratch( 1024 , 1024 );
+    }
+  }
+
+  if ( is_initialized || thread_spawn_failed ) {
+    std::string msg("Kokkos::OpenMP::initialize ERROR");
+
+    if ( is_initialized ) { msg.append(" : already initialized"); }
+    if ( thread_spawn_failed ) { msg.append(" : failed spawning threads"); }
+
+    Kokkos::Impl::throw_runtime_exception(msg);
+  }
+
+  // Check for over-subscription
+  if( Impl::mpi_ranks_per_node() * long(thread_count) > Impl::processors_per_node() ) {
+    std::cout << "Kokkos::OpenMP::initialize WARNING: You are likely oversubscribing your CPU cores." << std::endl;
+    std::cout << "                                    Detected: " << Impl::processors_per_node() << " cores per node." << std::endl;
+    std::cout << "                                    Detected: " << Impl::mpi_ranks_per_node() << " MPI_ranks per node." << std::endl;
+    std::cout << "                                    Requested: " << thread_count << " threads per process." << std::endl;
+  }
+  // Init the array for used for arbitrarily sized atomics
+  Impl::init_lock_array_host_space();
+
+  #if (KOKKOS_ENABLE_PROFILING)
+    Kokkos::Profiling::initialize();
+  #endif
+}
+
+//----------------------------------------------------------------------------
+
+void OpenMP::finalize()
+{
+  Impl::OpenMPexec::verify_initialized( "OpenMP::finalize" );
+  Impl::OpenMPexec::verify_is_process( "OpenMP::finalize" );
+
+  Impl::OpenMPexec::clear_scratch();
+
+  Impl::OpenMPexec::m_pool_topo[0] = 0 ;
+  Impl::OpenMPexec::m_pool_topo[1] = 0 ;
+  Impl::OpenMPexec::m_pool_topo[2] = 0 ;
+
+  omp_set_num_threads(1);
+
+  if ( Impl::s_using_hwloc && Kokkos::hwloc::can_bind_threads() ) {
+    hwloc::unbind_this_thread();
+  }
+
+  #if (KOKKOS_ENABLE_PROFILING)
+    Kokkos::Profiling::finalize();
+  #endif
+}
+
+//----------------------------------------------------------------------------
+
+void OpenMP::print_configuration( std::ostream & s , const bool detail )
+{
+  Impl::OpenMPexec::verify_is_process( "OpenMP::print_configuration" );
+
+  s << "Kokkos::OpenMP" ;
+
+#if defined( KOKKOS_HAVE_OPENMP )
+  s << " KOKKOS_HAVE_OPENMP" ;
+#endif
+#if defined( KOKKOS_HAVE_HWLOC )
+
+  const unsigned numa_count_       = Kokkos::hwloc::get_available_numa_count();
+  const unsigned cores_per_numa   = Kokkos::hwloc::get_available_cores_per_numa();
+  const unsigned threads_per_core = Kokkos::hwloc::get_available_threads_per_core();
+
+  s << " hwloc[" << numa_count_ << "x" << cores_per_numa << "x" << threads_per_core << "]"
+    << " hwloc_binding_" << ( Impl::s_using_hwloc ? "enabled" : "disabled" )
+    ;
+#endif
+
+  const bool is_initialized = 0 != Impl::OpenMPexec::m_pool[0] ;
+
+  if ( is_initialized ) {
+    const int numa_count      = Kokkos::Impl::OpenMPexec::m_pool_topo[0] / Kokkos::Impl::OpenMPexec::m_pool_topo[1] ;
+    const int core_per_numa   = Kokkos::Impl::OpenMPexec::m_pool_topo[1] / Kokkos::Impl::OpenMPexec::m_pool_topo[2] ;
+    const int thread_per_core = Kokkos::Impl::OpenMPexec::m_pool_topo[2] ;
+
+    s << " thread_pool_topology[ " << numa_count
+      << " x " << core_per_numa
+      << " x " << thread_per_core
+      << " ]"
+      << std::endl ;
+
+    if ( detail ) {
+      std::vector< std::pair<unsigned,unsigned> > coord( Kokkos::Impl::OpenMPexec::m_pool_topo[0] );
+
+#pragma omp parallel
+      {
+#pragma omp critical
+        {
+          coord[ omp_get_thread_num() ] = hwloc::get_this_thread_coordinate();
+        }
+/* END #pragma omp critical */
+      }
+/* END #pragma omp parallel */
+
+      for ( unsigned i = 0 ; i < coord.size() ; ++i ) {
+        s << "  thread omp_rank[" << i << "]"
+          << " kokkos_rank[" << Impl::OpenMPexec::m_map_rank[ i ] << "]"
+          << " hwloc_coord[" << coord[i].first << "." << coord[i].second << "]"
+          << std::endl ;
+      }
+    }
+  }
+  else {
+    s << " not initialized" << std::endl ;
+  }
+}
+
+int OpenMP::concurrency() {
+  return thread_pool_size(0);
+}
+
+} // namespace Kokkos
+
+#endif //KOKKOS_HAVE_OPENMP
diff --git a/lib/kokkos/core/src/OpenMP/Kokkos_OpenMPexec.hpp b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMPexec.hpp
new file mode 100644
index 0000000000..a01c9cb644
--- /dev/null
+++ b/lib/kokkos/core/src/OpenMP/Kokkos_OpenMPexec.hpp
@@ -0,0 +1,1083 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_OPENMPEXEC_HPP
+#define KOKKOS_OPENMPEXEC_HPP
+
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_spinwait.hpp>
+
+#include <Kokkos_Atomic.hpp>
+#include <iostream>
+#include <sstream>
+#include <fstream>
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+/** \brief  Data for OpenMP thread execution */
+
+class OpenMPexec {
+public:
+
+  enum { MAX_THREAD_COUNT = 4096 };
+
+private:
+
+  static OpenMPexec * m_pool[ MAX_THREAD_COUNT ]; // Indexed by: m_pool_rank_rev
+
+  static int          m_pool_topo[ 4 ];
+  static int          m_map_rank[ MAX_THREAD_COUNT ];
+
+  friend class Kokkos::OpenMP ;
+
+  int const  m_pool_rank ;
+  int const  m_pool_rank_rev ;
+  int const  m_scratch_exec_end ;
+  int const  m_scratch_reduce_end ;
+  int const  m_scratch_thread_end ;
+
+  int volatile  m_barrier_state ;
+
+  // Members for dynamic scheduling
+  // Which thread am I stealing from currently
+  int m_current_steal_target;
+  // This thread's owned work_range
+  Kokkos::pair<long,long> m_work_range KOKKOS_ALIGN_16;
+  // Team Offset if one thread determines work_range for others
+  long m_team_work_index;
+
+  // Is this thread stealing (i.e. its owned work_range is exhausted
+  bool m_stealing;
+
+  OpenMPexec();
+  OpenMPexec( const OpenMPexec & );
+  OpenMPexec & operator = ( const OpenMPexec & );
+
+  static void clear_scratch();
+
+public:
+
+  // Topology of a cache coherent thread pool:
+  //   TOTAL = NUMA x GRAIN
+  //   pool_size( depth = 0 )
+  //   pool_size(0) = total number of threads
+  //   pool_size(1) = number of threads per NUMA
+  //   pool_size(2) = number of threads sharing finest grain memory hierarchy
+
+  inline static
+  int pool_size( int depth = 0 ) { return m_pool_topo[ depth ]; }
+
+  inline static
+  OpenMPexec * pool_rev( int pool_rank_rev ) { return m_pool[ pool_rank_rev ]; }
+
+  inline int pool_rank() const { return m_pool_rank ; }
+  inline int pool_rank_rev() const { return m_pool_rank_rev ; }
+
+  inline long team_work_index() const { return m_team_work_index ; }
+
+  inline int scratch_reduce_size() const
+    { return m_scratch_reduce_end - m_scratch_exec_end ; }
+
+  inline int scratch_thread_size() const
+    { return m_scratch_thread_end - m_scratch_reduce_end ; }
+
+  inline void * scratch_reduce() const { return ((char *) this) + m_scratch_exec_end ; }
+  inline void * scratch_thread() const { return ((char *) this) + m_scratch_reduce_end ; }
+
+  inline
+  void state_wait( int state )
+    { Impl::spinwait( m_barrier_state , state ); }
+
+  inline
+  void state_set( int state ) { m_barrier_state = state ; }
+
+  ~OpenMPexec() {}
+
+  OpenMPexec( const int arg_poolRank
+            , const int arg_scratch_exec_size
+            , const int arg_scratch_reduce_size
+            , const int arg_scratch_thread_size )
+    : m_pool_rank( arg_poolRank )
+    , m_pool_rank_rev( pool_size() - ( arg_poolRank + 1 ) )
+    , m_scratch_exec_end( arg_scratch_exec_size )
+    , m_scratch_reduce_end( m_scratch_exec_end   + arg_scratch_reduce_size )
+    , m_scratch_thread_end( m_scratch_reduce_end + arg_scratch_thread_size )
+    , m_barrier_state(0)
+    {}
+
+  static void finalize();
+
+  static void initialize( const unsigned  team_count ,
+                          const unsigned threads_per_team ,
+                          const unsigned numa_count ,
+                          const unsigned cores_per_numa );
+
+  static void verify_is_process( const char * const );
+  static void verify_initialized( const char * const );
+
+  static void resize_scratch( size_t reduce_size , size_t thread_size );
+
+  inline static
+  OpenMPexec * get_thread_omp() { return m_pool[ m_map_rank[ omp_get_thread_num() ] ]; }
+
+  /* Dynamic Scheduling related functionality */
+  // Initialize the work range for this thread
+  inline void set_work_range(const long& begin, const long& end, const long& chunk_size) {
+    m_work_range.first = (begin+chunk_size-1)/chunk_size;
+    m_work_range.second = end>0?(end+chunk_size-1)/chunk_size:m_work_range.first;
+  }
+
+  // Claim and index from this thread's range from the beginning
+  inline long get_work_index_begin () {
+    Kokkos::pair<long,long> work_range_new = m_work_range;
+    Kokkos::pair<long,long> work_range_old = work_range_new;
+    if(work_range_old.first>=work_range_old.second)
+      return -1;
+
+    work_range_new.first+=1;
+
+    bool success = false;
+    while(!success) {
+      work_range_new = Kokkos::atomic_compare_exchange(&m_work_range,work_range_old,work_range_new);
+      success = ( (work_range_new == work_range_old) || 
+                  (work_range_new.first>=work_range_new.second));
+      work_range_old = work_range_new;
+      work_range_new.first+=1;
+    }
+    if(work_range_old.first<work_range_old.second)
+      return work_range_old.first;
+    else
+      return -1;
+  }
+
+  // Claim and index from this thread's range from the end
+  inline long get_work_index_end () {
+    Kokkos::pair<long,long> work_range_new = m_work_range;
+    Kokkos::pair<long,long> work_range_old = work_range_new;
+    if(work_range_old.first>=work_range_old.second)
+      return -1;
+    work_range_new.second-=1;
+    bool success = false;
+    while(!success) {
+      work_range_new = Kokkos::atomic_compare_exchange(&m_work_range,work_range_old,work_range_new);
+      success = ( (work_range_new == work_range_old) ||
+                  (work_range_new.first>=work_range_new.second) );
+      work_range_old = work_range_new;
+      work_range_new.second-=1;
+    }
+    if(work_range_old.first<work_range_old.second)
+      return work_range_old.second-1;
+    else
+      return -1;
+  }
+
+  // Reset the steal target
+  inline void reset_steal_target() {
+    m_current_steal_target = (m_pool_rank+1)%m_pool_topo[0];
+    m_stealing = false;
+  }
+
+  // Reset the steal target
+  inline void reset_steal_target(int team_size) {
+    m_current_steal_target = (m_pool_rank_rev+team_size);
+    if(m_current_steal_target>=m_pool_topo[0])
+      m_current_steal_target = 0;//m_pool_topo[0]-1;
+    m_stealing = false;
+  }
+
+  // Get a steal target; start with my-rank + 1 and go round robin, until arriving at this threads rank
+  // Returns -1 fi no active steal target available
+  inline int get_steal_target() {
+    while(( m_pool[m_current_steal_target]->m_work_range.second <=
+            m_pool[m_current_steal_target]->m_work_range.first  ) &&
+          (m_current_steal_target!=m_pool_rank) ) {
+      m_current_steal_target = (m_current_steal_target+1)%m_pool_topo[0];
+    }
+    if(m_current_steal_target == m_pool_rank)
+      return -1;
+    else
+      return m_current_steal_target;
+  }
+
+  inline int get_steal_target(int team_size) {
+
+    while(( m_pool[m_current_steal_target]->m_work_range.second <=
+            m_pool[m_current_steal_target]->m_work_range.first  ) &&
+          (m_current_steal_target!=m_pool_rank_rev) ) {
+      if(m_current_steal_target + team_size < m_pool_topo[0])
+        m_current_steal_target = (m_current_steal_target+team_size);
+      else
+        m_current_steal_target = 0;
+    }
+
+    if(m_current_steal_target == m_pool_rank_rev)
+      return -1;
+    else
+      return m_current_steal_target;
+  }
+
+  inline long steal_work_index (int team_size = 0) {
+    long index = -1;
+    int steal_target = team_size>0?get_steal_target(team_size):get_steal_target();
+    while ( (steal_target != -1) && (index == -1)) {
+      index = m_pool[steal_target]->get_work_index_end();
+      if(index == -1)
+        steal_target = team_size>0?get_steal_target(team_size):get_steal_target();
+    }
+    return index;
+  }
+
+  // Get a work index. Claim from owned range until its exhausted, then steal from other thread
+  inline long get_work_index (int team_size = 0) {
+    long work_index = -1;
+    if(!m_stealing) work_index = get_work_index_begin();
+
+    if( work_index == -1) {
+      memory_fence();
+      m_stealing = true;
+      work_index = steal_work_index(team_size);
+    }
+    m_team_work_index = work_index;
+    memory_fence();
+    return work_index;
+  }
+
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+class OpenMPexecTeamMember {
+public:
+
+  enum { TEAM_REDUCE_SIZE = 512 };
+
+  /** \brief  Thread states for team synchronization */
+  enum { Active = 0 , Rendezvous = 1 };
+
+  typedef Kokkos::OpenMP                         execution_space ;
+  typedef execution_space::scratch_memory_space  scratch_memory_space ;
+
+  Impl::OpenMPexec    & m_exec ;
+  scratch_memory_space  m_team_shared ;
+  int                   m_team_scratch_size[2] ;
+  int                   m_team_base_rev ;
+  int                   m_team_rank_rev ;
+  int                   m_team_rank ;
+  int                   m_team_size ;
+  int                   m_league_rank ;
+  int                   m_league_end ;
+  int                   m_league_size ;
+
+  int                   m_chunk_size;
+  int                   m_league_chunk_end;
+  Impl::OpenMPexec    & m_team_lead_exec ;
+  int                   m_invalid_thread;
+  int                   m_team_alloc;
+
+  // Fan-in team threads, root of the fan-in which does not block returns true
+  inline
+  bool team_fan_in() const
+    {
+      memory_fence();
+      for ( int n = 1 , j ; ( ( j = m_team_rank_rev + n ) < m_team_size ) && ! ( m_team_rank_rev & n ) ; n <<= 1 ) {
+
+        m_exec.pool_rev( m_team_base_rev + j )->state_wait( Active );
+      }
+
+      if ( m_team_rank_rev ) {
+        m_exec.state_set( Rendezvous );
+        memory_fence();
+        m_exec.state_wait( Rendezvous );
+      }
+
+      return 0 == m_team_rank_rev ;
+    }
+
+  inline
+  void team_fan_out() const
+    {
+      memory_fence();
+      for ( int n = 1 , j ; ( ( j = m_team_rank_rev + n ) < m_team_size ) && ! ( m_team_rank_rev & n ) ; n <<= 1 ) {
+        m_exec.pool_rev( m_team_base_rev + j )->state_set( Active );
+        memory_fence();
+      }
+    }
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  const execution_space::scratch_memory_space& team_shmem() const
+    { return m_team_shared.set_team_thread_mode(0,1,0) ; }
+
+  KOKKOS_INLINE_FUNCTION
+  const execution_space::scratch_memory_space& team_scratch(int) const
+    { return m_team_shared.set_team_thread_mode(0,1,0) ; }
+
+  KOKKOS_INLINE_FUNCTION
+  const execution_space::scratch_memory_space& thread_scratch(int) const
+    { return m_team_shared.set_team_thread_mode(0,team_size(),team_rank()) ; }
+
+  KOKKOS_INLINE_FUNCTION int league_rank() const { return m_league_rank ; }
+  KOKKOS_INLINE_FUNCTION int league_size() const { return m_league_size ; }
+  KOKKOS_INLINE_FUNCTION int team_rank() const { return m_team_rank ; }
+  KOKKOS_INLINE_FUNCTION int team_size() const { return m_team_size ; }
+
+  KOKKOS_INLINE_FUNCTION void team_barrier() const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    {}
+#else
+    {
+      if ( 1 < m_team_size && !m_invalid_thread) {
+        team_fan_in();
+        team_fan_out();
+      }
+    }
+#endif
+
+  template<class ValueType>
+  KOKKOS_INLINE_FUNCTION
+  void team_broadcast(ValueType& value, const int& thread_id) const
+  {
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { }
+#else
+    // Make sure there is enough scratch space:
+    typedef typename if_c< sizeof(ValueType) < TEAM_REDUCE_SIZE
+                         , ValueType , void >::type type ;
+
+    type * const local_value = ((type*) m_exec.scratch_thread());
+    if(team_rank() == thread_id)
+      *local_value = value;
+    memory_fence();
+    team_barrier();
+    value = *local_value;
+#endif
+  }
+
+#ifdef KOKKOS_HAVE_CXX11
+  template< class ValueType, class JoinOp >
+  KOKKOS_INLINE_FUNCTION ValueType
+    team_reduce( const ValueType & value
+               , const JoinOp & op_in ) const
+  #if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return ValueType(); }
+  #else
+    {
+      memory_fence();
+      typedef ValueType value_type;
+      const JoinLambdaAdapter<value_type,JoinOp> op(op_in);
+  #endif
+#else // KOKKOS_HAVE_CXX11
+  template< class JoinOp >
+  KOKKOS_INLINE_FUNCTION typename JoinOp::value_type
+    team_reduce( const typename JoinOp::value_type & value
+               , const JoinOp & op ) const
+  #if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return typename JoinOp::value_type(); }
+  #else
+    {
+      typedef typename JoinOp::value_type value_type;
+  #endif
+#endif // KOKKOS_HAVE_CXX11
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      // Make sure there is enough scratch space:
+      typedef typename if_c< sizeof(value_type) < TEAM_REDUCE_SIZE
+                           , value_type , void >::type type ;
+
+      type * const local_value = ((type*) m_exec.scratch_thread());
+
+      // Set this thread's contribution
+      *local_value = value ;
+
+      // Fence to make sure the base team member has access:
+      memory_fence();
+
+      if ( team_fan_in() ) {
+        // The last thread to synchronize returns true, all other threads wait for team_fan_out()
+        type * const team_value  = ((type*) m_exec.pool_rev( m_team_base_rev )->scratch_thread());
+
+        // Join to the team value:
+        for ( int i = 1 ; i < m_team_size ; ++i ) {
+          op.join( *team_value , *((type*) m_exec.pool_rev( m_team_base_rev + i )->scratch_thread()) );
+        }
+        memory_fence();
+
+        // The base team member may "lap" the other team members,
+        // copy to their local value before proceeding.
+        for ( int i = 1 ; i < m_team_size ; ++i ) {
+          *((type*) m_exec.pool_rev( m_team_base_rev + i )->scratch_thread()) = *team_value ;
+        }
+
+        // Fence to make sure all team members have access
+        memory_fence();
+      }
+
+      team_fan_out();
+
+      return *((type volatile const *)local_value);
+    }
+#endif
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering
+   *          with intra-team non-deterministic ordering accumulation.
+   *
+   *  The global inter-team accumulation value will, at the end of the
+   *  league's parallel execution, be the scan's total.
+   *  Parallel execution ordering of the league's teams is non-deterministic.
+   *  As such the base value for each team's scan operation is similarly
+   *  non-deterministic.
+   */
+  template< typename ArgType >
+  KOKKOS_INLINE_FUNCTION ArgType team_scan( const ArgType & value , ArgType * const global_accum ) const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return ArgType(); }
+#else
+    {
+      // Make sure there is enough scratch space:
+      typedef typename if_c< sizeof(ArgType) < TEAM_REDUCE_SIZE , ArgType , void >::type type ;
+
+      volatile type * const work_value  = ((type*) m_exec.scratch_thread());
+
+      *work_value = value ;
+
+      memory_fence();
+
+      if ( team_fan_in() ) {
+        // The last thread to synchronize returns true, all other threads wait for team_fan_out()
+        // m_team_base[0]                 == highest ranking team member
+        // m_team_base[ m_team_size - 1 ] == lowest ranking team member
+        //
+        // 1) copy from lower to higher rank, initialize lowest rank to zero
+        // 2) prefix sum from lowest to highest rank, skipping lowest rank
+
+        type accum = 0 ;
+
+        if ( global_accum ) {
+          for ( int i = m_team_size ; i-- ; ) {
+            type & val = *((type*) m_exec.pool_rev( m_team_base_rev + i )->scratch_thread());
+            accum += val ;
+          }
+          accum = atomic_fetch_add( global_accum , accum );
+        }
+
+        for ( int i = m_team_size ; i-- ; ) {
+          type & val = *((type*) m_exec.pool_rev( m_team_base_rev + i )->scratch_thread());
+          const type offset = accum ;
+          accum += val ;
+          val = offset ;
+        }
+
+        memory_fence();
+      }
+
+      team_fan_out();
+
+      return *work_value ;
+    }
+#endif
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering.
+   *
+   *  The highest rank thread can compute the reduction total as
+   *    reduction_total = dev.team_scan( value ) + value ;
+   */
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION Type team_scan( const Type & value ) const
+    { return this-> template team_scan<Type>( value , 0 ); }
+
+  //----------------------------------------
+  // Private for the driver
+
+private:
+
+  typedef execution_space::scratch_memory_space space ;
+
+public:
+
+  template< class ... Properties >
+  inline
+  OpenMPexecTeamMember( Impl::OpenMPexec & exec
+                      , const TeamPolicyInternal< OpenMP, Properties ...> & team
+                      , const int shmem_size_L1
+                      , const int shmem_size_L2
+                      )
+    : m_exec( exec )
+    , m_team_shared(0,0)
+    , m_team_scratch_size{ shmem_size_L1 , shmem_size_L2 }
+    , m_team_base_rev(0)
+    , m_team_rank_rev(0)
+    , m_team_rank(0)
+    , m_team_size( team.team_size() )
+    , m_league_rank(0)
+    , m_league_end(0)
+    , m_league_size( team.league_size() )
+    , m_chunk_size( team.chunk_size()>0?team.chunk_size():team.team_iter() )
+    , m_league_chunk_end(0)
+    , m_team_lead_exec( *exec.pool_rev( team.team_alloc() * (m_exec.pool_rank_rev()/team.team_alloc()) ))
+    , m_team_alloc( team.team_alloc())
+    {
+      const int pool_rank_rev        = m_exec.pool_rank_rev();
+      const int pool_team_rank_rev   = pool_rank_rev % team.team_alloc();
+      const int pool_league_rank_rev = pool_rank_rev / team.team_alloc();
+      const int pool_num_teams       = OpenMP::thread_pool_size(0)/team.team_alloc();
+      const int chunks_per_team      = ( team.league_size() + m_chunk_size*pool_num_teams-1 ) / (m_chunk_size*pool_num_teams);
+            int league_iter_end      = team.league_size() - pool_league_rank_rev * chunks_per_team * m_chunk_size;
+            int league_iter_begin    = league_iter_end - chunks_per_team * m_chunk_size;
+      if (league_iter_begin < 0)     league_iter_begin = 0;
+      if (league_iter_end>team.league_size()) league_iter_end = team.league_size();
+
+      if ((team.team_alloc()>m_team_size)?
+          (pool_team_rank_rev >= m_team_size):
+          (m_exec.pool_size() - pool_num_teams*m_team_size > m_exec.pool_rank())
+         )
+        m_invalid_thread = 1;
+      else
+        m_invalid_thread = 0;
+
+      m_team_rank_rev  = pool_team_rank_rev ;
+      if ( pool_team_rank_rev < m_team_size && !m_invalid_thread ) {
+        m_team_base_rev  = team.team_alloc() * pool_league_rank_rev ;
+        m_team_rank_rev  = pool_team_rank_rev ;
+        m_team_rank      = m_team_size - ( m_team_rank_rev + 1 );
+        m_league_end     = league_iter_end ;
+        m_league_rank    = league_iter_begin ;
+        new( (void*) &m_team_shared ) space( ( (char*) m_exec.pool_rev(m_team_base_rev)->scratch_thread() ) + TEAM_REDUCE_SIZE , m_team_scratch_size[0] ,
+                                             ( (char*) m_exec.pool_rev(m_team_base_rev)->scratch_thread() ) + TEAM_REDUCE_SIZE + m_team_scratch_size[0],
+                                               0 );
+      }
+
+      if ( (m_team_rank_rev == 0) && (m_invalid_thread == 0) ) {
+        m_exec.set_work_range(m_league_rank,m_league_end,m_chunk_size);
+        m_exec.reset_steal_target(m_team_size);
+      }
+    }
+
+  bool valid_static() const
+    {
+      return m_league_rank < m_league_end ;
+    }
+
+  void next_static()
+    {
+      if ( m_league_rank < m_league_end ) {
+        team_barrier();
+        new( (void*) &m_team_shared ) space( ( (char*) m_exec.pool_rev(m_team_base_rev)->scratch_thread() ) + TEAM_REDUCE_SIZE , m_team_scratch_size[0] ,
+                                             ( (char*) m_exec.pool_rev(m_team_base_rev)->scratch_thread() ) + TEAM_REDUCE_SIZE + m_team_scratch_size[0],
+                                               0);
+      }
+      m_league_rank++;
+    }
+
+  bool valid_dynamic() {
+    if(m_invalid_thread)
+      return false;
+    if ((m_league_rank < m_league_chunk_end) && (m_league_rank < m_league_size)) {
+      return true;
+    }
+
+    if (  m_team_rank_rev == 0 ) {
+      m_team_lead_exec.get_work_index(m_team_alloc);
+    }
+    team_barrier();
+
+    long work_index = m_team_lead_exec.team_work_index();
+
+    m_league_rank = work_index * m_chunk_size;
+    m_league_chunk_end = (work_index +1 ) * m_chunk_size;
+
+    if(m_league_chunk_end > m_league_size) m_league_chunk_end = m_league_size;
+
+    if(m_league_rank>=0)
+      return true;
+    return false;
+  }
+
+  void next_dynamic() {
+    if(m_invalid_thread)
+      return;
+
+    if ( m_league_rank < m_league_chunk_end ) {
+      team_barrier();
+      new( (void*) &m_team_shared ) space( ( (char*) m_exec.pool_rev(m_team_base_rev)->scratch_thread() ) + TEAM_REDUCE_SIZE , m_team_scratch_size[0] ,
+                                           ( (char*) m_exec.pool_rev(m_team_base_rev)->scratch_thread() ) + TEAM_REDUCE_SIZE + m_team_scratch_size[0],
+                                             0);
+    }
+    m_league_rank++;
+  }
+
+  static inline int team_reduce_size() { return TEAM_REDUCE_SIZE ; }
+};
+
+
+
+template< class ... Properties >
+class TeamPolicyInternal< Kokkos::OpenMP, Properties ... >: public PolicyTraits<Properties ...>
+{
+public:
+
+  //! Tag this class as a kokkos execution policy
+  typedef TeamPolicyInternal      execution_policy ;
+
+  typedef PolicyTraits<Properties ... > traits;
+
+  TeamPolicyInternal& operator = (const TeamPolicyInternal& p) {
+    m_league_size = p.m_league_size;
+    m_team_size = p.m_team_size;
+    m_team_alloc = p.m_team_alloc;
+    m_team_iter = p.m_team_iter;
+    m_team_scratch_size[0] = p.m_team_scratch_size[0];
+    m_thread_scratch_size[0] = p.m_thread_scratch_size[0];
+    m_team_scratch_size[1] = p.m_team_scratch_size[1];
+    m_thread_scratch_size[1] = p.m_thread_scratch_size[1];
+    m_chunk_size = p.m_chunk_size;
+    return *this;
+  }
+
+  //----------------------------------------
+
+  template< class FunctorType >
+  inline static
+  int team_size_max( const FunctorType & )
+    { return traits::execution_space::thread_pool_size(1); }
+
+  template< class FunctorType >
+  inline static
+  int team_size_recommended( const FunctorType & )
+    { return traits::execution_space::thread_pool_size(2); }
+
+  template< class FunctorType >
+  inline static
+  int team_size_recommended( const FunctorType &, const int& )
+    { return traits::execution_space::thread_pool_size(2); }
+
+  //----------------------------------------
+
+private:
+
+  int m_league_size ;
+  int m_team_size ;
+  int m_team_alloc ;
+  int m_team_iter ;
+
+  size_t m_team_scratch_size[2];
+  size_t m_thread_scratch_size[2];
+
+  int m_chunk_size;
+
+  inline void init( const int league_size_request
+                  , const int team_size_request )
+    {
+      const int pool_size  = traits::execution_space::thread_pool_size(0);
+      const int team_max   = traits::execution_space::thread_pool_size(1);
+      const int team_grain = traits::execution_space::thread_pool_size(2);
+
+      m_league_size = league_size_request ;
+
+      m_team_size = team_size_request < team_max ?
+                    team_size_request : team_max ;
+
+      // Round team size up to a multiple of 'team_gain'
+      const int team_size_grain = team_grain * ( ( m_team_size + team_grain - 1 ) / team_grain );
+      const int team_count      = pool_size / team_size_grain ;
+
+      // Constraint : pool_size = m_team_alloc * team_count
+      m_team_alloc = pool_size / team_count ;
+
+      // Maxumum number of iterations each team will take:
+      m_team_iter  = ( m_league_size + team_count - 1 ) / team_count ;
+
+      set_auto_chunk_size();
+    }
+
+public:
+
+  inline int team_size()   const { return m_team_size ; }
+  inline int league_size() const { return m_league_size ; }
+  inline size_t scratch_size(const int& level, int team_size_ = -1) const {
+    if(team_size_ < 0)
+      team_size_ = m_team_size;
+    return m_team_scratch_size[level] + team_size_*m_thread_scratch_size[level] ;
+  }
+
+  /** \brief  Specify league size, request team size */
+  TeamPolicyInternal( typename traits::execution_space &
+            , int league_size_request
+            , int team_size_request
+            , int /* vector_length_request */ = 1 )
+            : m_team_scratch_size { 0 , 0 }
+            , m_thread_scratch_size { 0 , 0 }
+            , m_chunk_size(0)
+    { init( league_size_request , team_size_request ); }
+
+  TeamPolicyInternal( typename traits::execution_space &
+            , int league_size_request
+            , const Kokkos::AUTO_t & /* team_size_request */
+            , int /* vector_length_request */ = 1)
+            : m_team_scratch_size { 0 , 0 }
+            , m_thread_scratch_size { 0 , 0 }
+            , m_chunk_size(0)
+    { init( league_size_request , traits::execution_space::thread_pool_size(2) ); }
+
+  TeamPolicyInternal( int league_size_request
+            , int team_size_request
+            , int /* vector_length_request */ = 1 )
+            : m_team_scratch_size { 0 , 0 }
+            , m_thread_scratch_size { 0 , 0 }
+            , m_chunk_size(0)
+    { init( league_size_request , team_size_request ); }
+
+  TeamPolicyInternal( int league_size_request
+            , const Kokkos::AUTO_t & /* team_size_request */
+            , int /* vector_length_request */ = 1 )
+            : m_team_scratch_size { 0 , 0 }
+            , m_thread_scratch_size { 0 , 0 }
+            , m_chunk_size(0)
+    { init( league_size_request , traits::execution_space::thread_pool_size(2) ); }
+
+  inline int team_alloc() const { return m_team_alloc ; }
+  inline int team_iter()  const { return m_team_iter ; }
+
+  inline int chunk_size() const { return m_chunk_size ; }
+
+  /** \brief set chunk_size to a discrete value*/
+  inline TeamPolicyInternal set_chunk_size(typename traits::index_type chunk_size_) const {
+    TeamPolicyInternal p = *this;
+    p.m_chunk_size = chunk_size_;
+    return p;
+  }
+
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerTeamValue& per_team) const {
+    TeamPolicyInternal p = *this;
+    p.m_team_scratch_size[level] = per_team.value;
+    return p;
+  };
+
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerThreadValue& per_thread) const {
+    TeamPolicyInternal p = *this;
+    p.m_thread_scratch_size[level] = per_thread.value;
+    return p;
+  };
+
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerTeamValue& per_team, const PerThreadValue& per_thread) const {
+    TeamPolicyInternal p = *this;
+    p.m_team_scratch_size[level] = per_team.value;
+    p.m_thread_scratch_size[level] = per_thread.value;
+    return p;
+  };
+
+private:
+  /** \brief finalize chunk_size if it was set to AUTO*/
+  inline void set_auto_chunk_size() {
+
+    int concurrency = traits::execution_space::thread_pool_size(0)/m_team_alloc;
+    if( concurrency==0 ) concurrency=1;
+
+    if(m_chunk_size > 0) {
+      if(!Impl::is_integral_power_of_two( m_chunk_size ))
+        Kokkos::abort("TeamPolicy blocking granularity must be power of two" );
+    }
+
+    int new_chunk_size = 1;
+    while(new_chunk_size*100*concurrency < m_league_size)
+      new_chunk_size *= 2;
+    if(new_chunk_size < 128) {
+      new_chunk_size = 1;
+      while( (new_chunk_size*40*concurrency < m_league_size ) && (new_chunk_size<128) )
+        new_chunk_size*=2;
+    }
+    m_chunk_size = new_chunk_size;
+  }
+
+public:
+  typedef Impl::OpenMPexecTeamMember member_type ;
+};
+} // namespace Impl
+
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+inline
+int OpenMP::thread_pool_size( int depth )
+{
+  return Impl::OpenMPexec::pool_size(depth);
+}
+
+KOKKOS_INLINE_FUNCTION
+int OpenMP::thread_pool_rank()
+{
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+  return Impl::OpenMPexec::m_map_rank[ omp_get_thread_num() ];
+#else
+  return -1 ;
+#endif
+}
+
+} // namespace Kokkos
+
+
+namespace Kokkos {
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember>
+  TeamThreadRange(const Impl::OpenMPexecTeamMember& thread, const iType& count) {
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember>(thread,count);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember>
+  TeamThreadRange(const Impl::OpenMPexecTeamMember& thread, const iType& begin, const iType& end) {
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember>(thread,begin,end);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember >
+  ThreadVectorRange(const Impl::OpenMPexecTeamMember& thread, const iType& count) {
+  return Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember >(thread,count);
+}
+
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadSingleStruct<Impl::OpenMPexecTeamMember> PerTeam(const Impl::OpenMPexecTeamMember& thread) {
+  return Impl::ThreadSingleStruct<Impl::OpenMPexecTeamMember>(thread);
+}
+
+KOKKOS_INLINE_FUNCTION
+Impl::VectorSingleStruct<Impl::OpenMPexecTeamMember> PerThread(const Impl::OpenMPexecTeamMember& thread) {
+  return Impl::VectorSingleStruct<Impl::OpenMPexecTeamMember>(thread);
+}
+} // namespace Kokkos
+
+namespace Kokkos {
+
+  /** \brief  Inter-thread parallel_for. Executes lambda(iType i) for each i=0..N-1.
+   *
+   * The range i=0..N-1 is mapped to all threads of the the calling thread team.
+   * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember>& loop_boundaries, const Lambda& lambda) {
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+/** \brief  Inter-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all threads of the the calling thread team and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember>& loop_boundaries,
+                     const Lambda & lambda, ValueType& result) {
+
+  result = ValueType();
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    result+=tmp;
+  }
+
+  result = loop_boundaries.thread.team_reduce(result,Impl::JoinAdd<ValueType>());
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember>& loop_boundaries,
+                     const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+  ValueType result = init_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    join(result,tmp);
+  }
+
+  init_result = loop_boundaries.thread.team_reduce(result,join);
+}
+
+} //namespace Kokkos
+
+
+namespace Kokkos {
+/** \brief  Intra-thread vector parallel_for. Executes lambda(iType i) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread.
+ * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember >&
+    loop_boundaries, const Lambda& lambda) {
+  #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+  #pragma ivdep
+  #endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember >&
+      loop_boundaries, const Lambda & lambda, ValueType& result) {
+  result = ValueType();
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    result+=tmp;
+  }
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember >&
+      loop_boundaries, const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+  ValueType result = init_result;
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    join(result,tmp);
+  }
+  init_result = result;
+}
+
+/** \brief  Intra-thread vector parallel exclusive prefix sum. Executes lambda(iType i, ValueType & val, bool final)
+ *          for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes in the thread and a scan operation is performed.
+ * Depending on the target execution space the operator might be called twice: once with final=false
+ * and once with final=true. When final==true val contains the prefix sum value. The contribution of this
+ * "i" needs to be added to val no matter whether final==true or not. In a serial execution
+ * (i.e. team_size==1) the operator is only called once with final==true. Scan_val will be set
+ * to the final sum value over all vector lanes.
+ * This functionality requires C++11 support.*/
+template< typename iType, class FunctorType >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::OpenMPexecTeamMember >&
+      loop_boundaries, const FunctorType & lambda) {
+
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
+  typedef typename ValueTraits::value_type value_type ;
+
+  value_type scan_val = value_type();
+
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,scan_val,true);
+  }
+}
+
+} // namespace Kokkos
+
+namespace Kokkos {
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::OpenMPexecTeamMember>& single_struct, const FunctorType& lambda) {
+  lambda();
+}
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::OpenMPexecTeamMember>& single_struct, const FunctorType& lambda) {
+  if(single_struct.team_member.team_rank()==0) lambda();
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::OpenMPexecTeamMember>& single_struct, const FunctorType& lambda, ValueType& val) {
+  lambda(val);
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::OpenMPexecTeamMember>& single_struct, const FunctorType& lambda, ValueType& val) {
+  if(single_struct.team_member.team_rank()==0) {
+    lambda(val);
+  }
+  single_struct.team_member.team_broadcast(val,0);
+}
+}
+
+#endif /* #ifndef KOKKOS_OPENMPEXEC_HPP */
+
diff --git a/lib/kokkos/core/src/Qthread/Kokkos_QthreadExec.cpp b/lib/kokkos/core/src/Qthread/Kokkos_QthreadExec.cpp
new file mode 100644
index 0000000000..3123a297c4
--- /dev/null
+++ b/lib/kokkos/core/src/Qthread/Kokkos_QthreadExec.cpp
@@ -0,0 +1,511 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core_fwd.hpp>
+
+#if defined( KOKKOS_HAVE_QTHREAD )
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <sstream>
+#include <utility>
+#include <Kokkos_Qthread.hpp>
+#include <Kokkos_Atomic.hpp>
+#include <impl/Kokkos_Error.hpp>
+
+// Defines to enable experimental Qthread functionality
+
+#define QTHREAD_LOCAL_PRIORITY
+#define CLONED_TASKS
+
+#include <qthread/qthread.h>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+namespace {
+
+enum { MAXIMUM_QTHREAD_WORKERS = 1024 };
+
+/** s_exec is indexed by the reverse rank of the workers
+ *  for faster fan-in / fan-out lookups
+ *  [ n - 1 , n - 2 , ... , 0 ]
+ */
+QthreadExec * s_exec[ MAXIMUM_QTHREAD_WORKERS ];
+
+int  s_number_shepherds            = 0 ;
+int  s_number_workers_per_shepherd = 0 ;
+int  s_number_workers              = 0 ;
+
+inline
+QthreadExec ** worker_exec()
+{
+  return s_exec + s_number_workers - ( qthread_shep() * s_number_workers_per_shepherd + qthread_worker_local(NULL) + 1 );
+}
+
+const int s_base_size = QthreadExec::align_alloc( sizeof(QthreadExec) );
+
+int s_worker_reduce_end   = 0 ; /* End of worker reduction memory    */
+int s_worker_shared_end   = 0 ; /* Total of worker scratch memory    */
+int s_worker_shared_begin = 0 ; /* Beginning of worker shared memory */
+
+QthreadExecFunctionPointer volatile s_active_function = 0 ;
+const void               * volatile s_active_function_arg = 0 ;
+
+} /* namespace */
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+int Qthread::is_initialized()
+{
+  return Impl::s_number_workers != 0 ;
+}
+
+int Qthread::concurrency()
+{
+  return Impl::s_number_workers_per_shepherd ;
+}
+
+int Qthread::in_parallel()
+{
+  return Impl::s_active_function != 0 ;
+}
+
+void Qthread::initialize( int thread_count )
+{
+  // Environment variable: QTHREAD_NUM_SHEPHERDS
+  // Environment variable: QTHREAD_NUM_WORKERS_PER_SHEP
+  // Environment variable: QTHREAD_HWPAR
+
+  {
+    char buffer[256];
+    snprintf(buffer,sizeof(buffer),"QTHREAD_HWPAR=%d",thread_count);
+    putenv(buffer);
+  }
+
+  const bool ok_init = ( QTHREAD_SUCCESS == qthread_initialize() ) &&
+                       ( thread_count    == qthread_num_shepherds() * qthread_num_workers_local(NO_SHEPHERD) ) &&
+                       ( thread_count    == qthread_num_workers() );
+
+  bool ok_symmetry = true ;
+
+  if ( ok_init ) {
+    Impl::s_number_shepherds            = qthread_num_shepherds();
+    Impl::s_number_workers_per_shepherd = qthread_num_workers_local(NO_SHEPHERD);
+    Impl::s_number_workers              = Impl::s_number_shepherds * Impl::s_number_workers_per_shepherd ;
+
+    for ( int i = 0 ; ok_symmetry && i < Impl::s_number_shepherds ; ++i ) {
+      ok_symmetry = ( Impl::s_number_workers_per_shepherd == qthread_num_workers_local(i) );
+    }
+  }
+
+  if ( ! ok_init || ! ok_symmetry ) {
+    std::ostringstream msg ;
+
+    msg << "Kokkos::Qthread::initialize(" << thread_count << ") FAILED" ;
+    msg << " : qthread_num_shepherds = " << qthread_num_shepherds();
+    msg << " : qthread_num_workers_per_shepherd = " << qthread_num_workers_local(NO_SHEPHERD);
+    msg << " : qthread_num_workers = " << qthread_num_workers();
+
+    if ( ! ok_symmetry ) {
+      msg << " : qthread_num_workers_local = {" ;
+      for ( int i = 0 ; i < Impl::s_number_shepherds ; ++i ) {
+        msg << " " << qthread_num_workers_local(i) ;
+      }
+      msg << " }" ;
+    }
+
+    Impl::s_number_workers   = 0 ;
+    Impl::s_number_shepherds = 0 ;
+    Impl::s_number_workers_per_shepherd = 0 ;
+
+    if ( ok_init ) { qthread_finalize(); }
+
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  Impl::QthreadExec::resize_worker_scratch( 256 , 256 );
+
+  // Init the array for used for arbitrarily sized atomics
+  Impl::init_lock_array_host_space();
+
+}
+
+void Qthread::finalize()
+{
+  Impl::QthreadExec::clear_workers();
+
+  if ( Impl::s_number_workers ) {
+    qthread_finalize();
+  }
+
+  Impl::s_number_workers    = 0 ;
+  Impl::s_number_shepherds  = 0 ;
+  Impl::s_number_workers_per_shepherd = 0 ;
+}
+
+void Qthread::print_configuration( std::ostream & s , const bool detail )
+{
+  s << "Kokkos::Qthread {"
+    << " num_shepherds(" << Impl::s_number_shepherds << ")"
+    << " num_workers_per_shepherd(" << Impl::s_number_workers_per_shepherd << ")"
+    << " }" << std::endl ;
+}
+
+Qthread & Qthread::instance( int )
+{
+  static Qthread q ;
+  return q ;
+}
+
+void Qthread::fence()
+{
+}
+
+int Qthread::shepherd_size() const { return Impl::s_number_shepherds ; }
+int Qthread::shepherd_worker_size() const { return Impl::s_number_workers_per_shepherd ; }
+
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+namespace {
+
+aligned_t driver_exec_all( void * arg )
+{
+  QthreadExec & exec = **worker_exec();
+
+  (*s_active_function)( exec , s_active_function_arg );
+
+/*
+  fprintf( stdout
+         , "QthreadExec driver worker(%d:%d) shepherd(%d:%d) shepherd_worker(%d:%d) done\n"
+         , exec.worker_rank()
+         , exec.worker_size()
+         , exec.shepherd_rank()
+         , exec.shepherd_size()
+         , exec.shepherd_worker_rank()
+         , exec.shepherd_worker_size()
+         );
+  fflush(stdout);
+*/
+
+  return 0 ;
+}
+
+aligned_t driver_resize_worker_scratch( void * arg )
+{
+  static volatile int lock_begin = 0 ;
+  static volatile int lock_end   = 0 ;
+
+  QthreadExec ** const exec = worker_exec();
+
+  //----------------------------------------
+  // Serialize allocation for thread safety
+
+  while ( ! atomic_compare_exchange_strong( & lock_begin , 0 , 1 ) ); // Spin wait to claim lock
+
+  const bool ok = 0 == *exec ;
+
+  if ( ok ) { *exec = (QthreadExec *) malloc( s_base_size + s_worker_shared_end ); }
+
+  lock_begin = 0 ; // release lock
+
+  if ( ok ) { new( *exec ) QthreadExec(); }
+
+  //----------------------------------------
+  // Wait for all calls to complete to insure that each worker has executed.
+
+  if ( s_number_workers == 1 + atomic_fetch_add( & lock_end , 1 ) ) { lock_end = 0 ; }
+
+  while ( lock_end );
+
+/*
+  fprintf( stdout
+         , "QthreadExec resize worker(%d:%d) shepherd(%d:%d) shepherd_worker(%d:%d) done\n"
+         , (**exec).worker_rank()
+         , (**exec).worker_size()
+         , (**exec).shepherd_rank()
+         , (**exec).shepherd_size()
+         , (**exec).shepherd_worker_rank()
+         , (**exec).shepherd_worker_size()
+         );
+  fflush(stdout);
+*/
+
+  //----------------------------------------
+
+  if ( ! ok ) {
+    fprintf( stderr , "Kokkos::QthreadExec resize failed\n" );
+    fflush( stderr );
+  }
+
+  return 0 ;
+}
+
+void verify_is_process( const char * const label , bool not_active = false )
+{
+  const bool not_process = 0 != qthread_shep() || 0 != qthread_worker_local(NULL);
+  const bool is_active   = not_active && ( s_active_function || s_active_function_arg );
+
+  if ( not_process || is_active ) {
+    std::string msg( label );
+    msg.append( " : FAILED" );
+    if ( not_process ) msg.append(" : not called by main process");
+    if ( is_active )   msg.append(" : parallel execution in progress");
+    Kokkos::Impl::throw_runtime_exception( msg );
+  }
+}
+
+}
+
+int QthreadExec::worker_per_shepherd()
+{
+  return s_number_workers_per_shepherd ;
+}
+
+QthreadExec::QthreadExec()
+{
+  const int shepherd_rank        = qthread_shep();
+  const int shepherd_worker_rank = qthread_worker_local(NULL);
+  const int worker_rank          = shepherd_rank * s_number_workers_per_shepherd + shepherd_worker_rank ;
+
+  m_worker_base          = s_exec ;
+  m_shepherd_base        = s_exec + s_number_workers_per_shepherd * ( ( s_number_shepherds - ( shepherd_rank + 1 ) ) );
+  m_scratch_alloc        = ( (unsigned char *) this ) + s_base_size ;
+  m_reduce_end           = s_worker_reduce_end ;
+  m_shepherd_rank        = shepherd_rank ;
+  m_shepherd_size        = s_number_shepherds ;
+  m_shepherd_worker_rank = shepherd_worker_rank ;
+  m_shepherd_worker_size = s_number_workers_per_shepherd ;
+  m_worker_rank          = worker_rank ;
+  m_worker_size          = s_number_workers ;
+  m_worker_state         = QthreadExec::Active ;
+}
+
+void QthreadExec::clear_workers()
+{
+  for ( int iwork = 0 ; iwork < s_number_workers ; ++iwork ) {
+    QthreadExec * const exec = s_exec[iwork] ;
+    s_exec[iwork] = 0 ;
+    free( exec );
+  }
+}
+
+void QthreadExec::shared_reset( Qthread::scratch_memory_space & space )
+{
+  new( & space )
+    Qthread::scratch_memory_space(
+      ((unsigned char *) (**m_shepherd_base).m_scratch_alloc ) + s_worker_shared_begin ,
+      s_worker_shared_end - s_worker_shared_begin
+    );
+}
+
+void QthreadExec::resize_worker_scratch( const int reduce_size , const int shared_size )
+{
+  const int exec_all_reduce_alloc = align_alloc( reduce_size );
+  const int shepherd_scan_alloc   = align_alloc( 8 );
+  const int shepherd_shared_end   = exec_all_reduce_alloc + shepherd_scan_alloc + align_alloc( shared_size );
+
+  if ( s_worker_reduce_end < exec_all_reduce_alloc ||
+       s_worker_shared_end < shepherd_shared_end ) {
+
+/*
+  fprintf( stdout , "QthreadExec::resize\n");
+  fflush(stdout);
+*/
+
+    // Clear current worker memory before allocating new worker memory
+    clear_workers();
+
+    // Increase the buffers to an aligned allocation
+    s_worker_reduce_end   = exec_all_reduce_alloc ;
+    s_worker_shared_begin = exec_all_reduce_alloc + shepherd_scan_alloc ;
+    s_worker_shared_end   = shepherd_shared_end ;
+
+    // Need to query which shepherd this main 'process' is running...
+ 
+    const int main_shep = qthread_shep();
+
+    // Have each worker resize its memory for proper first-touch
+#if 0
+    for ( int jshep = 0 ; jshep < s_number_shepherds ; ++jshep ) {
+    for ( int i = jshep != main_shep ? 0 : 1 ; i < s_number_workers_per_shepherd ; ++i ) {
+      qthread_fork_to( driver_resize_worker_scratch , NULL , NULL , jshep );
+    }}
+#else
+    // If this function is used before the 'qthread.task_policy' unit test
+    // the 'qthread.task_policy' unit test fails with a seg-fault within libqthread.so.
+    for ( int jshep = 0 ; jshep < s_number_shepherds ; ++jshep ) {
+      const int num_clone = jshep != main_shep ? s_number_workers_per_shepherd : s_number_workers_per_shepherd - 1 ;
+
+      if ( num_clone ) {
+        const int ret = qthread_fork_clones_to_local_priority
+          ( driver_resize_worker_scratch   /* function */
+          , NULL                           /* function data block */
+          , NULL                           /* pointer to return value feb */
+          , jshep                          /* shepherd number */
+          , num_clone - 1                  /* number of instances - 1 */
+          );
+
+        assert(ret == QTHREAD_SUCCESS);
+      }
+    }
+#endif
+
+    driver_resize_worker_scratch( NULL );
+
+    // Verify all workers allocated
+
+    bool ok = true ;
+    for ( int iwork = 0 ; ok && iwork < s_number_workers ; ++iwork ) { ok = 0 != s_exec[iwork] ; }
+
+    if ( ! ok ) {
+      std::ostringstream msg ;
+      msg << "Kokkos::Impl::QthreadExec::resize : FAILED for workers {" ;
+      for ( int iwork = 0 ; iwork < s_number_workers ; ++iwork ) {
+         if ( 0 == s_exec[iwork] ) { msg << " " << ( s_number_workers - ( iwork + 1 ) ); }
+      }
+      msg << " }" ;
+      Kokkos::Impl::throw_runtime_exception( msg.str() );
+    }
+  }
+}
+
+void QthreadExec::exec_all( Qthread & , QthreadExecFunctionPointer func , const void * arg )
+{
+  verify_is_process("QthreadExec::exec_all(...)",true);
+
+/*
+  fprintf( stdout , "QthreadExec::exec_all\n");
+  fflush(stdout);
+*/
+
+  s_active_function     = func ;
+  s_active_function_arg = arg ;
+
+  // Need to query which shepherd this main 'process' is running...
+ 
+  const int main_shep = qthread_shep();
+
+#if 0
+  for ( int jshep = 0 , iwork = 0 ; jshep < s_number_shepherds ; ++jshep ) {
+  for ( int i = jshep != main_shep ? 0 : 1 ; i < s_number_workers_per_shepherd ; ++i , ++iwork ) {
+    qthread_fork_to( driver_exec_all , NULL , NULL , jshep );
+  }}
+#else
+  // If this function is used before the 'qthread.task_policy' unit test
+  // the 'qthread.task_policy' unit test fails with a seg-fault within libqthread.so.
+  for ( int jshep = 0 ; jshep < s_number_shepherds ; ++jshep ) {
+    const int num_clone = jshep != main_shep ? s_number_workers_per_shepherd : s_number_workers_per_shepherd - 1 ;
+
+    if ( num_clone ) {
+      const int ret = qthread_fork_clones_to_local_priority
+        ( driver_exec_all   /* function */
+        , NULL              /* function data block */
+        , NULL              /* pointer to return value feb */
+        , jshep             /* shepherd number */
+        , num_clone - 1     /* number of instances - 1 */
+        );
+
+      assert(ret == QTHREAD_SUCCESS);
+    }
+  }
+#endif
+
+  driver_exec_all( NULL );
+
+  s_active_function     = 0 ;
+  s_active_function_arg = 0 ;
+}
+
+void * QthreadExec::exec_all_reduce_result()
+{
+  return s_exec[0]->m_scratch_alloc ;
+}
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+namespace Kokkos {
+namespace Impl {
+
+QthreadTeamPolicyMember::QthreadTeamPolicyMember()
+  : m_exec( **worker_exec() )
+  , m_team_shared(0,0)
+  , m_team_size( 1 )
+  , m_team_rank( 0 )
+  , m_league_size(1)
+  , m_league_end(1)
+  , m_league_rank(0)
+{
+  m_exec.shared_reset( m_team_shared );
+}
+
+QthreadTeamPolicyMember::QthreadTeamPolicyMember( const QthreadTeamPolicyMember::TaskTeam & )
+  : m_exec( **worker_exec() )
+  , m_team_shared(0,0)
+  , m_team_size( s_number_workers_per_shepherd )
+  , m_team_rank( m_exec.shepherd_worker_rank() )
+  , m_league_size(1)
+  , m_league_end(1)
+  , m_league_rank(0)
+{
+  m_exec.shared_reset( m_team_shared );
+}
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_QTHREAD ) */
+
diff --git a/lib/kokkos/core/src/Qthread/Kokkos_QthreadExec.hpp b/lib/kokkos/core/src/Qthread/Kokkos_QthreadExec.hpp
new file mode 100644
index 0000000000..f948eb2903
--- /dev/null
+++ b/lib/kokkos/core/src/Qthread/Kokkos_QthreadExec.hpp
@@ -0,0 +1,620 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_QTHREADEXEC_HPP
+#define KOKKOS_QTHREADEXEC_HPP
+
+#include <impl/Kokkos_spinwait.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+
+class QthreadExec ;
+
+typedef void (*QthreadExecFunctionPointer)( QthreadExec & , const void * );
+
+class QthreadExec {
+private:
+
+  enum { Inactive = 0 , Active = 1 };
+
+  const QthreadExec * const * m_worker_base ;
+  const QthreadExec * const * m_shepherd_base ;
+
+  void  * m_scratch_alloc ;  ///< Scratch memory [ reduce , team , shared ]
+  int     m_reduce_end ;     ///< End of scratch reduction memory
+
+  int     m_shepherd_rank ;
+  int     m_shepherd_size ;
+
+  int     m_shepherd_worker_rank ;
+  int     m_shepherd_worker_size ;
+
+  /*
+   *  m_worker_rank = m_shepherd_rank * m_shepherd_worker_size + m_shepherd_worker_rank
+   *  m_worker_size = m_shepherd_size * m_shepherd_worker_size
+   */
+  int     m_worker_rank ;
+  int     m_worker_size ;
+
+  int mutable volatile m_worker_state ;
+
+
+  friend class Kokkos::Qthread ;
+
+  ~QthreadExec();
+  QthreadExec( const QthreadExec & );
+  QthreadExec & operator = ( const QthreadExec & );
+
+public:
+
+  QthreadExec();
+
+  /** Execute the input function on all available Qthread workers */
+  static void exec_all( Qthread & , QthreadExecFunctionPointer , const void * );
+
+  //----------------------------------------
+  /** Barrier across all workers participating in the 'exec_all' */
+  void exec_all_barrier() const
+    {
+      const int rev_rank = m_worker_size - ( m_worker_rank + 1 );
+
+      int n , j ;
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < m_worker_size ) ; n <<= 1 ) {
+        Impl::spinwait( m_worker_base[j]->m_worker_state , QthreadExec::Active );
+      }
+
+      if ( rev_rank ) {
+        m_worker_state = QthreadExec::Inactive ;
+        Impl::spinwait( m_worker_state , QthreadExec::Inactive );
+      }
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < m_worker_size ) ; n <<= 1 ) {
+        m_worker_base[j]->m_worker_state = QthreadExec::Active ;
+      }
+    }
+
+  /** Barrier across workers within the shepherd with rank < team_rank */
+  void shepherd_barrier( const int team_size ) const
+    {
+      if ( m_shepherd_worker_rank < team_size ) {
+
+        const int rev_rank = team_size - ( m_shepherd_worker_rank + 1 );
+
+        int n , j ;
+
+        for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < team_size ) ; n <<= 1 ) {
+          Impl::spinwait( m_shepherd_base[j]->m_worker_state , QthreadExec::Active );
+        }
+
+        if ( rev_rank ) {
+          m_worker_state = QthreadExec::Inactive ;
+          Impl::spinwait( m_worker_state , QthreadExec::Inactive );
+        }
+
+        for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < team_size ) ; n <<= 1 ) {
+          m_shepherd_base[j]->m_worker_state = QthreadExec::Active ;
+        }
+      }
+    }
+
+  //----------------------------------------
+  /** Reduce across all workers participating in the 'exec_all' */
+  template< class FunctorType , class ReducerType , class ArgTag >
+  inline
+  void exec_all_reduce( const FunctorType & func, const ReducerType & reduce ) const
+    {
+      typedef Kokkos::Impl::if_c< std::is_same<InvalidType, ReducerType>::value, FunctorType, ReducerType > ReducerConditional;
+      typedef typename ReducerConditional::type ReducerTypeFwd;
+      typedef Kokkos::Impl::FunctorValueJoin< ReducerTypeFwd, ArgTag > ValueJoin ;
+
+      const int rev_rank = m_worker_size - ( m_worker_rank + 1 );
+
+      int n , j ;
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < m_worker_size ) ; n <<= 1 ) {
+        const QthreadExec & fan = *m_worker_base[j];
+
+        Impl::spinwait( fan.m_worker_state , QthreadExec::Active );
+
+        ValueJoin::join( ReducerConditional::select(func , reduce) , m_scratch_alloc , fan.m_scratch_alloc );
+      }
+
+      if ( rev_rank ) {
+        m_worker_state = QthreadExec::Inactive ;
+        Impl::spinwait( m_worker_state , QthreadExec::Inactive );
+      }
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < m_worker_size ) ; n <<= 1 ) {
+        m_worker_base[j]->m_worker_state = QthreadExec::Active ;
+      }
+    }
+
+  //----------------------------------------
+  /** Scall across all workers participating in the 'exec_all' */
+  template< class FunctorType , class ArgTag >
+  inline
+  void exec_all_scan( const FunctorType & func ) const
+    {
+      typedef Kokkos::Impl::FunctorValueInit<   FunctorType , ArgTag > ValueInit ;
+      typedef Kokkos::Impl::FunctorValueJoin<   FunctorType , ArgTag > ValueJoin ;
+      typedef Kokkos::Impl::FunctorValueOps<    FunctorType , ArgTag > ValueOps ;
+
+      const int rev_rank = m_worker_size - ( m_worker_rank + 1 );
+
+      int n , j ;
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < m_worker_size ) ; n <<= 1 ) {
+        Impl::spinwait( m_worker_base[j]->m_worker_state , QthreadExec::Active );
+      }
+
+      if ( rev_rank ) {
+        m_worker_state = QthreadExec::Inactive ;
+        Impl::spinwait( m_worker_state , QthreadExec::Inactive );
+      }
+      else {
+        // Root thread scans across values before releasing threads
+        // Worker data is in reverse order, so m_worker_base[0] is the
+        // highest ranking thread.
+
+        // Copy from lower ranking to higher ranking worker.
+        for ( int i = 1 ; i < m_worker_size ; ++i ) {
+          ValueOps::copy( func
+                        , m_worker_base[i-1]->m_scratch_alloc
+                        , m_worker_base[i]->m_scratch_alloc
+                        );
+        }
+
+        ValueInit::init( func , m_worker_base[m_worker_size-1]->m_scratch_alloc );
+
+        // Join from lower ranking to higher ranking worker.
+        // Value at m_worker_base[n-1] is zero so skip adding it to m_worker_base[n-2].
+        for ( int i = m_worker_size - 1 ; --i > 0 ; ) {
+          ValueJoin::join( func , m_worker_base[i-1]->m_scratch_alloc , m_worker_base[i]->m_scratch_alloc );
+        }
+      }
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < m_worker_size ) ; n <<= 1 ) {
+        m_worker_base[j]->m_worker_state = QthreadExec::Active ;
+      }
+    }
+
+  //----------------------------------------
+
+  template< class Type>
+  inline
+  volatile Type * shepherd_team_scratch_value() const
+    { return (volatile Type*)(((unsigned char *) m_scratch_alloc) + m_reduce_end); }
+
+  template< class Type >
+  inline
+  void shepherd_broadcast( Type & value , const int team_size , const int team_rank ) const
+    {
+      if ( m_shepherd_base ) {
+        Type * const shared_value = m_shepherd_base[0]->shepherd_team_scratch_value<Type>();
+        if ( m_shepherd_worker_rank == team_rank ) { *shared_value = value ; }
+        memory_fence();
+        shepherd_barrier( team_size );
+        value = *shared_value ;
+      }
+    }
+
+  template< class Type >
+  inline
+  Type shepherd_reduce( const int team_size , const Type & value ) const
+    {
+      *shepherd_team_scratch_value<Type>() = value ;
+
+      memory_fence();
+
+      const int rev_rank = team_size - ( m_shepherd_worker_rank + 1 );
+
+      int n , j ;
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < team_size ) ; n <<= 1 ) {
+        Impl::spinwait( m_shepherd_base[j]->m_worker_state , QthreadExec::Active );
+      }
+
+      if ( rev_rank ) {
+        m_worker_state = QthreadExec::Inactive ;
+        Impl::spinwait( m_worker_state , QthreadExec::Inactive );
+      }
+      else {
+        Type & accum = * m_shepherd_base[0]->shepherd_team_scratch_value<Type>();
+        for ( int i = 1 ; i < n ; ++i ) {
+          accum += * m_shepherd_base[i]->shepherd_team_scratch_value<Type>();
+        }
+        for ( int i = 1 ; i < n ; ++i ) {
+          * m_shepherd_base[i]->shepherd_team_scratch_value<Type>() = accum ;
+        }
+
+        memory_fence();
+      }
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < team_size ) ; n <<= 1 ) {
+        m_shepherd_base[j]->m_worker_state = QthreadExec::Active ;
+      }
+
+      return *shepherd_team_scratch_value<Type>();
+    }
+
+  template< class JoinOp >
+  inline
+  typename JoinOp::value_type
+    shepherd_reduce( const int team_size
+                   , const typename JoinOp::value_type & value
+                   , const JoinOp & op ) const
+    {
+      typedef typename JoinOp::value_type Type ;
+
+      *shepherd_team_scratch_value<Type>() = value ;
+
+      memory_fence();
+
+      const int rev_rank = team_size - ( m_shepherd_worker_rank + 1 );
+
+      int n , j ;
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < team_size ) ; n <<= 1 ) {
+        Impl::spinwait( m_shepherd_base[j]->m_worker_state , QthreadExec::Active );
+      }
+
+      if ( rev_rank ) {
+        m_worker_state = QthreadExec::Inactive ;
+        Impl::spinwait( m_worker_state , QthreadExec::Inactive );
+      }
+      else {
+        volatile Type & accum = * m_shepherd_base[0]->shepherd_team_scratch_value<Type>();
+        for ( int i = 1 ; i < team_size ; ++i ) {
+          op.join( accum , * m_shepherd_base[i]->shepherd_team_scratch_value<Type>() );
+        }
+        for ( int i = 1 ; i < team_size ; ++i ) {
+          * m_shepherd_base[i]->shepherd_team_scratch_value<Type>() = accum ;
+        }
+
+        memory_fence();
+      }
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < team_size ) ; n <<= 1 ) {
+        m_shepherd_base[j]->m_worker_state = QthreadExec::Active ;
+      }
+
+      return *shepherd_team_scratch_value<Type>();
+    }
+
+  template< class Type >
+  inline
+  Type shepherd_scan( const int team_size
+                    , const Type & value
+                    ,       Type * const global_value = 0 ) const
+    {
+      *shepherd_team_scratch_value<Type>() = value ;
+
+      memory_fence();
+
+      const int rev_rank = team_size - ( m_shepherd_worker_rank + 1 );
+
+      int n , j ;
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < team_size ) ; n <<= 1 ) {
+        Impl::spinwait( m_shepherd_base[j]->m_worker_state , QthreadExec::Active );
+      }
+
+      if ( rev_rank ) {
+        m_worker_state = QthreadExec::Inactive ;
+        Impl::spinwait( m_worker_state , QthreadExec::Inactive );
+      }
+      else {
+        // Root thread scans across values before releasing threads
+        // Worker data is in reverse order, so m_shepherd_base[0] is the
+        // highest ranking thread.
+
+        // Copy from lower ranking to higher ranking worker.
+
+        Type accum = * m_shepherd_base[0]->shepherd_team_scratch_value<Type>();
+        for ( int i = 1 ; i < team_size ; ++i ) {
+          const Type tmp = * m_shepherd_base[i]->shepherd_team_scratch_value<Type>();
+          accum += tmp ;
+          * m_shepherd_base[i-1]->shepherd_team_scratch_value<Type>() = tmp ;
+        }
+
+        * m_shepherd_base[team_size-1]->shepherd_team_scratch_value<Type>() =
+          global_value ? atomic_fetch_add( global_value , accum ) : 0 ;
+
+        // Join from lower ranking to higher ranking worker.
+        for ( int i = team_size ; --i ; ) {
+          * m_shepherd_base[i-1]->shepherd_team_scratch_value<Type>() += * m_shepherd_base[i]->shepherd_team_scratch_value<Type>();
+        }
+
+        memory_fence();
+      }
+
+      for ( n = 1 ; ( ! ( rev_rank & n ) ) && ( ( j = rev_rank + n ) < team_size ) ; n <<= 1 ) {
+        m_shepherd_base[j]->m_worker_state = QthreadExec::Active ;
+      }
+
+      return *shepherd_team_scratch_value<Type>();
+    }
+
+  //----------------------------------------
+
+  static inline
+  int align_alloc( int size )
+    {
+      enum { ALLOC_GRAIN = 1 << 6 /* power of two, 64bytes */};
+      enum { ALLOC_GRAIN_MASK = ALLOC_GRAIN - 1 };
+      return ( size + ALLOC_GRAIN_MASK ) & ~ALLOC_GRAIN_MASK ;
+    }
+
+  void shared_reset( Qthread::scratch_memory_space & );
+
+  void * exec_all_reduce_value() const { return m_scratch_alloc ; }
+
+  static void * exec_all_reduce_result();
+
+  static void resize_worker_scratch( const int reduce_size , const int shared_size );
+  static void clear_workers();
+
+  //----------------------------------------
+
+  inline int worker_rank() const { return m_worker_rank ; }
+  inline int worker_size() const { return m_worker_size ; }
+  inline int shepherd_worker_rank() const { return m_shepherd_worker_rank ; }
+  inline int shepherd_worker_size() const { return m_shepherd_worker_size ; }
+  inline int shepherd_rank() const { return m_shepherd_rank ; }
+  inline int shepherd_size() const { return m_shepherd_size ; }
+
+  static int worker_per_shepherd();
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+class QthreadTeamPolicyMember {
+private:
+
+  typedef Kokkos::Qthread                        execution_space ;
+  typedef execution_space::scratch_memory_space  scratch_memory_space ;
+
+
+        Impl::QthreadExec   & m_exec ;
+  scratch_memory_space        m_team_shared ;
+  const int                   m_team_size ;
+  const int                   m_team_rank ;
+  const int                   m_league_size ;
+  const int                   m_league_end ;
+        int                   m_league_rank ;
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  const scratch_memory_space & team_shmem() const { return m_team_shared ; }
+
+  KOKKOS_INLINE_FUNCTION int league_rank() const { return m_league_rank ; }
+  KOKKOS_INLINE_FUNCTION int league_size() const { return m_league_size ; }
+  KOKKOS_INLINE_FUNCTION int team_rank() const { return m_team_rank ; }
+  KOKKOS_INLINE_FUNCTION int team_size() const { return m_team_size ; }
+
+  KOKKOS_INLINE_FUNCTION void team_barrier() const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    {}
+#else
+    { m_exec.shepherd_barrier( m_team_size ); }
+#endif
+
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION Type team_broadcast( const Type & value , int rank ) const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return Type(); }
+#else
+    { return m_exec.template shepherd_broadcast<Type>( value , m_team_size , rank ); }
+#endif
+
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION Type team_reduce( const Type & value ) const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return Type(); }
+#else
+    { return m_exec.template shepherd_reduce<Type>( m_team_size , value ); }
+#endif
+
+  template< typename JoinOp >
+  KOKKOS_INLINE_FUNCTION typename JoinOp::value_type
+    team_reduce( const typename JoinOp::value_type & value
+               , const JoinOp & op ) const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return typename JoinOp::value_type(); }
+#else
+    { return m_exec.template shepherd_reduce<JoinOp>( m_team_size , value , op ); }
+#endif
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering.
+   *
+   *  The highest rank thread can compute the reduction total as
+   *    reduction_total = dev.team_scan( value ) + value ;
+   */
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION Type team_scan( const Type & value ) const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return Type(); }
+#else
+    { return m_exec.template shepherd_scan<Type>( m_team_size , value ); }
+#endif
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering
+   *          with intra-team non-deterministic ordering accumulation.
+   *
+   *  The global inter-team accumulation value will, at the end of the
+   *  league's parallel execution, be the scan's total.
+   *  Parallel execution ordering of the league's teams is non-deterministic.
+   *  As such the base value for each team's scan operation is similarly
+   *  non-deterministic.
+   */
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION Type team_scan( const Type & value , Type * const global_accum ) const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return Type(); }
+#else
+    { return m_exec.template shepherd_scan<Type>( m_team_size , value , global_accum ); }
+#endif
+
+  //----------------------------------------
+  // Private driver for task-team parallel
+
+  struct TaskTeam {};
+
+  QthreadTeamPolicyMember();
+  explicit QthreadTeamPolicyMember( const TaskTeam & );
+
+  //----------------------------------------
+  // Private for the driver ( for ( member_type i(exec,team); i ; i.next_team() ) { ... }
+
+  // Initialize
+  template< class ... Properties >
+  QthreadTeamPolicyMember( Impl::QthreadExec & exec
+                         , const Kokkos::Impl::TeamPolicyInternal<Qthread,Properties...> & team )
+    : m_exec( exec )
+    , m_team_shared(0,0)
+    , m_team_size(   team.m_team_size )
+    , m_team_rank(   exec.shepherd_worker_rank() )
+    , m_league_size( team.m_league_size )
+    , m_league_end(  team.m_league_size - team.m_shepherd_iter * ( exec.shepherd_size() - ( exec.shepherd_rank() + 1 ) ) )
+    , m_league_rank( m_league_end > team.m_shepherd_iter ? m_league_end - team.m_shepherd_iter : 0 )
+  {
+    m_exec.shared_reset( m_team_shared );
+  }
+
+  // Continue
+  operator bool () const { return m_league_rank < m_league_end ; }
+
+  // iterate
+  void next_team() { ++m_league_rank ; m_exec.shared_reset( m_team_shared ); }
+};
+
+
+template< class ... Properties >
+class TeamPolicyInternal< Kokkos::Qthread , Properties ... >
+  : public PolicyTraits< Properties... >
+{
+private:
+
+  const int m_league_size ;
+  const int m_team_size ;
+  const int m_shepherd_iter ;
+
+public:
+
+  //! Tag this class as a kokkos execution policy
+  typedef TeamPolicyInternal  execution_policy ;
+  typedef Qthread             execution_space ;
+  typedef PolicyTraits< Properties ... >  traits ;
+
+  //----------------------------------------
+
+  template< class FunctorType >
+  inline static
+  int team_size_max( const FunctorType & )
+    { return Qthread::instance().shepherd_worker_size(); }
+
+  template< class FunctorType >
+  static int team_size_recommended( const FunctorType & f )
+    { return team_size_max( f ); }
+
+  template< class FunctorType >
+  inline static
+  int team_size_recommended( const FunctorType & f , const int& )
+    { return team_size_max( f ); }
+
+  //----------------------------------------
+
+  inline int team_size()   const { return m_team_size ; }
+  inline int league_size() const { return m_league_size ; }
+
+  // One active team per shepherd
+  TeamPolicyInternal( Kokkos::Qthread & q
+                    , const int league_size
+                    , const int team_size
+                    , const int /* vector_length */ = 0
+                    )
+    : m_league_size( league_size )
+    , m_team_size( team_size < q.shepherd_worker_size()
+                 ? team_size : q.shepherd_worker_size() )
+    , m_shepherd_iter( ( league_size + q.shepherd_size() - 1 ) / q.shepherd_size() )
+    {
+    }
+
+  // One active team per shepherd
+  TeamPolicyInternal( const int league_size
+                    , const int team_size
+                    , const int /* vector_length */ = 0
+                    )
+    : m_league_size( league_size )
+    , m_team_size( team_size < Qthread::instance().shepherd_worker_size()
+                 ? team_size : Qthread::instance().shepherd_worker_size() )
+    , m_shepherd_iter( ( league_size + Qthread::instance().shepherd_size() - 1 ) / Qthread::instance().shepherd_size() )
+    {
+    }
+
+  typedef Impl::QthreadTeamPolicyMember member_type ;
+
+  friend class Impl::QthreadTeamPolicyMember ;
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #define KOKKOS_QTHREADEXEC_HPP */
+
diff --git a/lib/kokkos/core/src/Qthread/Kokkos_Qthread_Parallel.hpp b/lib/kokkos/core/src/Qthread/Kokkos_Qthread_Parallel.hpp
new file mode 100644
index 0000000000..5b6419289f
--- /dev/null
+++ b/lib/kokkos/core/src/Qthread/Kokkos_Qthread_Parallel.hpp
@@ -0,0 +1,745 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_QTHREAD_PARALLEL_HPP
+#define KOKKOS_QTHREAD_PARALLEL_HPP
+
+#include <vector>
+
+#include <Kokkos_Parallel.hpp>
+
+#include <impl/Kokkos_StaticAssert.hpp>
+#include <impl/Kokkos_FunctorAdapter.hpp>
+
+#include <Qthread/Kokkos_QthreadExec.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+
+template< class FunctorType , class ... Traits >
+class ParallelFor< FunctorType
+                 , Kokkos::RangePolicy< Traits ... >
+                 , Kokkos::Qthread
+                 >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... >  Policy ;
+
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::member_type  Member ;
+  typedef typename Policy::WorkRange    WorkRange ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor , const Member ibeg , const Member iend )
+    {
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( i );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor , const Member ibeg , const Member iend )
+    {
+      const TagType t{} ;
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( t , i );
+      }
+    }
+
+  // Function is called once by every concurrent thread.
+  static void exec( QthreadExec & exec , const void * arg )
+  {
+    const ParallelFor & self = * ((const ParallelFor *) arg );
+
+    const WorkRange range( self.m_policy, exec.worker_rank(), exec.worker_size() );
+
+    ParallelFor::template exec_range< WorkTag > ( self.m_functor , range.begin() , range.end() );
+
+    // All threads wait for completion.
+    exec.exec_all_barrier();
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      Impl::QthreadExec::exec_all( Qthread::instance() , & ParallelFor::exec , this );
+
+    }
+
+  ParallelFor( const FunctorType & arg_functor
+             , const Policy      & arg_policy
+             )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    { }
+};
+
+//----------------------------------------------------------------------------
+
+template< class FunctorType , class ReducerType , class ... Traits >
+class ParallelReduce< FunctorType
+                    , Kokkos::RangePolicy< Traits ... >
+                    , ReducerType
+                    , Kokkos::Qthread
+                    >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... >  Policy ;
+
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::WorkRange    WorkRange ;
+  typedef typename Policy::member_type  Member ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType, ReducerType>::value, FunctorType, ReducerType > ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  // Static Assert WorkTag void if ReducerType not InvalidType
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd, WorkTag > ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType   m_functor ;
+  const Policy        m_policy ;
+  const ReducerType   m_reducer ;
+  const pointer_type  m_result_ptr ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend
+            , reference_type update )
+    {
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( i , update );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend
+            , reference_type update )
+    {
+      const TagType t{} ;
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( t , i , update );
+      }
+    }
+
+  static void exec( QthreadExec & exec , const void * arg )
+  {
+    const ParallelReduce & self = * ((const ParallelReduce *) arg );
+
+    const WorkRange range( self.m_policy, exec.worker_rank(), exec.worker_size() );
+
+    ParallelReduce::template exec_range< WorkTag >(
+      self.m_functor, range.begin(), range.end(),
+      ValueInit::init( ReducerConditional::select(self.m_functor , self.m_reducer)
+                     , exec.exec_all_reduce_value() ) );
+
+    exec.template exec_all_reduce< FunctorType, ReducerType, WorkTag >( self.m_functor, self.m_reducer );
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      QthreadExec::resize_worker_scratch( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) , 0 );
+      Impl::QthreadExec::exec_all( Qthread::instance() , & ParallelReduce::exec , this );
+
+      const pointer_type data = (pointer_type) QthreadExec::exec_all_reduce_result();
+
+      Kokkos::Impl::FunctorFinal< ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer) , data );
+
+      if ( m_result_ptr ) {
+        const unsigned n = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer) );
+        for ( unsigned i = 0 ; i < n ; ++i ) { m_result_ptr[i] = data[i]; }
+      }
+    }
+
+  template< class ViewType >
+  ParallelReduce( const FunctorType  & arg_functor
+                , const Policy       & arg_policy
+                , const ViewType & arg_result_view
+                , typename std::enable_if<Kokkos::is_view< ViewType >::value &&
+                                          !Kokkos::is_reducer_type< ReducerType >::value
+                                          , void*>::type = NULL)
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    , m_reducer( InvalidType() )
+    , m_result_ptr( arg_result_view.data() )
+    { }
+
+  ParallelReduce( const FunctorType & arg_functor
+                , Policy       arg_policy
+                , const ReducerType& reducer )
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    , m_reducer( reducer )
+    , m_result_ptr( reducer.result_view().data() )
+    { }
+};
+
+//----------------------------------------------------------------------------
+
+template< class FunctorType , class ... Properties >
+class ParallelFor< FunctorType
+                 , TeamPolicy< Properties ... >
+                 , Kokkos::Qthread >
+{
+private:
+
+  typedef Kokkos::Impl::TeamPolicyInternal< Kokkos::Qthread , Properties ... > Policy ;
+  typedef typename Policy::member_type  Member ;
+  typedef typename Policy::work_tag     WorkTag ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      while ( member ) {
+        functor( member );
+        member.team_barrier();
+        member.next_team();
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      const TagType t{} ;
+      while ( member ) {
+        functor( t , member );
+        member.team_barrier();
+        member.next_team();
+      }
+    }
+
+  static void exec( QthreadExec & exec , const void * arg )
+  {
+    const ParallelFor & self = * ((const ParallelFor *) arg );
+
+    ParallelFor::template exec_team< WorkTag >
+      ( self.m_functor , Member( exec , self.m_policy ) );
+
+    exec.exec_all_barrier();
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      QthreadExec::resize_worker_scratch
+        ( /* reduction   memory */ 0
+        , /* team shared memory */ FunctorTeamShmemSize< FunctorType >::value( m_functor , m_policy.team_size() ) );
+      Impl::QthreadExec::exec_all( Qthread::instance() , & ParallelFor::exec , this );
+    }
+
+  ParallelFor( const FunctorType & arg_functor ,
+               const Policy      & arg_policy )
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    { }
+};
+
+//----------------------------------------------------------------------------
+
+template< class FunctorType , class ReducerType , class ... Properties >
+class ParallelReduce< FunctorType
+                    , TeamPolicy< Properties... >
+                    , ReducerType
+                    , Kokkos::Qthread
+                    >
+{
+private:
+
+  typedef Kokkos::Impl::TeamPolicyInternal< Kokkos::Qthread , Properties ... > Policy ;
+
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::member_type  Member ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd , WorkTag >  ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd , WorkTag >  ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+  const ReducerType  m_reducer ;
+  const pointer_type m_result_ptr ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_team( const FunctorType & functor , Member member , reference_type update )
+    {
+      while ( member ) {
+        functor( member , update );
+        member.team_barrier();
+        member.next_team();
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_team( const FunctorType & functor , Member member , reference_type update )
+    {
+      const TagType t{} ;
+      while ( member ) {
+        functor( t , member , update );
+        member.team_barrier();
+        member.next_team();
+      }
+    }
+
+  static void exec( QthreadExec & exec , const void * arg )
+  {
+    const ParallelReduce & self = * ((const ParallelReduce *) arg );
+
+    ParallelReduce::template exec_team< WorkTag >
+      ( self.m_functor
+      , Member( exec , self.m_policy )
+      , ValueInit::init( ReducerConditional::select( self.m_functor , self.m_reducer )
+                       , exec.exec_all_reduce_value() ) );
+
+    exec.template exec_all_reduce< FunctorType, ReducerType, WorkTag >( self.m_functor, self.m_reducer );
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      QthreadExec::resize_worker_scratch
+        ( /* reduction   memory */ ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) )
+        , /* team shared memory */ FunctorTeamShmemSize< FunctorType >::value( m_functor , m_policy.team_size() ) );
+
+      Impl::QthreadExec::exec_all( Qthread::instance() , & ParallelReduce::exec , this );
+
+      const pointer_type data = (pointer_type) QthreadExec::exec_all_reduce_result();
+
+      Kokkos::Impl::FunctorFinal< ReducerTypeFwd , WorkTag >::final( ReducerConditional::select(m_functor , m_reducer), data );
+
+      if ( m_result_ptr ) {
+        const unsigned n = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer) );
+        for ( unsigned i = 0 ; i < n ; ++i ) { m_result_ptr[i] = data[i]; }
+      }
+    }
+
+  template< class ViewType >
+  ParallelReduce( const FunctorType & arg_functor
+                , const Policy      & arg_policy
+                , const ViewType    & arg_result
+                , typename std::enable_if<Kokkos::is_view< ViewType >::value &&
+                                          !Kokkos::is_reducer_type< ReducerType >::value
+                                          , void*>::type = NULL)
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    , m_reducer( InvalidType() )
+    , m_result_ptr( arg_result.ptr_on_device() )
+    { }
+
+  inline
+  ParallelReduce( const FunctorType & arg_functor
+                , Policy       arg_policy
+                , const ReducerType& reducer )
+  : m_functor( arg_functor )
+  , m_policy( arg_policy )
+  , m_reducer( reducer )
+  , m_result_ptr( reducer.result_view().data() )
+  { }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+template< class FunctorType , class ... Traits >
+class ParallelScan< FunctorType
+                  , Kokkos::RangePolicy< Traits ... >
+                  , Kokkos::Qthread
+                  >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... >  Policy ;
+
+  typedef typename Policy::work_tag     WorkTag ;
+  typedef typename Policy::WorkRange    WorkRange ;
+  typedef typename Policy::member_type  Member ;
+
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   FunctorType, WorkTag > ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend
+            , reference_type update , const bool final )
+    {
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( i , update , final );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend
+            , reference_type update , const bool final )
+    {
+      const TagType t{} ;
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( t , i , update , final );
+      }
+    }
+
+  static void exec( QthreadExec & exec , const void * arg )
+  {
+    const ParallelScan & self = * ((const ParallelScan *) arg );
+
+    const WorkRange range( self.m_policy , exec.worker_rank() , exec.worker_size() );
+
+    // Initialize thread-local value
+    reference_type update = ValueInit::init( self.m_functor , exec.exec_all_reduce_value() );
+
+    ParallelScan::template exec_range< WorkTag >( self.m_functor, range.begin() , range.end() , update , false );
+
+    exec.template exec_all_scan< FunctorType , typename Policy::work_tag >( self.m_functor );
+
+    ParallelScan::template exec_range< WorkTag >( self.m_functor , range.begin() , range.end() , update , true );
+
+    exec.exec_all_barrier();
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      QthreadExec::resize_worker_scratch( ValueTraits::value_size( m_functor ) , 0 );
+      Impl::QthreadExec::exec_all( Qthread::instance() , & ParallelScan::exec , this );
+    }
+
+  ParallelScan( const FunctorType & arg_functor
+              , const Policy      & arg_policy
+              )
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    {
+    }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember>
+TeamThreadRange(const Impl::QthreadTeamPolicyMember& thread, const iType& count)
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember>(thread,count);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember>
+TeamThreadRange( const Impl::QthreadTeamPolicyMember& thread
+               , const iType & begin
+               , const iType & end
+               )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember>(thread,begin,end);
+}
+
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember >
+  ThreadVectorRange(const Impl::QthreadTeamPolicyMember& thread, const iType& count) {
+  return Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember >(thread,count);
+}
+
+
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadSingleStruct<Impl::QthreadTeamPolicyMember> PerTeam(const Impl::QthreadTeamPolicyMember& thread) {
+  return Impl::ThreadSingleStruct<Impl::QthreadTeamPolicyMember>(thread);
+}
+
+KOKKOS_INLINE_FUNCTION
+Impl::VectorSingleStruct<Impl::QthreadTeamPolicyMember> PerThread(const Impl::QthreadTeamPolicyMember& thread) {
+  return Impl::VectorSingleStruct<Impl::QthreadTeamPolicyMember>(thread);
+}
+
+} // namespace Kokkos
+
+namespace Kokkos {
+
+  /** \brief  Inter-thread parallel_for. Executes lambda(iType i) for each i=0..N-1.
+   *
+   * The range i=0..N-1 is mapped to all threads of the the calling thread team.
+   * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember>& loop_boundaries, const Lambda& lambda) {
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+/** \brief  Inter-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all threads of the the calling thread team and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember>& loop_boundaries,
+                     const Lambda & lambda, ValueType& result) {
+
+  result = ValueType();
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    result+=tmp;
+  }
+
+  result = loop_boundaries.thread.team_reduce(result,Impl::JoinAdd<ValueType>());
+}
+
+#if defined( KOKKOS_HAVE_CXX11 )
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember>& loop_boundaries,
+                     const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+  ValueType result = init_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    join(result,tmp);
+  }
+
+  init_result = loop_boundaries.thread.team_reduce(result,Impl::JoinLambdaAdapter<ValueType,JoinType>(join));
+}
+
+#endif /* #if defined( KOKKOS_HAVE_CXX11 ) */
+
+} // namespace Kokkos
+
+namespace Kokkos {
+/** \brief  Intra-thread vector parallel_for. Executes lambda(iType i) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread.
+ * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember >&
+    loop_boundaries, const Lambda& lambda) {
+  #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+  #pragma ivdep
+  #endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember >&
+      loop_boundaries, const Lambda & lambda, ValueType& result) {
+  result = ValueType();
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    result+=tmp;
+  }
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember >&
+      loop_boundaries, const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+  ValueType result = init_result;
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    join(result,tmp);
+  }
+  init_result = result;
+}
+
+/** \brief  Intra-thread vector parallel exclusive prefix sum. Executes lambda(iType i, ValueType & val, bool final)
+ *          for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes in the thread and a scan operation is performed.
+ * Depending on the target execution space the operator might be called twice: once with final=false
+ * and once with final=true. When final==true val contains the prefix sum value. The contribution of this
+ * "i" needs to be added to val no matter whether final==true or not. In a serial execution
+ * (i.e. team_size==1) the operator is only called once with final==true. Scan_val will be set
+ * to the final sum value over all vector lanes.
+ * This functionality requires C++11 support.*/
+template< typename iType, class FunctorType >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::QthreadTeamPolicyMember >&
+      loop_boundaries, const FunctorType & lambda) {
+
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
+  typedef typename ValueTraits::value_type value_type ;
+
+  value_type scan_val = value_type();
+
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,scan_val,true);
+  }
+}
+
+} // namespace Kokkos
+
+namespace Kokkos {
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::QthreadTeamPolicyMember>& single_struct, const FunctorType& lambda) {
+  lambda();
+}
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::QthreadTeamPolicyMember>& single_struct, const FunctorType& lambda) {
+  if(single_struct.team_member.team_rank()==0) lambda();
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::QthreadTeamPolicyMember>& single_struct, const FunctorType& lambda, ValueType& val) {
+  lambda(val);
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::QthreadTeamPolicyMember>& single_struct, const FunctorType& lambda, ValueType& val) {
+  if(single_struct.team_member.team_rank()==0) {
+    lambda(val);
+  }
+  single_struct.team_member.team_broadcast(val,0);
+}
+
+} // namespace Kokkos
+
+
+#endif /* #define KOKKOS_QTHREAD_PARALLEL_HPP */
+
diff --git a/lib/kokkos/core/src/Qthread/Kokkos_Qthread_TaskPolicy.cpp b/lib/kokkos/core/src/Qthread/Kokkos_Qthread_TaskPolicy.cpp
new file mode 100644
index 0000000000..8cc39d277c
--- /dev/null
+++ b/lib/kokkos/core/src/Qthread/Kokkos_Qthread_TaskPolicy.cpp
@@ -0,0 +1,491 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#include <Kokkos_Core_fwd.hpp>
+
+#if defined( KOKKOS_HAVE_QTHREAD )
+
+#include <stdio.h>
+
+#include <stdlib.h>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include <Kokkos_Atomic.hpp>
+#include <Qthread/Kokkos_Qthread_TaskPolicy.hpp>
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+typedef TaskMember< Kokkos::Qthread , void , void > Task ;
+
+namespace {
+
+inline
+unsigned padded_sizeof_derived( unsigned sizeof_derived )
+{
+  return sizeof_derived +
+    ( sizeof_derived % sizeof(Task*) ? sizeof(Task*) - sizeof_derived % sizeof(Task*) : 0 );
+}
+
+// int lock_alloc_dealloc = 0 ;
+
+} // namespace
+
+void Task::deallocate( void * ptr )
+{
+  // Counting on 'free' thread safety so lock/unlock not required.
+  // However, isolate calls here to mitigate future need to introduce lock/unlock.
+
+  // lock
+
+  // while ( ! Kokkos::atomic_compare_exchange_strong( & lock_alloc_dealloc , 0 , 1 ) );
+
+  free( ptr );
+
+  // unlock
+
+  // Kokkos::atomic_compare_exchange_strong( & lock_alloc_dealloc , 1 , 0 );
+}
+
+void * Task::allocate( const unsigned arg_sizeof_derived
+                     , const unsigned arg_dependence_capacity )
+{
+  // Counting on 'malloc' thread safety so lock/unlock not required.
+  // However, isolate calls here to mitigate future need to introduce lock/unlock.
+
+  // lock
+
+  // while ( ! Kokkos::atomic_compare_exchange_strong( & lock_alloc_dealloc , 0 , 1 ) );
+
+  void * const ptr = malloc( padded_sizeof_derived( arg_sizeof_derived ) + arg_dependence_capacity * sizeof(Task*) );
+
+  // unlock
+
+  // Kokkos::atomic_compare_exchange_strong( & lock_alloc_dealloc , 1 , 0 );
+
+  return ptr ;
+}
+
+Task::~TaskMember()
+{
+
+}
+
+
+Task::TaskMember( const function_verify_type   arg_verify
+                , const function_dealloc_type  arg_dealloc
+                , const function_single_type   arg_apply_single
+                , const function_team_type     arg_apply_team
+                , volatile int &               arg_active_count
+                , const unsigned               arg_sizeof_derived
+                , const unsigned               arg_dependence_capacity
+                )
+  : m_dealloc( arg_dealloc )
+  , m_verify(  arg_verify )
+  , m_apply_single( arg_apply_single )
+  , m_apply_team( arg_apply_team )
+  , m_active_count( & arg_active_count )
+  , m_qfeb(0)
+  , m_dep( (Task **)( ((unsigned char *) this) + padded_sizeof_derived( arg_sizeof_derived ) ) )
+  , m_dep_capacity( arg_dependence_capacity )
+  , m_dep_size( 0 )
+  , m_ref_count( 0 )
+  , m_state( Kokkos::Experimental::TASK_STATE_CONSTRUCTING )
+{
+  qthread_empty( & m_qfeb ); // Set to full when complete
+  for ( unsigned i = 0 ; i < arg_dependence_capacity ; ++i ) m_dep[i] = 0 ;
+}
+
+Task::TaskMember( const function_dealloc_type  arg_dealloc
+                , const function_single_type   arg_apply_single
+                , const function_team_type     arg_apply_team
+                , volatile int &               arg_active_count
+                , const unsigned               arg_sizeof_derived
+                , const unsigned               arg_dependence_capacity
+                )
+  : m_dealloc( arg_dealloc )
+  , m_verify(  & Task::verify_type<void> )
+  , m_apply_single( arg_apply_single )
+  , m_apply_team( arg_apply_team )
+  , m_active_count( & arg_active_count )
+  , m_qfeb(0)
+  , m_dep( (Task **)( ((unsigned char *) this) + padded_sizeof_derived( arg_sizeof_derived ) ) )
+  , m_dep_capacity( arg_dependence_capacity )
+  , m_dep_size( 0 )
+  , m_ref_count( 0 )
+  , m_state( Kokkos::Experimental::TASK_STATE_CONSTRUCTING )
+{
+  qthread_empty( & m_qfeb ); // Set to full when complete
+  for ( unsigned i = 0 ; i < arg_dependence_capacity ; ++i ) m_dep[i] = 0 ;
+}
+
+//----------------------------------------------------------------------------
+
+void Task::throw_error_add_dependence() const
+{
+  std::cerr << "TaskMember< Qthread >::add_dependence ERROR"
+            << " state(" << m_state << ")"
+            << " dep_size(" << m_dep_size << ")"
+            << std::endl ;
+  throw std::runtime_error("TaskMember< Qthread >::add_dependence ERROR");
+}
+
+void Task::throw_error_verify_type()
+{
+  throw std::runtime_error("TaskMember< Qthread >::verify_type ERROR");
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+void Task::assign( Task ** const lhs , Task * rhs , const bool no_throw )
+{
+  static const char msg_error_header[]      = "Kokkos::Impl::TaskManager<Kokkos::Qthread>::assign ERROR" ;
+  static const char msg_error_count[]       = ": negative reference count" ;
+  static const char msg_error_complete[]    = ": destroy task that is not complete" ;
+  static const char msg_error_dependences[] = ": destroy task that has dependences" ;
+  static const char msg_error_exception[]   = ": caught internal exception" ;
+
+  if ( rhs ) { Kokkos::atomic_fetch_add( & (*rhs).m_ref_count , 1 ); }
+
+  Task * const lhs_val = Kokkos::atomic_exchange( lhs , rhs );
+
+  if ( lhs_val ) {
+
+    const int count = Kokkos::atomic_fetch_add( & (*lhs_val).m_ref_count , -1 );
+
+    const char * msg_error = 0 ;
+
+    try {
+
+      if ( 1 == count ) {
+
+        // Reference count at zero, delete it
+
+        // Should only be deallocating a completed task
+        if ( (*lhs_val).m_state == Kokkos::Experimental::TASK_STATE_COMPLETE ) {
+
+          // A completed task should not have dependences...
+          for ( int i = 0 ; i < (*lhs_val).m_dep_size && 0 == msg_error ; ++i ) {
+            if ( (*lhs_val).m_dep[i] ) msg_error = msg_error_dependences ;
+          }
+        }
+        else {
+          msg_error = msg_error_complete ;
+        }
+
+        if ( 0 == msg_error ) {
+          // Get deletion function and apply it
+          const Task::function_dealloc_type d = (*lhs_val).m_dealloc ;
+
+          (*d)( lhs_val );
+        }
+      }
+      else if ( count <= 0 ) {
+        msg_error = msg_error_count ;
+      }
+    }
+    catch( ... ) {
+      if ( 0 == msg_error ) msg_error = msg_error_exception ;
+    }
+
+    if ( 0 != msg_error ) {
+      if ( no_throw ) {
+        std::cerr << msg_error_header << msg_error << std::endl ;
+        std::cerr.flush();
+      }
+      else {
+        std::string msg(msg_error_header);
+        msg.append(msg_error);
+        throw std::runtime_error( msg );
+      }
+    }
+  }
+}
+#endif
+
+
+//----------------------------------------------------------------------------
+
+void Task::closeout()
+{
+  enum { RESPAWN = int( Kokkos::Experimental::TASK_STATE_WAITING ) |
+                   int( Kokkos::Experimental::TASK_STATE_EXECUTING ) };
+
+#if 0
+fprintf( stdout
+       , "worker(%d.%d) task 0x%.12lx %s\n"
+       , qthread_shep()
+       , qthread_worker_local(NULL)
+       , reinterpret_cast<unsigned long>(this)
+       , ( m_state == RESPAWN ? "respawn" : "complete" )
+       );
+fflush(stdout);
+#endif
+
+  // When dependent tasks run there would be a race
+  // condition between destroying this task and
+  // querying the active count pointer from this task.
+  int volatile * const active_count = m_active_count ;
+
+  if ( m_state == RESPAWN ) {
+    // Task requests respawn, set state to waiting and reschedule the task
+    m_state = Kokkos::Experimental::TASK_STATE_WAITING ;
+    schedule();
+  }
+  else {
+
+    // Task did not respawn, is complete
+    m_state = Kokkos::Experimental::TASK_STATE_COMPLETE ;
+
+    // Release dependences before allowing dependent tasks to run.
+    // Otherwise there is a thread race condition for removing dependences.
+    for ( int i = 0 ; i < m_dep_size ; ++i ) {
+      assign( & m_dep[i] , 0 );
+    }
+
+    // Set qthread FEB to full so that dependent tasks are allowed to execute.
+    // This 'task' may be deleted immediately following this function call.
+    qthread_fill( & m_qfeb );
+
+    // The dependent task could now complete and destroy 'this' task
+    // before the call to 'qthread_fill' returns.  Therefore, for
+    // thread safety assume that 'this' task has now been destroyed.
+  }
+
+  // Decrement active task count before returning.
+  Kokkos::atomic_decrement( active_count );
+}
+
+aligned_t Task::qthread_func( void * arg )
+{
+  Task * const task = reinterpret_cast< Task * >(arg);
+
+  // First member of the team change state to executing.
+  // Use compare-exchange to avoid race condition with a respawn.
+  Kokkos::atomic_compare_exchange_strong( & task->m_state
+                                        , int(Kokkos::Experimental::TASK_STATE_WAITING)
+                                        , int(Kokkos::Experimental::TASK_STATE_EXECUTING)
+                                        );
+
+  if ( task->m_apply_team && ! task->m_apply_single ) {
+    Kokkos::Impl::QthreadTeamPolicyMember::TaskTeam task_team_tag ;
+
+    // Initialize team size and rank with shephered info
+    Kokkos::Impl::QthreadTeamPolicyMember member( task_team_tag );
+
+    (*task->m_apply_team)( task , member );
+
+#if 0
+fprintf( stdout
+       , "worker(%d.%d) task 0x%.12lx executed by member(%d:%d)\n"
+       , qthread_shep()
+       , qthread_worker_local(NULL)
+       , reinterpret_cast<unsigned long>(task)
+       , member.team_rank()
+       , member.team_size()
+       );
+fflush(stdout);
+#endif
+
+    member.team_barrier();
+    if ( member.team_rank() == 0 ) task->closeout();
+    member.team_barrier();
+  }
+  else if ( task->m_apply_team && task->m_apply_single == reinterpret_cast<function_single_type>(1) ) {
+    // Team hard-wired to one, no cloning
+    Kokkos::Impl::QthreadTeamPolicyMember member ;
+    (*task->m_apply_team)( task , member );
+    task->closeout();
+  }
+  else {
+    (*task->m_apply_single)( task );
+    task->closeout();
+  }
+
+#if 0
+fprintf( stdout
+       , "worker(%d.%d) task 0x%.12lx return\n"
+       , qthread_shep()
+       , qthread_worker_local(NULL)
+       , reinterpret_cast<unsigned long>(task)
+       );
+fflush(stdout);
+#endif
+
+  return 0 ;
+}
+
+void Task::respawn()
+{
+  // Change state from pure executing to ( waiting | executing )
+  // to avoid confusion with simply waiting.
+  Kokkos::atomic_compare_exchange_strong( & m_state
+                                        , int(Kokkos::Experimental::TASK_STATE_EXECUTING)
+                                        , int(Kokkos::Experimental::TASK_STATE_WAITING |
+                                              Kokkos::Experimental::TASK_STATE_EXECUTING)
+                                        );
+}
+
+void Task::schedule()
+{
+  // Is waiting for execution
+
+  // Increment active task count before spawning.
+  Kokkos::atomic_increment( m_active_count );
+
+  // spawn in qthread.  must malloc the precondition array and give to qthread.
+  // qthread will eventually free this allocation so memory will not be leaked.
+
+  // concern with thread safety of malloc, does this need to be guarded?
+  aligned_t ** qprecon = (aligned_t **) malloc( ( m_dep_size + 1 ) * sizeof(aligned_t *) );
+
+  qprecon[0] = reinterpret_cast<aligned_t *>( uintptr_t(m_dep_size) );
+
+  for ( int i = 0 ; i < m_dep_size ; ++i ) {
+    qprecon[i+1] = & m_dep[i]->m_qfeb ; // Qthread precondition flag
+  }
+
+  if ( m_apply_team && ! m_apply_single ) {
+    // If more than one shepherd spawn on a shepherd other than this shepherd
+    const int num_shepherd            = qthread_num_shepherds();
+    const int num_worker_per_shepherd = qthread_num_workers_local(NO_SHEPHERD);
+    const int this_shepherd           = qthread_shep();
+
+    int spawn_shepherd = ( this_shepherd + 1 ) % num_shepherd ;
+
+#if 0
+fprintf( stdout
+       , "worker(%d.%d) task 0x%.12lx spawning on shepherd(%d) clone(%d)\n"
+       , qthread_shep()
+       , qthread_worker_local(NULL)
+       , reinterpret_cast<unsigned long>(this)
+       , spawn_shepherd
+       , num_worker_per_shepherd - 1
+       );
+fflush(stdout);
+#endif
+
+    qthread_spawn_cloneable
+      ( & Task::qthread_func
+      , this
+      , 0
+      , NULL
+      , m_dep_size , qprecon /* dependences */
+      , spawn_shepherd
+      , unsigned( QTHREAD_SPAWN_SIMPLE | QTHREAD_SPAWN_LOCAL_PRIORITY )
+      , num_worker_per_shepherd - 1
+      );
+  }
+  else {
+    qthread_spawn( & Task::qthread_func /* function */
+                 , this                 /* function argument */
+                 , 0
+                 , NULL
+                 , m_dep_size , qprecon /* dependences */
+                 , NO_SHEPHERD
+                 , QTHREAD_SPAWN_SIMPLE /* allows optimization for non-blocking task */
+                 );
+  }
+}
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+namespace Kokkos {
+namespace Experimental {
+
+TaskPolicy< Kokkos::Qthread >::
+TaskPolicy
+  ( const unsigned /* arg_task_max_count */
+  , const unsigned /* arg_task_max_size */
+  , const unsigned arg_task_default_dependence_capacity 
+  , const unsigned arg_task_team_size
+  )
+  : m_default_dependence_capacity( arg_task_default_dependence_capacity )
+  , m_team_size( arg_task_team_size != 0 ? arg_task_team_size : unsigned(qthread_num_workers_local(NO_SHEPHERD)) )
+  , m_active_count_root(0)
+  , m_active_count( m_active_count_root )
+{
+  const unsigned num_worker_per_shepherd = unsigned( qthread_num_workers_local(NO_SHEPHERD) );
+
+  if ( m_team_size != 1 && m_team_size != num_worker_per_shepherd ) {
+    std::ostringstream msg ;
+    msg << "Kokkos::Experimental::TaskPolicy< Kokkos::Qthread >( "
+        << "default_depedence = " << arg_task_default_dependence_capacity
+        << " , team_size = " << arg_task_team_size
+        << " ) ERROR, valid team_size arguments are { (omitted) , 1 , " << num_worker_per_shepherd << " }" ;
+    Kokkos::Impl::throw_runtime_exception(msg.str());
+  }
+}
+
+TaskPolicy< Kokkos::Qthread >::member_type &
+TaskPolicy< Kokkos::Qthread >::member_single()
+{
+  static member_type s ;
+  return s ;
+}
+
+void wait( Kokkos::Experimental::TaskPolicy< Kokkos::Qthread > & policy )
+{
+  volatile int * const active_task_count = & policy.m_active_count ;
+  while ( *active_task_count ) qthread_yield();
+}
+
+} // namespace Experimental
+} // namespace Kokkos
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #if defined( KOKKOS_HAVE_QTHREAD ) */
+
diff --git a/lib/kokkos/core/src/Qthread/Kokkos_Qthread_TaskPolicy.hpp b/lib/kokkos/core/src/Qthread/Kokkos_Qthread_TaskPolicy.hpp
new file mode 100644
index 0000000000..22a565503d
--- /dev/null
+++ b/lib/kokkos/core/src/Qthread/Kokkos_Qthread_TaskPolicy.hpp
@@ -0,0 +1,664 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#ifndef KOKKOS_QTHREAD_TASKPOLICY_HPP
+#define KOKKOS_QTHREAD_TASKPOLICY_HPP
+
+#include <string>
+#include <typeinfo>
+#include <stdexcept>
+
+//----------------------------------------------------------------------------
+// Defines to enable experimental Qthread functionality
+
+#define QTHREAD_LOCAL_PRIORITY
+#define CLONED_TASKS
+
+#include <qthread.h>
+
+#undef QTHREAD_LOCAL_PRIORITY
+#undef CLONED_TASKS
+
+//----------------------------------------------------------------------------
+
+#include <Kokkos_Qthread.hpp>
+#include <Kokkos_TaskPolicy.hpp>
+#include <Kokkos_View.hpp>
+
+#include <impl/Kokkos_FunctorAdapter.hpp>
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template<>
+class TaskMember< Kokkos::Qthread , void , void >
+{
+public:
+
+  typedef TaskMember * (* function_verify_type) ( TaskMember * );
+  typedef void         (* function_single_type) ( TaskMember * );
+  typedef void         (* function_team_type)   ( TaskMember * , Kokkos::Impl::QthreadTeamPolicyMember & );
+  typedef void         (* function_dealloc_type)( TaskMember * );
+
+private:
+
+  const function_dealloc_type  m_dealloc ;       ///< Deallocation
+  const function_verify_type   m_verify ;        ///< Result type verification
+  const function_single_type   m_apply_single ;  ///< Apply function
+  const function_team_type     m_apply_team ;    ///< Apply function
+  int volatile * const         m_active_count ;  ///< Count of active tasks on this policy
+  aligned_t                    m_qfeb ;          ///< Qthread full/empty bit
+  TaskMember ** const          m_dep ;           ///< Dependences
+  const int                    m_dep_capacity ;  ///< Capacity of dependences
+  int                          m_dep_size ;      ///< Actual count of dependences
+  int                          m_ref_count ;     ///< Reference count
+  int                          m_state ;         ///< State of the task
+
+  TaskMember() /* = delete */ ;
+  TaskMember( const TaskMember & ) /* = delete */ ;
+  TaskMember & operator = ( const TaskMember & ) /* = delete */ ;
+
+  static aligned_t qthread_func( void * arg );
+
+  static void * allocate( const unsigned arg_sizeof_derived , const unsigned arg_dependence_capacity );
+  static void   deallocate( void * );
+
+  void throw_error_add_dependence() const ;
+  static void throw_error_verify_type();
+
+  template < class DerivedTaskType >
+  static
+  void deallocate( TaskMember * t )
+    {
+      DerivedTaskType * ptr = static_cast< DerivedTaskType * >(t);
+      ptr->~DerivedTaskType();
+      deallocate( (void *) ptr );
+    }
+
+  void schedule();
+  void closeout();
+
+protected :
+
+  ~TaskMember();
+
+  // Used by TaskMember< Qthread , ResultType , void >
+  TaskMember( const function_verify_type   arg_verify
+            , const function_dealloc_type  arg_dealloc
+            , const function_single_type   arg_apply_single
+            , const function_team_type     arg_apply_team
+            , volatile int &               arg_active_count
+            , const unsigned               arg_sizeof_derived
+            , const unsigned               arg_dependence_capacity
+            );
+
+  // Used for TaskMember< Qthread , void , void >
+  TaskMember( const function_dealloc_type  arg_dealloc
+            , const function_single_type   arg_apply_single
+            , const function_team_type     arg_apply_team
+            , volatile int &               arg_active_count
+            , const unsigned               arg_sizeof_derived
+            , const unsigned               arg_dependence_capacity
+            );
+
+public:
+
+  template< typename ResultType >
+  KOKKOS_FUNCTION static
+  TaskMember * verify_type( TaskMember * t )
+    {
+      enum { check_type = ! Kokkos::Impl::is_same< ResultType , void >::value };
+
+      if ( check_type && t != 0 ) {
+
+        // Verify that t->m_verify is this function
+        const function_verify_type self = & TaskMember::template verify_type< ResultType > ;
+
+        if ( t->m_verify != self ) {
+          t = 0 ;
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+          throw_error_verify_type();
+#endif
+        }
+      }
+      return t ;
+    }
+
+  //----------------------------------------
+  /*  Inheritence Requirements on task types:
+   *    typedef  FunctorType::value_type  value_type ;
+   *    class DerivedTaskType
+   *      : public TaskMember< Qthread , value_type , FunctorType >
+   *      { ... };
+   *    class TaskMember< Qthread , value_type , FunctorType >
+   *      : public TaskMember< Qthread , value_type , void >
+   *      , public Functor
+   *      { ... };
+   *  If value_type != void
+   *    class TaskMember< Qthread , value_type , void >
+   *      : public TaskMember< Qthread , void , void >
+   *
+   *  Allocate space for DerivedTaskType followed by TaskMember*[ dependence_capacity ]
+   *
+   */
+
+  /** \brief  Allocate and construct a single-thread task */
+  template< class DerivedTaskType >
+  static
+  TaskMember * create_single( const typename DerivedTaskType::functor_type &  arg_functor
+                            , volatile int &                                  arg_active_count
+                            , const unsigned                                  arg_dependence_capacity )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+      typedef typename functor_type::value_type       value_type ;
+
+      DerivedTaskType * const task =
+        new( allocate( sizeof(DerivedTaskType) , arg_dependence_capacity ) )
+          DerivedTaskType( & TaskMember::template deallocate< DerivedTaskType >
+                         , & TaskMember::template apply_single< functor_type , value_type >
+                         , 0
+                         , arg_active_count
+                         , sizeof(DerivedTaskType)
+                         , arg_dependence_capacity
+                         , arg_functor );
+
+      return static_cast< TaskMember * >( task );
+    }
+
+  /** \brief  Allocate and construct a team-thread task */
+  template< class DerivedTaskType >
+  static
+  TaskMember * create_team( const typename DerivedTaskType::functor_type &  arg_functor
+                          , volatile int &                                  arg_active_count
+                          , const unsigned                                  arg_dependence_capacity
+                          , const bool                                      arg_is_team )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+      typedef typename functor_type::value_type       value_type ;
+
+      const function_single_type flag = reinterpret_cast<function_single_type>( arg_is_team ? 0 : 1 );
+
+      DerivedTaskType * const task =
+        new( allocate( sizeof(DerivedTaskType) , arg_dependence_capacity ) )
+          DerivedTaskType( & TaskMember::template deallocate< DerivedTaskType >
+                         , flag
+                         , & TaskMember::template apply_team< functor_type , value_type >
+                         , arg_active_count
+                         , sizeof(DerivedTaskType)
+                         , arg_dependence_capacity
+                         , arg_functor );
+
+      return static_cast< TaskMember * >( task );
+    }
+
+  void respawn();
+  void spawn()
+    {
+       m_state = Kokkos::Experimental::TASK_STATE_WAITING ;
+       schedule();
+    }
+
+  //----------------------------------------
+
+  typedef FutureValueTypeIsVoidError get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const { return get_result_type() ; }
+
+  KOKKOS_INLINE_FUNCTION
+  Kokkos::Experimental::TaskState get_state() const { return Kokkos::Experimental::TaskState( m_state ); }
+
+  //----------------------------------------
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+  static
+  void assign( TaskMember ** const lhs , TaskMember * const rhs , const bool no_throw = false );
+#else
+  KOKKOS_INLINE_FUNCTION static
+  void assign( TaskMember ** const lhs , TaskMember * const rhs , const bool no_throw = false ) {}
+#endif
+
+  KOKKOS_INLINE_FUNCTION
+  TaskMember * get_dependence( int i ) const
+    { return ( Kokkos::Experimental::TASK_STATE_EXECUTING == m_state && 0 <= i && i < m_dep_size ) ? m_dep[i] : (TaskMember*) 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  int get_dependence() const
+    { return m_dep_size ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void clear_dependence()
+    {
+      for ( int i = 0 ; i < m_dep_size ; ++i ) assign( m_dep + i , 0 );
+      m_dep_size = 0 ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void add_dependence( TaskMember * before )
+    {
+      if ( ( Kokkos::Experimental::TASK_STATE_CONSTRUCTING == m_state ||
+             Kokkos::Experimental::TASK_STATE_EXECUTING    == m_state ) &&
+           m_dep_size < m_dep_capacity ) {
+        assign( m_dep + m_dep_size , before );
+        ++m_dep_size ;
+      }
+      else {
+        throw_error_add_dependence();
+      }
+    }
+
+  //----------------------------------------
+
+  template< class FunctorType , class ResultType >
+  KOKKOS_INLINE_FUNCTION static
+  void apply_single( typename Kokkos::Impl::enable_if< ! Kokkos::Impl::is_same< ResultType , void >::value , TaskMember * >::type t )
+    {
+      typedef TaskMember< Kokkos::Qthread , ResultType , FunctorType > derived_type ;
+
+      // TaskMember< Kokkos::Qthread , ResultType , FunctorType >
+      //   : public TaskMember< Kokkos::Qthread , ResultType , void >
+      //   , public FunctorType
+      //   { ... };
+
+      derived_type & m = * static_cast< derived_type * >( t );
+
+      Kokkos::Impl::FunctorApply< FunctorType , void , ResultType & >::apply( (FunctorType &) m , & m.m_result );
+    }
+
+  template< class FunctorType , class ResultType >
+  KOKKOS_INLINE_FUNCTION static
+  void apply_single( typename Kokkos::Impl::enable_if< Kokkos::Impl::is_same< ResultType , void >::value , TaskMember * >::type t )
+    {
+      typedef TaskMember< Kokkos::Qthread , ResultType , FunctorType > derived_type ;
+
+      // TaskMember< Kokkos::Qthread , ResultType , FunctorType >
+      //   : public TaskMember< Kokkos::Qthread , ResultType , void >
+      //   , public FunctorType
+      //   { ... };
+
+      derived_type & m = * static_cast< derived_type * >( t );
+
+      Kokkos::Impl::FunctorApply< FunctorType , void , void >::apply( (FunctorType &) m );
+    }
+
+  //----------------------------------------
+
+  template< class FunctorType , class ResultType >
+  KOKKOS_INLINE_FUNCTION static
+  void apply_team( typename Kokkos::Impl::enable_if< ! Kokkos::Impl::is_same< ResultType , void >::value , TaskMember * >::type t
+                 , Kokkos::Impl::QthreadTeamPolicyMember & member )
+    {
+      typedef TaskMember< Kokkos::Qthread , ResultType , FunctorType > derived_type ;
+
+      derived_type & m = * static_cast< derived_type * >( t );
+
+      m.FunctorType::apply( member , m.m_result );
+    }
+
+  template< class FunctorType , class ResultType >
+  KOKKOS_INLINE_FUNCTION static
+  void apply_team( typename Kokkos::Impl::enable_if< Kokkos::Impl::is_same< ResultType , void >::value , TaskMember * >::type t
+                 , Kokkos::Impl::QthreadTeamPolicyMember & member )
+    {
+      typedef TaskMember< Kokkos::Qthread , ResultType , FunctorType > derived_type ;
+
+      derived_type & m = * static_cast< derived_type * >( t );
+
+      m.FunctorType::apply( member );
+    }
+};
+
+//----------------------------------------------------------------------------
+/** \brief  Base class for tasks with a result value in the Qthread execution space.
+ *
+ *  The FunctorType must be void because this class is accessed by the
+ *  Future class for the task and result value.
+ *
+ *  Must be derived from TaskMember<S,void,void> 'root class' so the Future class
+ *  can correctly static_cast from the 'root class' to this class.
+ */
+template < class ResultType >
+class TaskMember< Kokkos::Qthread , ResultType , void >
+  : public TaskMember< Kokkos::Qthread , void , void >
+{
+public:
+
+  ResultType  m_result ;
+
+  typedef const ResultType & get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const { return m_result ; }
+
+protected:
+
+  typedef TaskMember< Kokkos::Qthread , void , void >  task_root_type ;
+  typedef task_root_type::function_dealloc_type        function_dealloc_type ;
+  typedef task_root_type::function_single_type         function_single_type ;
+  typedef task_root_type::function_team_type           function_team_type ;
+
+  inline
+  TaskMember( const function_dealloc_type  arg_dealloc
+            , const function_single_type   arg_apply_single
+            , const function_team_type     arg_apply_team
+            , volatile int &               arg_active_count
+            , const unsigned               arg_sizeof_derived
+            , const unsigned               arg_dependence_capacity
+            )
+    : task_root_type( & task_root_type::template verify_type< ResultType >
+                    , arg_dealloc
+                    , arg_apply_single
+                    , arg_apply_team
+                    , arg_active_count
+                    , arg_sizeof_derived
+                    , arg_dependence_capacity )
+    , m_result()
+    {}
+};
+
+template< class ResultType , class FunctorType >
+class TaskMember< Kokkos::Qthread , ResultType , FunctorType >
+  : public TaskMember< Kokkos::Qthread , ResultType , void >
+  , public FunctorType
+{
+public:
+
+  typedef FunctorType  functor_type ;
+
+  typedef TaskMember< Kokkos::Qthread , void , void >        task_root_type ;
+  typedef TaskMember< Kokkos::Qthread , ResultType , void >  task_base_type ;
+  typedef task_root_type::function_dealloc_type              function_dealloc_type ;
+  typedef task_root_type::function_single_type               function_single_type ;
+  typedef task_root_type::function_team_type                 function_team_type ;
+
+  inline
+  TaskMember( const function_dealloc_type  arg_dealloc
+            , const function_single_type   arg_apply_single
+            , const function_team_type     arg_apply_team
+            , volatile int &               arg_active_count
+            , const unsigned               arg_sizeof_derived
+            , const unsigned               arg_dependence_capacity
+            , const functor_type &         arg_functor
+            )
+    : task_base_type( arg_dealloc
+                    , arg_apply_single
+                    , arg_apply_team
+                    , arg_active_count
+                    , arg_sizeof_derived
+                    , arg_dependence_capacity )
+    , functor_type( arg_functor )
+    {}
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+void wait( TaskPolicy< Kokkos::Qthread > & );
+
+template<>
+class TaskPolicy< Kokkos::Qthread >
+{
+public:
+
+  typedef Kokkos::Qthread                        execution_space ;
+  typedef TaskPolicy                             execution_policy ;
+  typedef Kokkos::Impl::QthreadTeamPolicyMember  member_type ;
+
+private:
+
+  typedef Impl::TaskMember< execution_space , void , void > task_root_type ;
+
+  template< class FunctorType >
+  static inline
+  const task_root_type * get_task_root( const FunctorType * f )
+    {
+      typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
+      return static_cast< const task_root_type * >( static_cast< const task_type * >(f) );
+    }
+
+  template< class FunctorType >
+  static inline
+  task_root_type * get_task_root( FunctorType * f )
+    {
+      typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
+      return static_cast< task_root_type * >( static_cast< task_type * >(f) );
+    }
+
+  unsigned        m_default_dependence_capacity ;
+  unsigned        m_team_size ;
+  volatile int    m_active_count_root ;
+  volatile int &  m_active_count ;
+
+public:
+
+  TaskPolicy
+    ( const unsigned arg_task_max_count
+    , const unsigned arg_task_max_size
+    , const unsigned arg_task_default_dependence_capacity = 4
+    , const unsigned arg_task_team_size = 0 /* choose default */
+    );
+
+  KOKKOS_FUNCTION TaskPolicy() = default ;
+  KOKKOS_FUNCTION TaskPolicy( TaskPolicy && rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy( const TaskPolicy & rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy & operator = ( TaskPolicy && rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy & operator = ( const TaskPolicy & rhs ) = default ;
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  int allocated_task_count() const { return m_active_count ; }
+
+  template< class ValueType >
+  const Future< ValueType , execution_space > &
+    spawn( const Future< ValueType , execution_space > & f 
+         , const bool priority = false ) const
+      {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        f.m_task->spawn();
+#endif
+        return f ;
+      }
+
+  // Create single-thread task
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  task_create( const FunctorType & functor
+             , const unsigned dependence_capacity = ~0u ) const
+    {
+      typedef typename FunctorType::value_type value_type ;
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >  task_type ;
+      return Future< value_type , execution_space >(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        task_root_type::create_single< task_type >
+          ( functor
+          , m_active_count
+          , ( ~0u == dependence_capacity ? m_default_dependence_capacity : dependence_capacity )
+          )
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  Future< typename FunctorType::value_type , execution_space >
+  proc_create( const FunctorType & functor
+             , const unsigned dependence_capacity = ~0u ) const
+    { return task_create( functor , dependence_capacity ); }
+
+  // Create thread-team task
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  task_create_team( const FunctorType & functor
+                  , const unsigned dependence_capacity = ~0u ) const
+    {
+      typedef typename FunctorType::value_type  value_type ;
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >  task_type ;
+
+      return Future< value_type , execution_space >(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        task_root_type::create_team< task_type >
+          ( functor
+          , m_active_count
+          , ( ~0u == dependence_capacity ? m_default_dependence_capacity : dependence_capacity )
+          , 1 < m_team_size
+          )
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  proc_create_team( const FunctorType & functor
+                  , const unsigned dependence_capacity = ~0u ) const
+    { return task_create_team( functor , dependence_capacity ); }
+
+  // Add dependence
+  template< class A1 , class A2 , class A3 , class A4 >
+  void add_dependence( const Future<A1,A2> & after
+                     , const Future<A3,A4> & before
+                     , typename Kokkos::Impl::enable_if
+                        < Kokkos::Impl::is_same< typename Future<A1,A2>::execution_space , execution_space >::value
+                          &&
+                          Kokkos::Impl::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
+                        >::type * = 0
+                      )
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      after.m_task->add_dependence( before.m_task );
+#endif
+    }
+
+  //----------------------------------------
+  // Functions for an executing task functor to query dependences,
+  // set new dependences, and respawn itself.
+
+  template< class FunctorType >
+  Future< void , execution_space >
+  get_dependence( const FunctorType * task_functor , int i ) const
+    {
+      return Future<void,execution_space>(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        get_task_root(task_functor)->get_dependence(i)
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  int get_dependence( const FunctorType * task_functor ) const
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return get_task_root(task_functor)->get_dependence(); }
+#else
+    { return 0 ; }
+#endif
+
+  template< class FunctorType >
+  void clear_dependence( FunctorType * task_functor ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      get_task_root(task_functor)->clear_dependence();
+#endif
+    }
+
+  template< class FunctorType , class A3 , class A4 >
+  void add_dependence( FunctorType * task_functor
+                     , const Future<A3,A4> & before
+                     , typename Kokkos::Impl::enable_if
+                        < Kokkos::Impl::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
+                        >::type * = 0
+                      )
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      get_task_root(task_functor)->add_dependence( before.m_task );
+#endif
+    }
+
+  template< class FunctorType >
+  void respawn( FunctorType * task_functor 
+              , const bool priority = false ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      get_task_root(task_functor)->respawn();
+#endif
+    }
+
+  template< class FunctorType >
+  void respawn_needing_memory( FunctorType * task_functor ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      get_task_root(task_functor)->respawn();
+#endif
+    }
+
+  static member_type & member_single();
+
+  friend void wait( TaskPolicy< Kokkos::Qthread > & );
+};
+
+} /* namespace Experimental */
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #define KOKKOS_QTHREAD_TASK_HPP */
+
diff --git a/lib/kokkos/core/src/Qthread/README b/lib/kokkos/core/src/Qthread/README
new file mode 100644
index 0000000000..6e6c86a9ef
--- /dev/null
+++ b/lib/kokkos/core/src/Qthread/README
@@ -0,0 +1,25 @@
+
+# This Qthreads back-end uses an experimental branch of the Qthreads repository with special #define options.
+
+# Cloning repository and branch:
+
+git clone git@github.com:Qthreads/qthreads.git qthreads
+
+cd qthreads
+
+# checkout branch with "cloned tasks"
+
+git checkout dev-kokkos
+
+# Configure/autogen
+
+sh autogen.sh
+
+# configure with 'hwloc' installation:
+
+./configure CFLAGS="-DCLONED_TASKS -DQTHREAD_LOCAL_PRIORITY" --with-hwloc=${HWLOCDIR} --prefix=${INSTALLDIR}
+
+# install
+
+make install
+
diff --git a/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec.cpp b/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec.cpp
new file mode 100644
index 0000000000..5f0b8f70cd
--- /dev/null
+++ b/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec.cpp
@@ -0,0 +1,826 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core_fwd.hpp>
+
+#if defined( KOKKOS_HAVE_PTHREAD ) || defined( KOKKOS_HAVE_WINTHREAD )
+
+#include <stdint.h>
+#include <limits>
+#include <utility>
+#include <iostream>
+#include <sstream>
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <impl/Kokkos_CPUDiscovery.hpp>
+#include <impl/Kokkos_Profiling_Interface.hpp>
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+namespace {
+
+ThreadsExec                  s_threads_process ;
+ThreadsExec                * s_threads_exec[  ThreadsExec::MAX_THREAD_COUNT ] = { 0 };
+pthread_t                    s_threads_pid[   ThreadsExec::MAX_THREAD_COUNT ] = { 0 };
+std::pair<unsigned,unsigned> s_threads_coord[ ThreadsExec::MAX_THREAD_COUNT ];
+
+int s_thread_pool_size[3] = { 0 , 0 , 0 };
+
+unsigned s_current_reduce_size = 0 ;
+unsigned s_current_shared_size = 0 ;
+
+void (* volatile s_current_function)( ThreadsExec & , const void * );
+const void * volatile s_current_function_arg = 0 ;
+
+struct Sentinel {
+  Sentinel()
+  {
+    HostSpace::register_in_parallel( ThreadsExec::in_parallel );
+  }
+
+  ~Sentinel()
+  {
+    if ( s_thread_pool_size[0] ||
+         s_thread_pool_size[1] ||
+         s_thread_pool_size[2] ||
+         s_current_reduce_size ||
+         s_current_shared_size ||
+         s_current_function ||
+         s_current_function_arg ||
+         s_threads_exec[0] ) {
+      std::cerr << "ERROR : Process exiting without calling Kokkos::Threads::terminate()" << std::endl ;
+    }
+  }
+};
+
+inline
+unsigned fan_size( const unsigned rank , const unsigned size )
+{
+  const unsigned rank_rev = size - ( rank + 1 );
+  unsigned count = 0 ;
+  for ( unsigned n = 1 ; ( rank_rev + n < size ) && ! ( rank_rev & n ) ; n <<= 1 ) { ++count ; }
+  return count ;
+}
+
+} // namespace
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+void execute_function_noop( ThreadsExec & , const void * ) {}
+
+void ThreadsExec::driver(void)
+{
+  ThreadsExec this_thread ;
+
+  while ( ThreadsExec::Active == this_thread.m_pool_state ) {
+
+    (*s_current_function)( this_thread , s_current_function_arg );
+
+    // Deactivate thread and wait for reactivation
+    this_thread.m_pool_state = ThreadsExec::Inactive ;
+
+    wait_yield( this_thread.m_pool_state , ThreadsExec::Inactive );
+  }
+}
+
+ThreadsExec::ThreadsExec()
+  : m_pool_base(0)
+  , m_scratch(0)
+  , m_scratch_reduce_end(0)
+  , m_scratch_thread_end(0)
+  , m_numa_rank(0)
+  , m_numa_core_rank(0)
+  , m_pool_rank(0)
+  , m_pool_size(0)
+  , m_pool_fan_size(0)
+  , m_pool_state( ThreadsExec::Terminating )
+{
+  if ( & s_threads_process != this ) {
+
+    // A spawned thread
+
+    ThreadsExec * const nil = 0 ;
+
+    // Which entry in 's_threads_exec', possibly determined from hwloc binding
+    const int entry = ((size_t)s_current_function_arg) < size_t(s_thread_pool_size[0])
+                    ? ((size_t)s_current_function_arg)
+                    : size_t(Kokkos::hwloc::bind_this_thread( s_thread_pool_size[0] , s_threads_coord ));
+
+    // Given a good entry set this thread in the 's_threads_exec' array
+    if ( entry < s_thread_pool_size[0] &&
+         nil == atomic_compare_exchange( s_threads_exec + entry , nil , this ) ) {
+
+      const std::pair<unsigned,unsigned> coord = Kokkos::hwloc::get_this_thread_coordinate();
+
+      m_numa_rank       = coord.first ;
+      m_numa_core_rank  = coord.second ;
+      m_pool_base       = s_threads_exec ;
+      m_pool_rank       = s_thread_pool_size[0] - ( entry + 1 );
+      m_pool_rank_rev   = s_thread_pool_size[0] - ( pool_rank() + 1 );
+      m_pool_size       = s_thread_pool_size[0] ;
+      m_pool_fan_size   = fan_size( m_pool_rank , m_pool_size );
+      m_pool_state      = ThreadsExec::Active ;
+
+      s_threads_pid[ m_pool_rank ] = pthread_self();
+
+      // Inform spawning process that the threads_exec entry has been set.
+      s_threads_process.m_pool_state = ThreadsExec::Active ;
+    }
+    else {
+      // Inform spawning process that the threads_exec entry could not be set.
+      s_threads_process.m_pool_state = ThreadsExec::Terminating ;
+    }
+  }
+  else {
+    // Enables 'parallel_for' to execute on unitialized Threads device
+    m_pool_rank  = 0 ;
+    m_pool_size  = 1 ;
+    m_pool_state = ThreadsExec::Inactive ;
+
+    s_threads_pid[ m_pool_rank ] = pthread_self();
+  }
+}
+
+ThreadsExec::~ThreadsExec()
+{
+  const unsigned entry = m_pool_size - ( m_pool_rank + 1 );
+
+  typedef Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::HostSpace , void > Record ;
+
+  if ( m_scratch ) {
+    Record * const r = Record::get_record( m_scratch );
+
+    m_scratch = 0 ;
+
+    Record::decrement( r );
+  }
+
+  m_pool_base   = 0 ;
+  m_scratch_reduce_end = 0 ;
+  m_scratch_thread_end = 0 ;
+  m_numa_rank      = 0 ;
+  m_numa_core_rank = 0 ;
+  m_pool_rank      = 0 ;
+  m_pool_size      = 0 ;
+  m_pool_fan_size  = 0 ;
+
+  m_pool_state  = ThreadsExec::Terminating ;
+
+  if ( & s_threads_process != this && entry < MAX_THREAD_COUNT ) {
+    ThreadsExec * const nil = 0 ;
+
+    atomic_compare_exchange( s_threads_exec + entry , this , nil );
+
+    s_threads_process.m_pool_state = ThreadsExec::Terminating ;
+  }
+}
+
+
+int ThreadsExec::get_thread_count()
+{
+  return s_thread_pool_size[0] ;
+}
+
+ThreadsExec * ThreadsExec::get_thread( const int init_thread_rank )
+{
+  ThreadsExec * const th =
+    init_thread_rank < s_thread_pool_size[0]
+    ? s_threads_exec[ s_thread_pool_size[0] - ( init_thread_rank + 1 ) ] : 0 ;
+
+  if ( 0 == th || th->m_pool_rank != init_thread_rank ) {
+    std::ostringstream msg ;
+    msg << "Kokkos::Impl::ThreadsExec::get_thread ERROR : "
+        << "thread " << init_thread_rank << " of " << s_thread_pool_size[0] ;
+    if ( 0 == th ) {
+      msg << " does not exist" ;
+    }
+    else {
+      msg << " has wrong thread_rank " << th->m_pool_rank ;
+    }
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  return th ;
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsExec::execute_sleep( ThreadsExec & exec , const void * )
+{
+  ThreadsExec::global_lock();
+  ThreadsExec::global_unlock();
+
+  const int n = exec.m_pool_fan_size ;
+  const int rank_rev = exec.m_pool_size - ( exec.m_pool_rank + 1 );
+
+  for ( int i = 0 ; i < n ; ++i ) {
+    Impl::spinwait( exec.m_pool_base[ rank_rev + (1<<i) ]->m_pool_state , ThreadsExec::Active );
+  }
+
+  exec.m_pool_state = ThreadsExec::Inactive ;
+}
+
+}
+}
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+void ThreadsExec::verify_is_process( const std::string & name , const bool initialized )
+{
+  if ( ! is_process() ) {
+    std::string msg( name );
+    msg.append( " FAILED : Called by a worker thread, can only be called by the master process." );
+    Kokkos::Impl::throw_runtime_exception( msg );
+  }
+
+  if ( initialized && 0 == s_thread_pool_size[0] ) {
+    std::string msg( name );
+    msg.append( " FAILED : Threads not initialized." );
+    Kokkos::Impl::throw_runtime_exception( msg );
+  }
+}
+
+int ThreadsExec::in_parallel()
+{
+  // A thread function is in execution and
+  // the function argument is not the special threads process argument and
+  // the master process is a worker or is not the master process.
+  return s_current_function &&
+         ( & s_threads_process != s_current_function_arg ) &&
+         ( s_threads_process.m_pool_base || ! is_process() );
+}
+
+// Wait for root thread to become inactive
+void ThreadsExec::fence()
+{
+  if ( s_thread_pool_size[0] ) {
+    // Wait for the root thread to complete:
+    Impl::spinwait( s_threads_exec[0]->m_pool_state , ThreadsExec::Active );
+  }
+
+  s_current_function     = 0 ;
+  s_current_function_arg = 0 ;
+
+  // Make sure function and arguments are cleared before
+  // potentially re-activating threads with a subsequent launch.
+  memory_fence();
+}
+
+/** \brief  Begin execution of the asynchronous functor */
+void ThreadsExec::start( void (*func)( ThreadsExec & , const void * ) , const void * arg )
+{
+  verify_is_process("ThreadsExec::start" , true );
+
+  if ( s_current_function || s_current_function_arg ) {
+    Kokkos::Impl::throw_runtime_exception( std::string( "ThreadsExec::start() FAILED : already executing" ) );
+  }
+
+  s_current_function     = func ;
+  s_current_function_arg = arg ;
+
+  // Make sure function and arguments are written before activating threads.
+  memory_fence();
+
+  // Activate threads:
+  for ( int i = s_thread_pool_size[0] ; 0 < i-- ; ) {
+    s_threads_exec[i]->m_pool_state = ThreadsExec::Active ;
+  }
+
+  if ( s_threads_process.m_pool_size ) {
+    // Master process is the root thread, run it:
+    (*func)( s_threads_process , arg );
+    s_threads_process.m_pool_state = ThreadsExec::Inactive ;
+  }
+}
+
+//----------------------------------------------------------------------------
+
+bool ThreadsExec::sleep()
+{
+  verify_is_process("ThreadsExec::sleep", true );
+
+  if ( & execute_sleep == s_current_function ) return false ;
+
+  fence();
+
+  ThreadsExec::global_lock();
+
+  s_current_function = & execute_sleep ;
+
+  // Activate threads:
+  for ( unsigned i = s_thread_pool_size[0] ; 0 < i ; ) {
+    s_threads_exec[--i]->m_pool_state = ThreadsExec::Active ;
+  }
+
+  return true ;
+}
+
+bool ThreadsExec::wake()
+{
+  verify_is_process("ThreadsExec::wake", true );
+
+  if ( & execute_sleep != s_current_function ) return false ;
+
+  ThreadsExec::global_unlock();
+
+  if ( s_threads_process.m_pool_base ) {
+    execute_sleep( s_threads_process , 0 );
+    s_threads_process.m_pool_state = ThreadsExec::Inactive ;
+  }
+
+  fence();
+
+  return true ;
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsExec::execute_serial( void (*func)( ThreadsExec & , const void * ) )
+{
+  s_current_function = func ;
+  s_current_function_arg = & s_threads_process ;
+
+  // Make sure function and arguments are written before activating threads.
+  memory_fence();
+
+  const unsigned begin = s_threads_process.m_pool_base ? 1 : 0 ;
+
+  for ( unsigned i = s_thread_pool_size[0] ; begin < i ; ) {
+    ThreadsExec & th = * s_threads_exec[ --i ];
+
+    th.m_pool_state = ThreadsExec::Active ;
+
+    wait_yield( th.m_pool_state , ThreadsExec::Active );
+  }
+
+  if ( s_threads_process.m_pool_base ) {
+    s_threads_process.m_pool_state = ThreadsExec::Active ;
+    (*func)( s_threads_process , 0 );
+    s_threads_process.m_pool_state = ThreadsExec::Inactive ;
+  }
+
+  s_current_function_arg = 0 ;
+  s_current_function = 0 ;
+
+  // Make sure function and arguments are cleared before proceeding.
+  memory_fence();
+}
+
+//----------------------------------------------------------------------------
+
+void * ThreadsExec::root_reduce_scratch()
+{
+  return s_threads_process.reduce_memory();
+}
+
+void ThreadsExec::execute_resize_scratch( ThreadsExec & exec , const void * )
+{
+  typedef Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::HostSpace , void > Record ;
+
+  if ( exec.m_scratch ) {
+    Record * const r = Record::get_record( exec.m_scratch );
+
+    exec.m_scratch = 0 ;
+
+    Record::decrement( r );
+  }
+
+  exec.m_scratch_reduce_end = s_threads_process.m_scratch_reduce_end ;
+  exec.m_scratch_thread_end = s_threads_process.m_scratch_thread_end ;
+
+  if ( s_threads_process.m_scratch_thread_end ) {
+
+    // Allocate tracked memory:
+    {
+      Record * const r = Record::allocate( Kokkos::HostSpace() , "thread_scratch" , s_threads_process.m_scratch_thread_end );
+
+      Record::increment( r );
+
+      exec.m_scratch = r->data();
+    }
+
+    unsigned * ptr = reinterpret_cast<unsigned *>( exec.m_scratch );
+
+    unsigned * const end = ptr + s_threads_process.m_scratch_thread_end / sizeof(unsigned);
+
+    // touch on this thread
+    while ( ptr < end ) *ptr++ = 0 ;
+  }
+}
+
+void * ThreadsExec::resize_scratch( size_t reduce_size , size_t thread_size )
+{
+  enum { ALIGN_MASK = Kokkos::Impl::MEMORY_ALIGNMENT - 1 };
+
+  fence();
+
+  const size_t old_reduce_size = s_threads_process.m_scratch_reduce_end ;
+  const size_t old_thread_size = s_threads_process.m_scratch_thread_end - s_threads_process.m_scratch_reduce_end ;
+
+  reduce_size = ( reduce_size + ALIGN_MASK ) & ~ALIGN_MASK ;
+  thread_size = ( thread_size + ALIGN_MASK ) & ~ALIGN_MASK ;
+
+  // Increase size or deallocate completely.
+
+  if ( ( old_reduce_size < reduce_size ) ||
+       ( old_thread_size < thread_size ) ||
+       ( ( reduce_size == 0 && thread_size == 0 ) &&
+         ( old_reduce_size != 0 || old_thread_size != 0 ) ) ) {
+
+    verify_is_process( "ThreadsExec::resize_scratch" , true );
+
+    s_threads_process.m_scratch_reduce_end = reduce_size ;
+    s_threads_process.m_scratch_thread_end = reduce_size + thread_size ;
+
+    execute_serial( & execute_resize_scratch );
+
+    s_threads_process.m_scratch = s_threads_exec[0]->m_scratch ;
+  }
+
+  return s_threads_process.m_scratch ;
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsExec::print_configuration( std::ostream & s , const bool detail )
+{
+  verify_is_process("ThreadsExec::print_configuration",false);
+
+  fence();
+
+  const unsigned numa_count       = Kokkos::hwloc::get_available_numa_count();
+  const unsigned cores_per_numa   = Kokkos::hwloc::get_available_cores_per_numa();
+  const unsigned threads_per_core = Kokkos::hwloc::get_available_threads_per_core();
+
+  // Forestall compiler warnings for unused variables.
+  (void) numa_count;
+  (void) cores_per_numa;
+  (void) threads_per_core;
+
+  s << "Kokkos::Threads" ;
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+  s << " KOKKOS_HAVE_PTHREAD" ;
+#endif
+#if defined( KOKKOS_HAVE_HWLOC )
+  s << " hwloc[" << numa_count << "x" << cores_per_numa << "x" << threads_per_core << "]" ;
+#endif
+
+  if ( s_thread_pool_size[0] ) {
+    s << " threads[" << s_thread_pool_size[0] << "]"
+      << " threads_per_numa[" << s_thread_pool_size[1] << "]"
+      << " threads_per_core[" << s_thread_pool_size[2] << "]"
+      ;
+    if ( 0 == s_threads_process.m_pool_base ) { s << " Asynchronous" ; }
+    s << " ReduceScratch[" << s_current_reduce_size << "]"
+      << " SharedScratch[" << s_current_shared_size << "]" ;
+    s << std::endl ;
+
+    if ( detail ) {
+
+      for ( int i = 0 ; i < s_thread_pool_size[0] ; ++i ) {
+
+        ThreadsExec * const th = s_threads_exec[i] ;
+
+        if ( th ) {
+
+          const int rank_rev = th->m_pool_size - ( th->m_pool_rank + 1 );
+
+          s << " Thread[ " << th->m_pool_rank << " : "
+            << th->m_numa_rank << "." << th->m_numa_core_rank << " ]" ;
+
+          s << " Fan{" ;
+          for ( int j = 0 ; j < th->m_pool_fan_size ; ++j ) {
+            ThreadsExec * const thfan = th->m_pool_base[rank_rev+(1<<j)] ;
+            s << " [ " << thfan->m_pool_rank << " : "
+              << thfan->m_numa_rank << "." << thfan->m_numa_core_rank << " ]" ;
+          }
+          s << " }" ;
+
+          if ( th == & s_threads_process ) {
+            s << " is_process" ;
+          }
+        }
+        s << std::endl ;
+      }
+    }
+  }
+  else {
+    s << " not initialized" << std::endl ;
+  }
+}
+
+//----------------------------------------------------------------------------
+
+int ThreadsExec::is_initialized()
+{ return 0 != s_threads_exec[0] ; }
+
+void ThreadsExec::initialize( unsigned thread_count ,
+                              unsigned use_numa_count ,
+                              unsigned use_cores_per_numa ,
+                              bool allow_asynchronous_threadpool )
+{
+  static const Sentinel sentinel ;
+
+  const bool is_initialized = 0 != s_thread_pool_size[0] ;
+
+  unsigned thread_spawn_failed = 0 ;
+
+  for ( int i = 0; i < ThreadsExec::MAX_THREAD_COUNT ; i++)
+    s_threads_exec[i] = NULL;
+
+  if ( ! is_initialized ) {
+
+    // If thread_count, use_numa_count, or use_cores_per_numa are zero
+    // then they will be given default values based upon hwloc detection
+    // and allowed asynchronous execution.
+
+    const bool hwloc_avail = Kokkos::hwloc::available();
+    const bool hwloc_can_bind = hwloc_avail && Kokkos::hwloc::can_bind_threads();
+
+    if ( thread_count == 0 ) {
+      thread_count = hwloc_avail
+      ? Kokkos::hwloc::get_available_numa_count() *
+        Kokkos::hwloc::get_available_cores_per_numa() *
+        Kokkos::hwloc::get_available_threads_per_core()
+      : 1 ;
+    }
+
+    const unsigned thread_spawn_begin =
+      hwloc::thread_mapping( "Kokkos::Threads::initialize" ,
+                             allow_asynchronous_threadpool ,
+                             thread_count ,
+                             use_numa_count ,
+                             use_cores_per_numa ,
+                             s_threads_coord );
+
+    const std::pair<unsigned,unsigned> proc_coord = s_threads_coord[0] ;
+
+    if ( thread_spawn_begin ) {
+      // Synchronous with s_threads_coord[0] as the process core
+      // Claim entry #0 for binding the process core.
+      s_threads_coord[0] = std::pair<unsigned,unsigned>(~0u,~0u);
+    }
+
+    s_thread_pool_size[0] = thread_count ;
+    s_thread_pool_size[1] = s_thread_pool_size[0] / use_numa_count ;
+    s_thread_pool_size[2] = s_thread_pool_size[1] / use_cores_per_numa ;
+    s_current_function = & execute_function_noop ; // Initialization work function
+
+    for ( unsigned ith = thread_spawn_begin ; ith < thread_count ; ++ith ) {
+
+      s_threads_process.m_pool_state = ThreadsExec::Inactive ;
+
+      // If hwloc available then spawned thread will
+      // choose its own entry in 's_threads_coord'
+      // otherwise specify the entry.
+      s_current_function_arg = (void*)static_cast<uintptr_t>( hwloc_can_bind ? ~0u : ith );
+
+      // Make sure all outstanding memory writes are complete
+      // before spawning the new thread.
+      memory_fence();
+
+      // Spawn thread executing the 'driver()' function.
+      // Wait until spawned thread has attempted to initialize.
+      // If spawning and initialization is successfull then
+      // an entry in 's_threads_exec' will be assigned.
+      if ( ThreadsExec::spawn() ) {
+        wait_yield( s_threads_process.m_pool_state , ThreadsExec::Inactive );
+      }
+      if ( s_threads_process.m_pool_state == ThreadsExec::Terminating ) break ;
+    }
+
+    // Wait for all spawned threads to deactivate before zeroing the function.
+
+    for ( unsigned ith = thread_spawn_begin ; ith < thread_count ; ++ith ) {
+      // Try to protect against cache coherency failure by casting to volatile.
+      ThreadsExec * const th = ((ThreadsExec * volatile *)s_threads_exec)[ith] ;
+      if ( th ) {
+        wait_yield( th->m_pool_state , ThreadsExec::Active );
+      }
+      else {
+        ++thread_spawn_failed ;
+      }
+    }
+
+    s_current_function     = 0 ;
+    s_current_function_arg = 0 ;
+    s_threads_process.m_pool_state = ThreadsExec::Inactive ;
+
+    memory_fence();
+
+    if ( ! thread_spawn_failed ) {
+      // Bind process to the core on which it was located before spawning occured
+      if (hwloc_can_bind) {
+        Kokkos::hwloc::bind_this_thread( proc_coord );
+      }
+
+      if ( thread_spawn_begin ) { // Include process in pool.
+        const std::pair<unsigned,unsigned> coord = Kokkos::hwloc::get_this_thread_coordinate();
+
+        s_threads_exec[0]                   = & s_threads_process ;
+        s_threads_process.m_numa_rank       = coord.first ;
+        s_threads_process.m_numa_core_rank  = coord.second ;
+        s_threads_process.m_pool_base       = s_threads_exec ;
+        s_threads_process.m_pool_rank       = thread_count - 1 ; // Reversed for scan-compatible reductions
+        s_threads_process.m_pool_size       = thread_count ;
+        s_threads_process.m_pool_fan_size   = fan_size( s_threads_process.m_pool_rank , s_threads_process.m_pool_size );
+        s_threads_pid[ s_threads_process.m_pool_rank ] = pthread_self();
+      }
+      else {
+        s_threads_process.m_pool_base = 0 ;
+        s_threads_process.m_pool_rank = 0 ;
+        s_threads_process.m_pool_size = 0 ;
+        s_threads_process.m_pool_fan_size = 0 ;
+      }
+
+      // Initial allocations:
+      ThreadsExec::resize_scratch( 1024 , 1024 );
+    }
+    else {
+      s_thread_pool_size[0] = 0 ;
+      s_thread_pool_size[1] = 0 ;
+      s_thread_pool_size[2] = 0 ;
+    }
+  }
+
+  if ( is_initialized || thread_spawn_failed ) {
+
+    std::ostringstream msg ;
+
+    msg << "Kokkos::Threads::initialize ERROR" ;
+
+    if ( is_initialized ) {
+      msg << " : already initialized" ;
+    }
+    if ( thread_spawn_failed ) {
+      msg << " : failed to spawn " << thread_spawn_failed << " threads" ;
+    }
+
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  // Check for over-subscription
+  if( Impl::mpi_ranks_per_node() * long(thread_count) > Impl::processors_per_node() ) {
+    std::cout << "Kokkos::Threads::initialize WARNING: You are likely oversubscribing your CPU cores." << std::endl;
+    std::cout << "                                    Detected: " << Impl::processors_per_node() << " cores per node." << std::endl;
+    std::cout << "                                    Detected: " << Impl::mpi_ranks_per_node() << " MPI_ranks per node." << std::endl;
+    std::cout << "                                    Requested: " << thread_count << " threads per process." << std::endl;
+  }
+
+  // Init the array for used for arbitrarily sized atomics
+  Impl::init_lock_array_host_space();
+
+  #if (KOKKOS_ENABLE_PROFILING)
+    Kokkos::Profiling::initialize();
+  #endif
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsExec::finalize()
+{
+  verify_is_process("ThreadsExec::finalize",false);
+
+  fence();
+
+  resize_scratch(0,0);
+
+  const unsigned begin = s_threads_process.m_pool_base ? 1 : 0 ;
+
+  for ( unsigned i = s_thread_pool_size[0] ; begin < i-- ; ) {
+
+    if ( s_threads_exec[i] ) {
+
+      s_threads_exec[i]->m_pool_state = ThreadsExec::Terminating ;
+
+      wait_yield( s_threads_process.m_pool_state , ThreadsExec::Inactive );
+
+      s_threads_process.m_pool_state = ThreadsExec::Inactive ;
+    }
+
+    s_threads_pid[i] = 0 ;
+  }
+
+  if ( s_threads_process.m_pool_base ) {
+    ( & s_threads_process )->~ThreadsExec();
+    s_threads_exec[0] = 0 ;
+  }
+
+  if (Kokkos::hwloc::can_bind_threads() ) {
+    Kokkos::hwloc::unbind_this_thread();
+  }
+
+  s_thread_pool_size[0] = 0 ;
+  s_thread_pool_size[1] = 0 ;
+  s_thread_pool_size[2] = 0 ;
+
+  // Reset master thread to run solo.
+  s_threads_process.m_numa_rank       = 0 ;
+  s_threads_process.m_numa_core_rank  = 0 ;
+  s_threads_process.m_pool_base       = 0 ;
+  s_threads_process.m_pool_rank       = 0 ;
+  s_threads_process.m_pool_size       = 1 ;
+  s_threads_process.m_pool_fan_size   = 0 ;
+  s_threads_process.m_pool_state = ThreadsExec::Inactive ;
+
+  #if (KOKKOS_ENABLE_PROFILING)
+    Kokkos::Profiling::finalize();
+  #endif
+}
+
+//----------------------------------------------------------------------------
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+int Threads::concurrency() {
+  return thread_pool_size(0);
+}
+
+Threads & Threads::instance(int)
+{
+  static Threads t ;
+  return t ;
+}
+
+int Threads::thread_pool_size( int depth )
+{
+  return Impl::s_thread_pool_size[depth];
+}
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+int Threads::thread_pool_rank()
+{
+  const pthread_t pid = pthread_self();
+  int i = 0;
+  while ( ( i < Impl::s_thread_pool_size[0] ) && ( pid != Impl::s_threads_pid[i] ) ) { ++i ; }
+  return i ;
+}
+#endif
+
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_PTHREAD ) || defined( KOKKOS_HAVE_WINTHREAD ) */
+
diff --git a/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec.hpp b/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec.hpp
new file mode 100644
index 0000000000..4ec1450d0f
--- /dev/null
+++ b/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec.hpp
@@ -0,0 +1,631 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_THREADSEXEC_HPP
+#define KOKKOS_THREADSEXEC_HPP
+
+#include <stdio.h>
+
+#include <utility>
+#include <impl/Kokkos_spinwait.hpp>
+#include <impl/Kokkos_FunctorAdapter.hpp>
+
+#include <Kokkos_Atomic.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+class ThreadsExec {
+public:
+
+  // Fan array has log_2(NT) reduction threads plus 2 scan threads
+  // Currently limited to 16k threads.
+  enum { MAX_FAN_COUNT    = 16 };
+  enum { MAX_THREAD_COUNT = 1 << ( MAX_FAN_COUNT - 2 ) };
+  enum { VECTOR_LENGTH    = 8 };
+
+  /** \brief States of a worker thread */
+  enum { Terminating ///<  Termination in progress
+       , Inactive    ///<  Exists, waiting for work
+       , Active      ///<  Exists, performing work
+       , Rendezvous  ///<  Exists, waiting in a barrier or reduce
+
+       , ScanCompleted
+       , ScanAvailable
+       , ReductionAvailable
+       };
+
+private:
+
+  friend class Kokkos::Threads ;
+
+  // Fan-in operations' root is the highest ranking thread
+  // to place the 'scan' reduction intermediate values on
+  // the threads that need them.
+  // For a simple reduction the thread location is arbitrary.
+
+  ThreadsExec * const * m_pool_base ; ///< Base for pool fan-in
+
+  void *        m_scratch ;
+  int           m_scratch_reduce_end ;
+  int           m_scratch_thread_end ;
+  int           m_numa_rank ;
+  int           m_numa_core_rank ;
+  int           m_pool_rank ;
+  int           m_pool_rank_rev ;
+  int           m_pool_size ;
+  int           m_pool_fan_size ;
+  int volatile  m_pool_state ;  ///< State for global synchronizations
+
+  // Members for dynamic scheduling
+  // Which thread am I stealing from currently
+  int m_current_steal_target;
+  // This thread's owned work_range
+  Kokkos::pair<long,long> m_work_range KOKKOS_ALIGN_16;
+  // Team Offset if one thread determines work_range for others
+  long m_team_work_index;
+
+  // Is this thread stealing (i.e. its owned work_range is exhausted
+  bool m_stealing;
+
+  static void global_lock();
+  static void global_unlock();
+  static bool spawn();
+
+  static void execute_resize_scratch( ThreadsExec & , const void * );
+  static void execute_sleep(          ThreadsExec & , const void * );
+
+  ThreadsExec( const ThreadsExec & );
+  ThreadsExec & operator = ( const ThreadsExec & );
+
+  static void execute_serial( void (*)( ThreadsExec & , const void * ) );
+
+public:
+
+  KOKKOS_INLINE_FUNCTION int pool_size() const { return m_pool_size ; }
+  KOKKOS_INLINE_FUNCTION int pool_rank() const { return m_pool_rank ; }
+  KOKKOS_INLINE_FUNCTION int numa_rank() const { return m_numa_rank ; }
+  KOKKOS_INLINE_FUNCTION int numa_core_rank() const { return m_numa_core_rank ; }
+  inline long team_work_index() const { return m_team_work_index ; }
+
+  static int get_thread_count();
+  static ThreadsExec * get_thread( const int init_thread_rank );
+
+  inline void * reduce_memory() const { return m_scratch ; }
+  KOKKOS_INLINE_FUNCTION  void * scratch_memory() const
+    { return reinterpret_cast<unsigned char *>(m_scratch) + m_scratch_reduce_end ; }
+
+  KOKKOS_INLINE_FUNCTION  int volatile & state() { return m_pool_state ; }
+  KOKKOS_INLINE_FUNCTION  ThreadsExec * const * pool_base() const { return m_pool_base ; }
+
+  static void driver(void);
+
+  ~ThreadsExec();
+  ThreadsExec();
+
+  static void * resize_scratch( size_t reduce_size , size_t thread_size );
+
+  static void * root_reduce_scratch();
+
+  static bool is_process();
+
+  static void verify_is_process( const std::string & , const bool initialized );
+
+  static int is_initialized();
+
+  static void initialize( unsigned thread_count ,
+                          unsigned use_numa_count ,
+                          unsigned use_cores_per_numa ,
+                          bool allow_asynchronous_threadpool );
+
+  static void finalize();
+
+  /* Given a requested team size, return valid team size */
+  static unsigned team_size_valid( unsigned );
+
+  static void print_configuration( std::ostream & , const bool detail = false );
+
+  //------------------------------------
+
+  static void wait_yield( volatile int & , const int );
+
+  //------------------------------------
+  // All-thread functions:
+
+  inline
+  int all_reduce( const int value )
+    {
+      // Make sure there is enough scratch space:
+      const int rev_rank = m_pool_size - ( m_pool_rank + 1 );
+
+      *((volatile int*) reduce_memory()) = value ;
+
+      memory_fence();
+
+      // Fan-in reduction with highest ranking thread as the root
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        // Wait: Active -> Rendezvous
+        Impl::spinwait( m_pool_base[ rev_rank + (1<<i) ]->m_pool_state , ThreadsExec::Active );
+      }
+
+      if ( rev_rank ) {
+        m_pool_state = ThreadsExec::Rendezvous ;
+        // Wait: Rendezvous -> Active
+        Impl::spinwait( m_pool_state , ThreadsExec::Rendezvous );
+      }
+      else {
+        // Root thread does the reduction and broadcast
+
+        int accum = 0 ;
+
+        for ( int rank = 0 ; rank < m_pool_size ; ++rank ) {
+          accum += *((volatile int *) get_thread( rank )->reduce_memory());
+        }
+
+        for ( int rank = 0 ; rank < m_pool_size ; ++rank ) {
+          *((volatile int *) get_thread( rank )->reduce_memory()) = accum ;
+        }
+
+        memory_fence();
+
+        for ( int rank = 0 ; rank < m_pool_size ; ++rank ) {
+          get_thread( rank )->m_pool_state = ThreadsExec::Active ;
+        }
+      }
+
+      return *((volatile int*) reduce_memory());
+    }
+
+  inline
+  void barrier( )
+    {
+      // Make sure there is enough scratch space:
+      const int rev_rank = m_pool_size - ( m_pool_rank + 1 );
+
+      memory_fence();
+
+      // Fan-in reduction with highest ranking thread as the root
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        // Wait: Active -> Rendezvous
+        Impl::spinwait( m_pool_base[ rev_rank + (1<<i) ]->m_pool_state , ThreadsExec::Active );
+      }
+
+      if ( rev_rank ) {
+        m_pool_state = ThreadsExec::Rendezvous ;
+        // Wait: Rendezvous -> Active
+        Impl::spinwait( m_pool_state , ThreadsExec::Rendezvous );
+      }
+      else {
+        // Root thread does the reduction and broadcast
+
+        memory_fence();
+
+        for ( int rank = 0 ; rank < m_pool_size ; ++rank ) {
+          get_thread( rank )->m_pool_state = ThreadsExec::Active ;
+        }
+      }
+    }
+
+  //------------------------------------
+  // All-thread functions:
+
+  template< class FunctorType , class ArgTag >
+  inline
+  void fan_in_reduce( const FunctorType & f ) const
+    {
+      typedef Kokkos::Impl::FunctorValueJoin< FunctorType , ArgTag > Join ;
+      typedef Kokkos::Impl::FunctorFinal<     FunctorType , ArgTag > Final ;
+
+      const int rev_rank  = m_pool_size - ( m_pool_rank + 1 );
+
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+
+        ThreadsExec & fan = *m_pool_base[ rev_rank + ( 1 << i ) ] ;
+
+        Impl::spinwait( fan.m_pool_state , ThreadsExec::Active );
+
+        Join::join( f , reduce_memory() , fan.reduce_memory() );
+      }
+
+      if ( ! rev_rank ) {
+        Final::final( f , reduce_memory() );
+      }
+    }
+
+  inline
+  void fan_in() const
+    {
+      const int rev_rank = m_pool_size - ( m_pool_rank + 1 );
+
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        Impl::spinwait( m_pool_base[rev_rank+(1<<i)]->m_pool_state , ThreadsExec::Active );
+      }
+    }
+
+  template< class FunctorType , class ArgTag >
+  inline
+  void scan_large( const FunctorType & f )
+    {
+      // Sequence of states:
+      //  0) Active             : entry and exit state
+      //  1) ReductionAvailable : reduction value available
+      //  2) ScanAvailable      : inclusive scan value available
+      //  3) Rendezvous         : All threads inclusive scan value are available
+      //  4) ScanCompleted      : exclusive scan value copied
+
+      typedef Kokkos::Impl::FunctorValueTraits< FunctorType , ArgTag > Traits ;
+      typedef Kokkos::Impl::FunctorValueJoin<   FunctorType , ArgTag > Join ;
+      typedef Kokkos::Impl::FunctorValueInit<   FunctorType , ArgTag > Init ;
+
+      typedef typename Traits::value_type scalar_type ;
+
+      const int      rev_rank = m_pool_size - ( m_pool_rank + 1 );
+      const unsigned count    = Traits::value_count( f );
+
+      scalar_type * const work_value = (scalar_type *) reduce_memory();
+
+      //--------------------------------
+      // Fan-in reduction with highest ranking thread as the root
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        ThreadsExec & fan = *m_pool_base[ rev_rank + (1<<i) ];
+
+        // Wait: Active -> ReductionAvailable (or ScanAvailable)
+        Impl::spinwait( fan.m_pool_state , ThreadsExec::Active );
+        Join::join( f , work_value , fan.reduce_memory() );
+      }
+
+      // Copy reduction value to scan value before releasing from this phase.
+      for ( unsigned i = 0 ; i < count ; ++i ) { work_value[i+count] = work_value[i] ; }
+
+      if ( rev_rank ) {
+
+        // Set: Active -> ReductionAvailable
+        m_pool_state = ThreadsExec::ReductionAvailable ;
+
+        // Wait for contributing threads' scan value to be available.
+        if ( ( 1 << m_pool_fan_size ) < ( m_pool_rank + 1 ) ) {
+          ThreadsExec & th = *m_pool_base[ rev_rank + ( 1 << m_pool_fan_size ) ] ;
+
+          // Wait: Active             -> ReductionAvailable
+          // Wait: ReductionAvailable -> ScanAvailable
+          Impl::spinwait( th.m_pool_state , ThreadsExec::Active );
+          Impl::spinwait( th.m_pool_state , ThreadsExec::ReductionAvailable );
+
+          Join::join( f , work_value + count , ((scalar_type *)th.reduce_memory()) + count );
+        }
+
+        // This thread has completed inclusive scan
+        // Set: ReductionAvailable -> ScanAvailable
+        m_pool_state = ThreadsExec::ScanAvailable ;
+
+        // Wait for all threads to complete inclusive scan
+        // Wait: ScanAvailable -> Rendezvous
+        Impl::spinwait( m_pool_state , ThreadsExec::ScanAvailable );
+      }
+
+      //--------------------------------
+
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        ThreadsExec & fan = *m_pool_base[ rev_rank + (1<<i) ];
+        // Wait: ReductionAvailable -> ScanAvailable
+        Impl::spinwait( fan.m_pool_state , ThreadsExec::ReductionAvailable );
+        // Set: ScanAvailable -> Rendezvous
+        fan.m_pool_state = ThreadsExec::Rendezvous ;
+      }
+
+      // All threads have completed the inclusive scan.
+      // All non-root threads are in the Rendezvous state.
+      // Threads are free to overwrite their reduction value.
+      //--------------------------------
+
+      if ( ( rev_rank + 1 ) < m_pool_size ) {
+        // Exclusive scan: copy the previous thread's inclusive scan value
+
+        ThreadsExec & th = *m_pool_base[ rev_rank + 1 ] ; // Not the root thread
+
+        const scalar_type * const src_value = ((scalar_type *)th.reduce_memory()) + count ;
+
+        for ( unsigned j = 0 ; j < count ; ++j ) { work_value[j] = src_value[j]; }
+      }
+      else {
+        (void) Init::init( f , work_value );
+      }
+
+      //--------------------------------
+      // Wait for all threads to copy previous thread's inclusive scan value
+      // Wait for all threads: Rendezvous -> ScanCompleted
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        Impl::spinwait( m_pool_base[ rev_rank + (1<<i) ]->m_pool_state , ThreadsExec::Rendezvous );
+      }
+      if ( rev_rank ) {
+        // Set: ScanAvailable -> ScanCompleted
+        m_pool_state = ThreadsExec::ScanCompleted ;
+        // Wait: ScanCompleted -> Active
+        Impl::spinwait( m_pool_state , ThreadsExec::ScanCompleted );
+      }
+      // Set: ScanCompleted -> Active
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        m_pool_base[ rev_rank + (1<<i) ]->m_pool_state = ThreadsExec::Active ;
+      }
+    }
+
+  template< class FunctorType , class ArgTag >
+  inline
+  void scan_small( const FunctorType & f )
+    {
+      typedef Kokkos::Impl::FunctorValueTraits< FunctorType , ArgTag > Traits ;
+      typedef Kokkos::Impl::FunctorValueJoin<   FunctorType , ArgTag > Join ;
+      typedef Kokkos::Impl::FunctorValueInit<   FunctorType , ArgTag > Init ;
+
+      typedef typename Traits::value_type scalar_type ;
+
+      const int      rev_rank = m_pool_size - ( m_pool_rank + 1 );
+      const unsigned count    = Traits::value_count( f );
+
+      scalar_type * const work_value = (scalar_type *) reduce_memory();
+
+      //--------------------------------
+      // Fan-in reduction with highest ranking thread as the root
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        // Wait: Active -> Rendezvous
+        Impl::spinwait( m_pool_base[ rev_rank + (1<<i) ]->m_pool_state , ThreadsExec::Active );
+      }
+
+      for ( unsigned i = 0 ; i < count ; ++i ) { work_value[i+count] = work_value[i]; }
+
+      if ( rev_rank ) {
+        m_pool_state = ThreadsExec::Rendezvous ;
+        // Wait: Rendezvous -> Active
+        Impl::spinwait( m_pool_state , ThreadsExec::Rendezvous );
+      }
+      else {
+        // Root thread does the thread-scan before releasing threads
+
+        scalar_type * ptr_prev = 0 ;
+
+        for ( int rank = 0 ; rank < m_pool_size ; ++rank ) {
+          scalar_type * const ptr = (scalar_type *) get_thread( rank )->reduce_memory();
+          if ( rank ) {
+            for ( unsigned i = 0 ; i < count ; ++i ) { ptr[i] = ptr_prev[ i + count ]; }
+            Join::join( f , ptr + count , ptr );
+          }
+          else {
+            (void) Init::init( f , ptr );
+          }
+          ptr_prev = ptr ;
+        }
+      }
+
+      for ( int i = 0 ; i < m_pool_fan_size ; ++i ) {
+        m_pool_base[ rev_rank + (1<<i) ]->m_pool_state = ThreadsExec::Active ;
+      }
+    }
+
+  //------------------------------------
+  /** \brief  Wait for previous asynchronous functor to
+   *          complete and release the Threads device.
+   *          Acquire the Threads device and start this functor.
+   */
+  static void start( void (*)( ThreadsExec & , const void * ) , const void * );
+
+  static int  in_parallel();
+  static void fence();
+  static bool sleep();
+  static bool wake();
+
+  /* Dynamic Scheduling related functionality */
+  // Initialize the work range for this thread
+  inline void set_work_range(const long& begin, const long& end, const long& chunk_size) {
+    m_work_range.first = (begin+chunk_size-1)/chunk_size;
+    m_work_range.second = end>0?(end+chunk_size-1)/chunk_size:m_work_range.first;
+  }
+
+  // Claim and index from this thread's range from the beginning
+  inline long get_work_index_begin () {
+    Kokkos::pair<long,long> work_range_new = m_work_range;
+    Kokkos::pair<long,long> work_range_old = work_range_new;
+    if(work_range_old.first>=work_range_old.second)
+      return -1;
+
+    work_range_new.first+=1;
+
+    bool success = false;
+    while(!success) {
+      work_range_new = Kokkos::atomic_compare_exchange(&m_work_range,work_range_old,work_range_new);
+      success = ( (work_range_new == work_range_old) ||
+                  (work_range_new.first>=work_range_new.second));
+      work_range_old = work_range_new;
+      work_range_new.first+=1;
+    }
+    if(work_range_old.first<work_range_old.second)
+      return work_range_old.first;
+    else
+      return -1;
+  }
+
+  // Claim and index from this thread's range from the end
+  inline long get_work_index_end () {
+    Kokkos::pair<long,long> work_range_new = m_work_range;
+    Kokkos::pair<long,long> work_range_old = work_range_new;
+    if(work_range_old.first>=work_range_old.second)
+      return -1;
+    work_range_new.second-=1;
+    bool success = false;
+    while(!success) {
+      work_range_new = Kokkos::atomic_compare_exchange(&m_work_range,work_range_old,work_range_new);
+      success = ( (work_range_new == work_range_old) ||
+                  (work_range_new.first>=work_range_new.second) );
+      work_range_old = work_range_new;
+      work_range_new.second-=1;
+    }
+    if(work_range_old.first<work_range_old.second)
+      return work_range_old.second-1;
+    else
+      return -1;
+  }
+
+  // Reset the steal target
+  inline void reset_steal_target() {
+    m_current_steal_target = (m_pool_rank+1)%pool_size();
+    m_stealing = false;
+  }
+
+  // Reset the steal target
+  inline void reset_steal_target(int team_size) {
+    m_current_steal_target = (m_pool_rank_rev+team_size);
+    if(m_current_steal_target>=pool_size())
+      m_current_steal_target = 0;//pool_size()-1;
+    m_stealing = false;
+  }
+
+  // Get a steal target; start with my-rank + 1 and go round robin, until arriving at this threads rank
+  // Returns -1 fi no active steal target available
+  inline int get_steal_target() {
+    while(( m_pool_base[m_current_steal_target]->m_work_range.second <=
+            m_pool_base[m_current_steal_target]->m_work_range.first  ) &&
+          (m_current_steal_target!=m_pool_rank) ) {
+      m_current_steal_target = (m_current_steal_target+1)%pool_size();
+    }
+    if(m_current_steal_target == m_pool_rank)
+      return -1;
+    else
+      return m_current_steal_target;
+  }
+
+  inline int get_steal_target(int team_size) {
+
+    while(( m_pool_base[m_current_steal_target]->m_work_range.second <=
+            m_pool_base[m_current_steal_target]->m_work_range.first  ) &&
+          (m_current_steal_target!=m_pool_rank_rev) ) {
+      if(m_current_steal_target + team_size < pool_size())
+        m_current_steal_target = (m_current_steal_target+team_size);
+      else
+        m_current_steal_target = 0;
+    }
+
+    if(m_current_steal_target == m_pool_rank_rev)
+      return -1;
+    else
+      return m_current_steal_target;
+  }
+
+  inline long steal_work_index (int team_size = 0) {
+    long index = -1;
+    int steal_target = team_size>0?get_steal_target(team_size):get_steal_target();
+    while ( (steal_target != -1) && (index == -1)) {
+      index = m_pool_base[steal_target]->get_work_index_end();
+      if(index == -1)
+        steal_target = team_size>0?get_steal_target(team_size):get_steal_target();
+    }
+    return index;
+  }
+
+  // Get a work index. Claim from owned range until its exhausted, then steal from other thread
+  inline long get_work_index (int team_size = 0) {
+    long work_index = -1;
+    if(!m_stealing) work_index = get_work_index_begin();
+
+    if( work_index == -1) {
+      memory_fence();
+      m_stealing = true;
+      work_index = steal_work_index(team_size);
+    }
+
+    m_team_work_index = work_index;
+    memory_fence();
+    return work_index;
+  }
+
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+inline int Threads::in_parallel()
+{ return Impl::ThreadsExec::in_parallel(); }
+
+inline int Threads::is_initialized()
+{ return Impl::ThreadsExec::is_initialized(); }
+
+inline void Threads::initialize(
+  unsigned threads_count ,
+  unsigned use_numa_count ,
+  unsigned use_cores_per_numa ,
+  bool allow_asynchronous_threadpool )
+{
+  Impl::ThreadsExec::initialize( threads_count , use_numa_count , use_cores_per_numa , allow_asynchronous_threadpool );
+}
+
+inline void Threads::finalize()
+{
+  Impl::ThreadsExec::finalize();
+}
+
+inline void Threads::print_configuration( std::ostream & s , const bool detail )
+{
+  Impl::ThreadsExec::print_configuration( s , detail );
+}
+
+inline bool Threads::sleep()
+{ return Impl::ThreadsExec::sleep() ; }
+
+inline bool Threads::wake()
+{ return Impl::ThreadsExec::wake() ; }
+
+inline void Threads::fence()
+{ Impl::ThreadsExec::fence() ; }
+
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #define KOKKOS_THREADSEXEC_HPP */
+
diff --git a/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec_base.cpp b/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec_base.cpp
new file mode 100644
index 0000000000..ce09248678
--- /dev/null
+++ b/lib/kokkos/core/src/Threads/Kokkos_ThreadsExec_base.cpp
@@ -0,0 +1,255 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core_fwd.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+
+/* Standard 'C' Linux libraries */
+
+#include <pthread.h>
+#include <sched.h>
+#include <errno.h>
+
+/* Standard C++ libaries */
+
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <stdexcept>
+
+#include <Kokkos_Threads.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+namespace {
+
+pthread_mutex_t host_internal_pthread_mutex = PTHREAD_MUTEX_INITIALIZER ;
+
+// Pthreads compatible driver.
+// Recovery from an exception would require constant intra-thread health
+// verification; which would negatively impact runtime.  As such simply
+// abort the process.
+
+void * internal_pthread_driver( void * )
+{
+  try {
+    ThreadsExec::driver();
+  }
+  catch( const std::exception & x ) {
+    std::cerr << "Exception thrown from worker thread: " << x.what() << std::endl ;
+    std::cerr.flush();
+    std::abort();
+  }
+  catch( ... ) {
+    std::cerr << "Exception thrown from worker thread" << std::endl ;
+    std::cerr.flush();
+    std::abort();
+  }
+  return NULL ;
+}
+
+} // namespace
+
+//----------------------------------------------------------------------------
+// Spawn a thread
+
+bool ThreadsExec::spawn()
+{
+  bool result = false ;
+
+  pthread_attr_t attr ;
+
+  if ( 0 == pthread_attr_init( & attr ) ||
+       0 == pthread_attr_setscope(       & attr, PTHREAD_SCOPE_SYSTEM ) ||
+       0 == pthread_attr_setdetachstate( & attr, PTHREAD_CREATE_DETACHED ) ) {
+
+    pthread_t pt ;
+
+    result = 0 == pthread_create( & pt, & attr, internal_pthread_driver, 0 );
+  }
+
+  pthread_attr_destroy( & attr );
+
+  return result ;
+}
+
+//----------------------------------------------------------------------------
+
+bool ThreadsExec::is_process()
+{
+  static const pthread_t master_pid = pthread_self();
+
+  return pthread_equal( master_pid , pthread_self() );
+}
+
+void ThreadsExec::global_lock()
+{
+  pthread_mutex_lock( & host_internal_pthread_mutex );
+}
+
+void ThreadsExec::global_unlock()
+{
+  pthread_mutex_unlock( & host_internal_pthread_mutex );
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsExec::wait_yield( volatile int & flag , const int value )
+{
+  while ( value == flag ) { sched_yield(); }
+}
+
+} // namespace Impl
+} // namespace Kokkos
+
+/* end #if defined( KOKKOS_HAVE_PTHREAD ) */
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#elif defined( KOKKOS_HAVE_WINTHREAD )
+
+/* Windows libraries */
+#include <winsock2.h>
+#include <windows.h>
+#include <process.h>
+
+/* Standard C++ libaries */
+
+#include <cstdlib>
+#include <string>
+#include <iostream>
+#include <stdexcept>
+
+#include <Kokkos_Threads.hpp>
+
+//----------------------------------------------------------------------------
+// Driver for each created pthread
+
+namespace Kokkos {
+namespace Impl {
+namespace {
+
+unsigned WINAPI internal_winthread_driver( void * arg )
+{
+  ThreadsExec::driver();
+
+  return 0 ;
+}
+
+class ThreadLockWindows {
+private:
+  CRITICAL_SECTION  m_handle ;
+
+  ~ThreadLockWindows()
+  { DeleteCriticalSection( & m_handle ); }
+
+  ThreadLockWindows();
+  { InitializeCriticalSection( & m_handle ); }
+
+  ThreadLockWindows( const ThreadLockWindows & );
+  ThreadLockWindows & operator = ( const ThreadLockWindows & );
+
+public:
+
+  static ThreadLockWindows & singleton();
+
+  void lock()
+  { EnterCriticalSection( & m_handle ); }
+
+  void unlock()
+  { LeaveCriticalSection( & m_handle ); }
+};
+
+ThreadLockWindows & ThreadLockWindows::singleton()
+{ static ThreadLockWindows self ; return self ; }
+
+} // namespace <>
+} // namespace Kokkos
+} // namespace Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+// Spawn this thread
+
+bool ThreadsExec::spawn()
+{
+  unsigned Win32ThreadID = 0 ;
+
+  HANDLE handle =
+    _beginthreadex(0,0,internal_winthread_driver,0,0, & Win32ThreadID );
+
+  return ! handle ;
+}
+
+bool ThreadsExec::is_process() { return true ; }
+
+void ThreadsExec::global_lock()
+{ ThreadLockWindows::singleton().lock(); }
+
+void ThreadsExec::global_unlock()
+{ ThreadLockWindows::singleton().unlock(); }
+
+void ThreadsExec::wait_yield( volatile int & flag , const int value ) {}
+{
+  while ( value == flag ) { Sleep(0); }
+}
+
+} // namespace Impl
+} // namespace Kokkos
+
+#endif /* end #elif defined( KOKKOS_HAVE_WINTHREAD ) */
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+
+
diff --git a/lib/kokkos/core/src/Threads/Kokkos_ThreadsTeam.hpp b/lib/kokkos/core/src/Threads/Kokkos_ThreadsTeam.hpp
new file mode 100644
index 0000000000..3407ffaa54
--- /dev/null
+++ b/lib/kokkos/core/src/Threads/Kokkos_ThreadsTeam.hpp
@@ -0,0 +1,932 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_THREADSTEAM_HPP
+#define KOKKOS_THREADSTEAM_HPP
+
+#include <stdio.h>
+
+#include <utility>
+#include <impl/Kokkos_spinwait.hpp>
+#include <impl/Kokkos_FunctorAdapter.hpp>
+
+#include <Kokkos_Atomic.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+
+template< class > struct ThreadsExecAdapter ;
+
+//----------------------------------------------------------------------------
+
+class ThreadsExecTeamMember {
+private:
+
+  enum { TEAM_REDUCE_SIZE = 512 };
+
+  typedef Kokkos::Threads execution_space ;
+  typedef execution_space::scratch_memory_space space ;
+
+  ThreadsExec * const   m_exec ;
+  ThreadsExec * const * m_team_base ; ///< Base for team fan-in
+  space                 m_team_shared ;
+  int                   m_team_shared_size ;
+  int                   m_team_size ;
+  int                   m_team_rank ;
+  int                   m_team_rank_rev ;
+  int                   m_league_size ;
+  int                   m_league_end ;
+  int                   m_league_rank ;
+
+  int                   m_chunk_size;
+  int                   m_league_chunk_end;
+
+  int                   m_invalid_thread;
+  int                   m_team_alloc;
+
+  inline
+  void set_team_shared()
+    { new( & m_team_shared ) space( ((char *) (*m_team_base)->scratch_memory()) + TEAM_REDUCE_SIZE , m_team_shared_size ); }
+  
+public:
+
+  // Fan-in and wait until the matching fan-out is called.
+  // The root thread which does not wait will return true.
+  // All other threads will return false during the fan-out.
+  KOKKOS_INLINE_FUNCTION bool team_fan_in() const
+    {
+      int n , j ;
+
+      // Wait for fan-in threads
+      for ( n = 1 ; ( ! ( m_team_rank_rev & n ) ) && ( ( j = m_team_rank_rev + n ) < m_team_size ) ; n <<= 1 ) {
+        Impl::spinwait( m_team_base[j]->state() , ThreadsExec::Active );
+      }
+
+      // If not root then wait for release
+      if ( m_team_rank_rev ) {
+        m_exec->state() = ThreadsExec::Rendezvous ;
+        Impl::spinwait( m_exec->state() , ThreadsExec::Rendezvous );
+      }
+
+      return ! m_team_rank_rev ;
+    }
+
+  KOKKOS_INLINE_FUNCTION void team_fan_out() const
+    {
+      int n , j ;
+      for ( n = 1 ; ( ! ( m_team_rank_rev & n ) ) && ( ( j = m_team_rank_rev + n ) < m_team_size ) ; n <<= 1 ) {
+        m_team_base[j]->state() = ThreadsExec::Active ;
+      }
+    }
+
+public:
+
+  KOKKOS_INLINE_FUNCTION static int team_reduce_size() { return TEAM_REDUCE_SIZE ; }
+
+  KOKKOS_INLINE_FUNCTION
+  const execution_space::scratch_memory_space & team_shmem() const
+    { return m_team_shared.set_team_thread_mode(0,1,0) ; }
+
+  KOKKOS_INLINE_FUNCTION
+  const execution_space::scratch_memory_space & team_scratch(int) const
+    { return m_team_shared.set_team_thread_mode(0,1,0) ; }
+
+  KOKKOS_INLINE_FUNCTION
+  const execution_space::scratch_memory_space & thread_scratch(int) const
+    { return m_team_shared.set_team_thread_mode(0,team_size(),team_rank()) ; }
+
+  KOKKOS_INLINE_FUNCTION int league_rank() const { return m_league_rank ; }
+  KOKKOS_INLINE_FUNCTION int league_size() const { return m_league_size ; }
+  KOKKOS_INLINE_FUNCTION int team_rank() const { return m_team_rank ; }
+  KOKKOS_INLINE_FUNCTION int team_size() const { return m_team_size ; }
+
+  KOKKOS_INLINE_FUNCTION void team_barrier() const
+    {
+      team_fan_in();
+      team_fan_out();
+    }
+
+  template<class ValueType>
+  KOKKOS_INLINE_FUNCTION
+  void team_broadcast(ValueType& value, const int& thread_id) const
+  {
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { }
+#else
+    // Make sure there is enough scratch space:
+    typedef typename if_c< sizeof(ValueType) < TEAM_REDUCE_SIZE
+                         , ValueType , void >::type type ;
+
+    if ( m_team_base ) {
+      type * const local_value = ((type*) m_team_base[0]->scratch_memory());
+      if(team_rank() == thread_id) *local_value = value;
+      memory_fence();
+      team_barrier();
+      value = *local_value;
+    }
+#endif
+  }
+
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION Type team_reduce( const Type & value ) const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return Type(); }
+#else
+    {
+      // Make sure there is enough scratch space:
+      typedef typename if_c< sizeof(Type) < TEAM_REDUCE_SIZE , Type , void >::type type ;
+
+      if ( 0 == m_exec ) return value ;
+
+      *((volatile type*) m_exec->scratch_memory() ) = value ;
+
+      memory_fence();
+
+      type & accum = *((type *) m_team_base[0]->scratch_memory() );
+
+      if ( team_fan_in() ) {
+        for ( int i = 1 ; i < m_team_size ; ++i ) {
+          accum += *((type *) m_team_base[i]->scratch_memory() );
+        }
+        memory_fence();
+      }
+
+      team_fan_out();
+
+      return accum ;
+    }
+#endif
+
+#ifdef KOKKOS_HAVE_CXX11
+  template< class ValueType, class JoinOp >
+  KOKKOS_INLINE_FUNCTION ValueType
+    team_reduce( const ValueType & value
+               , const JoinOp & op_in ) const
+  #if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return ValueType(); }
+  #else
+    {
+      typedef ValueType value_type;
+      const JoinLambdaAdapter<value_type,JoinOp> op(op_in);
+  #endif
+#else // KOKKOS_HAVE_CXX11
+  template< class JoinOp >
+  KOKKOS_INLINE_FUNCTION typename JoinOp::value_type
+    team_reduce( const typename JoinOp::value_type & value
+               , const JoinOp & op ) const
+  #if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return typename JoinOp::value_type(); }
+  #else
+    {
+      typedef typename JoinOp::value_type value_type;
+  #endif
+#endif // KOKKOS_HAVE_CXX11
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      // Make sure there is enough scratch space:
+      typedef typename if_c< sizeof(value_type) < TEAM_REDUCE_SIZE
+                           , value_type , void >::type type ;
+
+      if ( 0 == m_exec ) return value ;
+
+      type * const local_value = ((type*) m_exec->scratch_memory());
+
+      // Set this thread's contribution
+      *local_value = value ;
+
+      // Fence to make sure the base team member has access:
+      memory_fence();
+
+      if ( team_fan_in() ) {
+        // The last thread to synchronize returns true, all other threads wait for team_fan_out()
+        type * const team_value = ((type*) m_team_base[0]->scratch_memory());
+
+        // Join to the team value:
+        for ( int i = 1 ; i < m_team_size ; ++i ) {
+          op.join( *team_value , *((type*) m_team_base[i]->scratch_memory()) );
+        }
+
+        // Team base thread may "lap" member threads so copy out to their local value.
+        for ( int i = 1 ; i < m_team_size ; ++i ) {
+          *((type*) m_team_base[i]->scratch_memory()) = *team_value ;
+        }
+
+        // Fence to make sure all team members have access
+        memory_fence();
+      }
+
+      team_fan_out();
+
+      // Value was changed by the team base
+      return *((type volatile const *) local_value);
+    }
+#endif
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering
+   *          with intra-team non-deterministic ordering accumulation.
+   *
+   *  The global inter-team accumulation value will, at the end of the
+   *  league's parallel execution, be the scan's total.
+   *  Parallel execution ordering of the league's teams is non-deterministic.
+   *  As such the base value for each team's scan operation is similarly
+   *  non-deterministic.
+   */
+  template< typename ArgType >
+  KOKKOS_INLINE_FUNCTION ArgType team_scan( const ArgType & value , ArgType * const global_accum ) const
+#if ! defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return ArgType(); }
+#else
+    {
+      // Make sure there is enough scratch space:
+      typedef typename if_c< sizeof(ArgType) < TEAM_REDUCE_SIZE , ArgType , void >::type type ;
+
+      if ( 0 == m_exec ) return type(0);
+
+      volatile type * const work_value  = ((type*) m_exec->scratch_memory());
+
+      *work_value = value ;
+
+      memory_fence();
+
+      if ( team_fan_in() ) {
+        // The last thread to synchronize returns true, all other threads wait for team_fan_out()
+        // m_team_base[0]                 == highest ranking team member
+        // m_team_base[ m_team_size - 1 ] == lowest ranking team member
+        //
+        // 1) copy from lower to higher rank, initialize lowest rank to zero
+        // 2) prefix sum from lowest to highest rank, skipping lowest rank
+
+        type accum = 0 ;
+
+        if ( global_accum ) {
+          for ( int i = m_team_size ; i-- ; ) {
+            type & val = *((type*) m_team_base[i]->scratch_memory());
+            accum += val ;
+          }
+          accum = atomic_fetch_add( global_accum , accum );
+        }
+
+        for ( int i = m_team_size ; i-- ; ) {
+          type & val = *((type*) m_team_base[i]->scratch_memory());
+          const type offset = accum ;
+          accum += val ;
+          val = offset ;
+        }
+
+        memory_fence();
+      }
+
+      team_fan_out();
+
+      return *work_value ;
+    }
+#endif
+
+  /** \brief  Intra-team exclusive prefix sum with team_rank() ordering.
+   *
+   *  The highest rank thread can compute the reduction total as
+   *    reduction_total = dev.team_scan( value ) + value ;
+   */
+  template< typename ArgType >
+  KOKKOS_INLINE_FUNCTION ArgType team_scan( const ArgType & value ) const
+    { return this-> template team_scan<ArgType>( value , 0 ); }
+
+
+  //----------------------------------------
+  // Private for the driver
+
+  template< class ... Properties >
+  ThreadsExecTeamMember( Impl::ThreadsExec * exec
+                       , const TeamPolicyInternal< Kokkos::Threads , Properties ... > & team
+                       , const int shared_size )
+    : m_exec( exec )
+    , m_team_base(0)
+    , m_team_shared(0,0)
+    , m_team_shared_size( shared_size )
+    , m_team_size(team.team_size())
+    , m_team_rank(0)
+    , m_team_rank_rev(0)
+    , m_league_size(0)
+    , m_league_end(0)
+    , m_league_rank(0)
+    , m_chunk_size( team.chunk_size() )
+    , m_league_chunk_end(0)
+    , m_team_alloc( team.team_alloc())
+   {
+      if ( team.league_size() ) {
+        // Execution is using device-team interface:
+
+        const int pool_rank_rev = m_exec->pool_size() - ( m_exec->pool_rank() + 1 );
+        const int team_rank_rev = pool_rank_rev % team.team_alloc();
+        const size_t pool_league_size     = m_exec->pool_size() / team.team_alloc() ;
+        const size_t pool_league_rank_rev = pool_rank_rev / team.team_alloc() ;
+        const size_t pool_league_rank     = pool_league_size - ( pool_league_rank_rev + 1 );
+
+        const int pool_num_teams       = m_exec->pool_size()/team.team_alloc();
+        const int chunk_size           = team.chunk_size()>0?team.chunk_size():team.team_iter();
+        const int chunks_per_team      = ( team.league_size() + chunk_size*pool_num_teams-1 ) / (chunk_size*pool_num_teams);
+              int league_iter_end      = team.league_size() - pool_league_rank_rev * chunks_per_team * chunk_size;
+              int league_iter_begin    = league_iter_end - chunks_per_team * chunk_size;
+        if (league_iter_begin < 0)     league_iter_begin = 0;
+        if (league_iter_end>team.league_size()) league_iter_end = team.league_size();
+
+        if ((team.team_alloc()>m_team_size)?
+            (team_rank_rev >= m_team_size):
+            (m_exec->pool_size() - pool_num_teams*m_team_size > m_exec->pool_rank())
+           )
+          m_invalid_thread = 1;
+        else
+          m_invalid_thread = 0;
+
+        // May be using fewer threads per team than a multiple of threads per core,
+        // some threads will idle.
+
+        if ( team_rank_rev < team.team_size() && !m_invalid_thread) {
+
+          m_team_base        = m_exec->pool_base() + team.team_alloc() * pool_league_rank_rev ;
+          m_team_size        = team.team_size() ;
+          m_team_rank        = team.team_size() - ( team_rank_rev + 1 );
+          m_team_rank_rev    = team_rank_rev ;
+          m_league_size      = team.league_size();
+
+          m_league_rank      = ( team.league_size() *  pool_league_rank    ) / pool_league_size ;
+          m_league_end       = ( team.league_size() * (pool_league_rank+1) ) / pool_league_size ;
+
+          set_team_shared();
+        }
+
+        if ( (m_team_rank_rev == 0) && (m_invalid_thread == 0) ) {
+          m_exec->set_work_range(m_league_rank,m_league_end,m_chunk_size);
+          m_exec->reset_steal_target(m_team_size);
+        }
+        if(std::is_same<typename TeamPolicyInternal<Kokkos::Threads, Properties ...>::schedule_type::type,Kokkos::Dynamic>::value) {
+          m_exec->barrier();
+        }
+      }
+    }
+
+  ThreadsExecTeamMember()
+    : m_exec(0)
+    , m_team_base(0)
+    , m_team_shared(0,0)
+    , m_team_shared_size(0)
+    , m_team_size(1)
+    , m_team_rank(0)
+    , m_team_rank_rev(0)
+    , m_league_size(1)
+    , m_league_end(0)
+    , m_league_rank(0)
+    , m_chunk_size(0)
+    , m_league_chunk_end(0)
+    , m_invalid_thread(0)
+    , m_team_alloc(0)
+    {}
+
+  inline
+  ThreadsExec & threads_exec_team_base() const { return m_team_base ? **m_team_base : *m_exec ; }
+
+  bool valid_static() const
+    { return m_league_rank < m_league_end ; }
+
+  void next_static()
+    {
+      if ( m_league_rank < m_league_end ) {
+        team_barrier();
+        set_team_shared();
+      }
+      m_league_rank++;
+    }
+
+  bool valid_dynamic() {
+
+    if(m_invalid_thread)
+      return false;
+    if ((m_league_rank < m_league_chunk_end) && (m_league_rank < m_league_size)) {
+      return true;
+    }
+
+    if (  m_team_rank_rev == 0 ) {
+      m_team_base[0]->get_work_index(m_team_alloc);
+    }
+    team_barrier();
+
+    long work_index = m_team_base[0]->team_work_index();
+
+    m_league_rank = work_index * m_chunk_size;
+    m_league_chunk_end = (work_index +1 ) * m_chunk_size;
+
+    if(m_league_chunk_end > m_league_size) m_league_chunk_end = m_league_size;
+
+    if(m_league_rank>=0)
+      return true;
+    return false;
+  }
+
+  void next_dynamic() {
+    if(m_invalid_thread)
+      return;
+
+    if ( m_league_rank < m_league_chunk_end ) {
+      team_barrier();
+      set_team_shared();
+    }
+    m_league_rank++;
+  }
+
+  void set_league_shmem( const int arg_league_rank
+                       , const int arg_league_size
+                       , const int arg_shmem_size
+                       )
+    {
+      m_league_rank = arg_league_rank ;
+      m_league_size = arg_league_size ;
+      m_team_shared_size = arg_shmem_size ;
+      set_team_shared();
+    }
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+template< class ... Properties >
+class TeamPolicyInternal< Kokkos::Threads , Properties ... >: public PolicyTraits<Properties ...>
+{
+private:
+
+  int m_league_size ;
+  int m_team_size ;
+  int m_team_alloc ;
+  int m_team_iter ;
+
+  size_t m_team_scratch_size[2];
+  size_t m_thread_scratch_size[2];
+
+  int m_chunk_size;
+
+  inline
+  void init( const int league_size_request 
+           , const int team_size_request )
+   {
+      const int pool_size  = traits::execution_space::thread_pool_size(0);
+      const int team_max   = traits::execution_space::thread_pool_size(1);
+      const int team_grain = traits::execution_space::thread_pool_size(2);
+
+      m_league_size = league_size_request ;
+
+      m_team_size = team_size_request < team_max ?
+                    team_size_request : team_max ;
+
+      // Round team size up to a multiple of 'team_gain'
+      const int team_size_grain = team_grain * ( ( m_team_size + team_grain - 1 ) / team_grain );
+      const int team_count      = pool_size / team_size_grain ;
+
+      // Constraint : pool_size = m_team_alloc * team_count
+      m_team_alloc = pool_size / team_count ;
+
+      // Maxumum number of iterations each team will take:
+      m_team_iter  = ( m_league_size + team_count - 1 ) / team_count ;
+
+      set_auto_chunk_size();
+   }
+
+
+public:
+
+  //! Tag this class as a kokkos execution policy
+  //! Tag this class as a kokkos execution policy
+  typedef TeamPolicyInternal      execution_policy ;
+
+  typedef PolicyTraits<Properties ... > traits;
+
+  TeamPolicyInternal& operator = (const TeamPolicyInternal& p) {
+    m_league_size = p.m_league_size;
+    m_team_size = p.m_team_size;
+    m_team_alloc = p.m_team_alloc;
+    m_team_iter = p.m_team_iter;
+    m_team_scratch_size[0] = p.m_team_scratch_size[0];
+    m_thread_scratch_size[0] = p.m_thread_scratch_size[0];
+    m_team_scratch_size[1] = p.m_team_scratch_size[1];
+    m_thread_scratch_size[1] = p.m_thread_scratch_size[1];
+    m_chunk_size = p.m_chunk_size;
+    return *this;
+  }
+
+  //----------------------------------------
+
+  template< class FunctorType >
+  inline static
+  int team_size_max( const FunctorType & )
+    { return traits::execution_space::thread_pool_size(1); }
+
+  template< class FunctorType >
+  static int team_size_recommended( const FunctorType & )
+    { return traits::execution_space::thread_pool_size(2); }
+
+
+  template< class FunctorType >
+  inline static
+  int team_size_recommended( const FunctorType &, const int& )
+    { return traits::execution_space::thread_pool_size(2); }
+
+  //----------------------------------------
+
+  inline int team_size() const { return m_team_size ; }
+  inline int team_alloc() const { return m_team_alloc ; }
+  inline int league_size() const { return m_league_size ; }
+  inline size_t scratch_size(const int& level, int team_size_ = -1 ) const {
+    if(team_size_ < 0)
+      team_size_ = m_team_size;
+    return m_team_scratch_size[level] + team_size_*m_thread_scratch_size[level] ;
+  }
+
+  inline int team_iter() const { return m_team_iter ; }
+
+  /** \brief  Specify league size, request team size */
+  TeamPolicyInternal( typename traits::execution_space &
+            , int league_size_request
+            , int team_size_request
+            , int vector_length_request = 1 )
+    : m_league_size(0)
+    , m_team_size(0)
+    , m_team_alloc(0)
+    , m_team_scratch_size { 0 , 0 }
+    , m_thread_scratch_size { 0 , 0 }
+    , m_chunk_size(0)
+    { init(league_size_request,team_size_request); (void) vector_length_request; }
+
+  /** \brief  Specify league size, request team size */
+  TeamPolicyInternal( typename traits::execution_space &
+            , int league_size_request
+            , const Kokkos::AUTO_t & /* team_size_request */
+            , int /* vector_length_request */ = 1 )
+    : m_league_size(0)
+    , m_team_size(0)
+    , m_team_alloc(0)
+    , m_team_scratch_size { 0 , 0 }
+    , m_thread_scratch_size { 0 , 0 }
+    , m_chunk_size(0)
+    { init(league_size_request,traits::execution_space::thread_pool_size(2)); }
+
+  TeamPolicyInternal( int league_size_request
+            , int team_size_request
+            , int /* vector_length_request */ = 1 )
+    : m_league_size(0)
+    , m_team_size(0)
+    , m_team_alloc(0)
+    , m_team_scratch_size { 0 , 0 }
+    , m_thread_scratch_size { 0 , 0 }
+    , m_chunk_size(0)
+    { init(league_size_request,team_size_request); }
+
+  TeamPolicyInternal( int league_size_request
+            , const Kokkos::AUTO_t & /* team_size_request */
+            , int /* vector_length_request */ = 1 )
+    : m_league_size(0)
+    , m_team_size(0)
+    , m_team_alloc(0)
+    , m_team_scratch_size { 0 , 0 }
+    , m_thread_scratch_size { 0 , 0 }
+    , m_chunk_size(0)
+    { init(league_size_request,traits::execution_space::thread_pool_size(2)); }
+
+  inline int chunk_size() const { return m_chunk_size ; }
+
+  /** \brief set chunk_size to a discrete value*/
+  inline TeamPolicyInternal set_chunk_size(typename traits::index_type chunk_size_) const {
+    TeamPolicyInternal p = *this;
+    p.m_chunk_size = chunk_size_;
+    return p;
+  }
+
+  /** \brief set per team scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerTeamValue& per_team) const {
+    TeamPolicyInternal p = *this;
+    p.m_team_scratch_size[level] = per_team.value;
+    return p;
+  };
+
+  /** \brief set per thread scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerThreadValue& per_thread) const {
+    TeamPolicyInternal p = *this;
+    p.m_thread_scratch_size[level] = per_thread.value;
+    return p;
+  };
+
+  /** \brief set per thread and per team scratch size for a specific level of the scratch hierarchy */
+  inline TeamPolicyInternal set_scratch_size(const int& level, const PerTeamValue& per_team, const PerThreadValue& per_thread) const {
+    TeamPolicyInternal p = *this;
+    p.m_team_scratch_size[level] = per_team.value;
+    p.m_thread_scratch_size[level] = per_thread.value;
+    return p;
+  };
+
+private:
+  /** \brief finalize chunk_size if it was set to AUTO*/
+  inline void set_auto_chunk_size() {
+
+    int concurrency = traits::execution_space::thread_pool_size(0)/m_team_alloc;
+    if( concurrency==0 ) concurrency=1;
+
+    if(m_chunk_size > 0) {
+      if(!Impl::is_integral_power_of_two( m_chunk_size ))
+        Kokkos::abort("TeamPolicy blocking granularity must be power of two" );
+    }
+
+    int new_chunk_size = 1;
+    while(new_chunk_size*100*concurrency < m_league_size)
+      new_chunk_size *= 2;
+    if(new_chunk_size < 128) {
+      new_chunk_size = 1;
+      while( (new_chunk_size*40*concurrency < m_league_size ) && (new_chunk_size<128) )
+        new_chunk_size*=2;
+    }
+    m_chunk_size = new_chunk_size;
+  }
+
+public:
+
+  typedef Impl::ThreadsExecTeamMember member_type ;
+
+  friend class Impl::ThreadsExecTeamMember ;
+};
+
+} /*namespace Impl */
+} /* namespace Kokkos */
+
+
+namespace Kokkos {
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember>
+TeamThreadRange(const Impl::ThreadsExecTeamMember& thread, const iType& count)
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember>(thread,count);
+}
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember>
+TeamThreadRange( const Impl::ThreadsExecTeamMember& thread
+               , const iType & begin
+               , const iType & end
+               )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember>(thread,begin,end);
+}
+
+
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember >
+  ThreadVectorRange(const Impl::ThreadsExecTeamMember& thread, const iType& count) {
+  return Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember >(thread,count);
+}
+
+
+KOKKOS_INLINE_FUNCTION
+Impl::ThreadSingleStruct<Impl::ThreadsExecTeamMember> PerTeam(const Impl::ThreadsExecTeamMember& thread) {
+  return Impl::ThreadSingleStruct<Impl::ThreadsExecTeamMember>(thread);
+}
+
+KOKKOS_INLINE_FUNCTION
+Impl::VectorSingleStruct<Impl::ThreadsExecTeamMember> PerThread(const Impl::ThreadsExecTeamMember& thread) {
+  return Impl::VectorSingleStruct<Impl::ThreadsExecTeamMember>(thread);
+}
+} // namespace Kokkos
+
+namespace Kokkos {
+
+  /** \brief  Inter-thread parallel_for. Executes lambda(iType i) for each i=0..N-1.
+   *
+   * The range i=0..N-1 is mapped to all threads of the the calling thread team.
+   * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember>& loop_boundaries, const Lambda& lambda) {
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+/** \brief  Inter-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all threads of the the calling thread team and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember>& loop_boundaries,
+                     const Lambda & lambda, ValueType& result) {
+
+  result = ValueType();
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    result+=tmp;
+  }
+
+  result = loop_boundaries.thread.team_reduce(result,Impl::JoinAdd<ValueType>());
+}
+
+#if defined( KOKKOS_HAVE_CXX11 )
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember>& loop_boundaries,
+                     const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+  ValueType result = init_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    join(result,tmp);
+  }
+
+  init_result = loop_boundaries.thread.team_reduce(result,Impl::JoinLambdaAdapter<ValueType,JoinType>(join));
+}
+
+#endif /* #if defined( KOKKOS_HAVE_CXX11 ) */
+
+} //namespace Kokkos
+
+
+namespace Kokkos {
+/** \brief  Intra-thread vector parallel_for. Executes lambda(iType i) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread.
+ * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember >&
+    loop_boundaries, const Lambda& lambda) {
+  #ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+  #pragma ivdep
+  #endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a summation of
+ * val is performed and put into result. This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember >&
+      loop_boundaries, const Lambda & lambda, ValueType& result) {
+  result = ValueType();
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    result+=tmp;
+  }
+}
+
+/** \brief  Intra-thread vector parallel_reduce. Executes lambda(iType i, ValueType & val) for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes of the the calling thread and a reduction of
+ * val is performed using JoinType(ValueType& val, const ValueType& update) and put into init_result.
+ * The input value of init_result is used as initializer for temporary variables of ValueType. Therefore
+ * the input value should be the neutral element with respect to the join operation (e.g. '0 for +-' or
+ * '1 for *'). This functionality requires C++11 support.*/
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember >&
+      loop_boundaries, const Lambda & lambda, const JoinType& join, ValueType& init_result) {
+
+  ValueType result = init_result;
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    ValueType tmp = ValueType();
+    lambda(i,tmp);
+    join(result,tmp);
+  }
+  init_result = result;
+}
+
+/** \brief  Intra-thread vector parallel exclusive prefix sum. Executes lambda(iType i, ValueType & val, bool final)
+ *          for each i=0..N-1.
+ *
+ * The range i=0..N-1 is mapped to all vector lanes in the thread and a scan operation is performed.
+ * Depending on the target execution space the operator might be called twice: once with final=false
+ * and once with final=true. When final==true val contains the prefix sum value. The contribution of this
+ * "i" needs to be added to val no matter whether final==true or not. In a serial execution
+ * (i.e. team_size==1) the operator is only called once with final==true. Scan_val will be set
+ * to the final sum value over all vector lanes.
+ * This functionality requires C++11 support.*/
+template< typename iType, class FunctorType >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan(const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::ThreadsExecTeamMember >&
+      loop_boundaries, const FunctorType & lambda) {
+
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
+  typedef typename ValueTraits::value_type value_type ;
+
+  value_type scan_val = value_type();
+
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+#pragma ivdep
+#endif
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    lambda(i,scan_val,true);
+  }
+}
+
+} // namespace Kokkos
+
+namespace Kokkos {
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::ThreadsExecTeamMember>& single_struct, const FunctorType& lambda) {
+  lambda();
+}
+
+template<class FunctorType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::ThreadsExecTeamMember>& single_struct, const FunctorType& lambda) {
+  if(single_struct.team_member.team_rank()==0) lambda();
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::VectorSingleStruct<Impl::ThreadsExecTeamMember>& single_struct, const FunctorType& lambda, ValueType& val) {
+  lambda(val);
+}
+
+template<class FunctorType, class ValueType>
+KOKKOS_INLINE_FUNCTION
+void single(const Impl::ThreadSingleStruct<Impl::ThreadsExecTeamMember>& single_struct, const FunctorType& lambda, ValueType& val) {
+  if(single_struct.team_member.team_rank()==0) {
+    lambda(val);
+  }
+  single_struct.team_member.team_broadcast(val,0);
+}
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #define KOKKOS_THREADSTEAM_HPP */
+
diff --git a/lib/kokkos/core/src/Threads/Kokkos_Threads_Parallel.hpp b/lib/kokkos/core/src/Threads/Kokkos_Threads_Parallel.hpp
new file mode 100644
index 0000000000..1aba00c94b
--- /dev/null
+++ b/lib/kokkos/core/src/Threads/Kokkos_Threads_Parallel.hpp
@@ -0,0 +1,658 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_THREADS_PARALLEL_HPP
+#define KOKKOS_THREADS_PARALLEL_HPP
+
+#include <vector>
+#include <iostream> 
+
+#include <Kokkos_Parallel.hpp>
+
+#include <impl/Kokkos_StaticAssert.hpp>
+#include <impl/Kokkos_FunctorAdapter.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+/* ParallelFor Kokkos::Threads with RangePolicy */
+
+template< class FunctorType , class ... Traits >
+class ParallelFor< FunctorType
+                 , Kokkos::RangePolicy< Traits ... >
+                 , Kokkos::Threads
+                 >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy ;
+  typedef typename Policy::work_tag    WorkTag ;
+  typedef typename Policy::WorkRange   WorkRange ;
+  typedef typename Policy::member_type Member ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend )
+    {
+      #if defined( KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION ) && \
+          defined( KOKKOS_HAVE_PRAGMA_IVDEP )
+      #pragma ivdep
+      #endif
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( i );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member ibeg , const Member iend )
+    {
+      const TagType t{} ;
+      #if defined( KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION ) && \
+          defined( KOKKOS_HAVE_PRAGMA_IVDEP )
+      #pragma ivdep
+      #endif
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( t , i );
+      }
+    }
+
+  static void exec( ThreadsExec & exec , const void * arg )
+  {
+    exec_schedule<typename Policy::schedule_type::type>(exec,arg);
+  }
+
+  template<class Schedule>
+  static
+  typename std::enable_if< std::is_same<Schedule,Kokkos::Static>::value >::type
+  exec_schedule( ThreadsExec & exec , const void * arg )
+  {
+    const ParallelFor & self = * ((const ParallelFor *) arg );
+
+    WorkRange range( self.m_policy , exec.pool_rank() , exec.pool_size() );
+
+    ParallelFor::template exec_range< WorkTag >
+      ( self.m_functor , range.begin() , range.end() );
+
+    exec.fan_in();
+  }
+
+  template<class Schedule>
+  static
+  typename std::enable_if< std::is_same<Schedule,Kokkos::Dynamic>::value >::type
+  exec_schedule( ThreadsExec & exec , const void * arg )
+  {
+    const ParallelFor & self = * ((const ParallelFor *) arg );
+
+    WorkRange range( self.m_policy , exec.pool_rank() , exec.pool_size() );
+
+    exec.set_work_range(range.begin(),range.end(),self.m_policy.chunk_size());
+    exec.reset_steal_target();
+    exec.barrier();
+
+    long work_index = exec.get_work_index();
+
+    while(work_index != -1) {
+      const Member begin = static_cast<Member>(work_index) * self.m_policy.chunk_size();
+      const Member end = begin + self.m_policy.chunk_size() < self.m_policy.end()?begin+self.m_policy.chunk_size():self.m_policy.end();
+
+      ParallelFor::template exec_range< WorkTag >
+        ( self.m_functor , begin , end );
+      work_index = exec.get_work_index();
+    }
+
+    exec.fan_in();
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      ThreadsExec::start( & ParallelFor::exec , this );
+      ThreadsExec::fence();
+    }
+
+  ParallelFor( const FunctorType & arg_functor
+             , const Policy      & arg_policy )
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    {}
+};
+
+//----------------------------------------------------------------------------
+/* ParallelFor Kokkos::Threads with TeamPolicy */
+
+template< class FunctorType , class ... Properties >
+class ParallelFor< FunctorType
+                 , Kokkos::TeamPolicy< Properties ... >
+                 , Kokkos::Threads
+                 >
+{
+private:
+
+  typedef Kokkos::Impl::TeamPolicyInternal< Kokkos::Threads, Properties ... >  Policy ;
+  typedef typename Policy::work_tag                    WorkTag ;
+  typedef typename Policy::member_type                 Member ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+  const int          m_shared ;
+
+  template< class TagType , class Schedule>
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value
+  && std::is_same<Schedule,Kokkos::Static>::value >::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      for ( ; member.valid_static() ; member.next_static() ) {
+        functor( member );
+      }
+    }
+
+  template< class TagType , class Schedule>
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value
+  && std::is_same<Schedule,Kokkos::Static>::value >::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      const TagType t{} ;
+      for ( ; member.valid_static() ; member.next_static() ) {
+        functor( t , member );
+      }
+    }
+
+  template< class TagType , class Schedule>
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value
+  && std::is_same<Schedule,Kokkos::Dynamic>::value >::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+
+      for ( ; member.valid_dynamic() ; member.next_dynamic() ) {
+        functor( member );
+      }
+    }
+
+  template< class TagType , class Schedule>
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value
+                          && std::is_same<Schedule,Kokkos::Dynamic>::value >::type
+  exec_team( const FunctorType & functor , Member member )
+    {
+      const TagType t{} ;
+      for ( ; member.valid_dynamic() ; member.next_dynamic() ) {
+        functor( t , member );
+      }
+    }
+
+  static void exec( ThreadsExec & exec , const void * arg )
+  {
+    const ParallelFor & self = * ((const ParallelFor *) arg );
+
+    ParallelFor::exec_team< WorkTag , typename Policy::schedule_type::type >
+      ( self.m_functor , Member( & exec , self.m_policy , self.m_shared ) );
+
+    exec.barrier();
+    exec.fan_in();
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      ThreadsExec::resize_scratch( 0 , Policy::member_type::team_reduce_size() + m_shared );
+
+      ThreadsExec::start( & ParallelFor::exec , this );
+
+      ThreadsExec::fence();
+    }
+
+  ParallelFor( const FunctorType & arg_functor
+             , const Policy      & arg_policy )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    , m_shared( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , arg_policy.team_size() ) )
+    { }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+/* ParallelReduce with Kokkos::Threads and RangePolicy */
+
+template< class FunctorType , class ReducerType, class ... Traits >
+class ParallelReduce< FunctorType
+                    , Kokkos::RangePolicy< Traits ... >
+                    , ReducerType
+                    , Kokkos::Threads
+                    >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy ;
+
+  typedef typename Policy::work_tag    WorkTag ;
+  typedef typename Policy::WorkRange   WorkRange ;
+  typedef typename Policy::member_type Member ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd, WorkTag > ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+  const ReducerType   m_reducer ;
+  const pointer_type m_result_ptr ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member & ibeg , const Member & iend
+            , reference_type update )
+    {
+      #if defined( KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION ) && \
+          defined( KOKKOS_HAVE_PRAGMA_IVDEP )
+      #pragma ivdep
+      #endif
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( i , update );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member & ibeg , const Member & iend
+            , reference_type update )
+    {
+      const TagType t{} ;
+      #if defined( KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION ) && \
+          defined( KOKKOS_HAVE_PRAGMA_IVDEP )
+      #pragma ivdep
+      #endif
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( t , i , update );
+      }
+    }
+
+  static void
+  exec( ThreadsExec & exec , const void * arg ) {
+    exec_schedule<typename Policy::schedule_type::type>(exec, arg);
+  }
+
+  template<class Schedule>
+  static
+  typename std::enable_if< std::is_same<Schedule,Kokkos::Static>::value >::type
+  exec_schedule( ThreadsExec & exec , const void * arg )
+  {
+    const ParallelReduce & self = * ((const ParallelReduce *) arg );
+    const WorkRange range( self.m_policy, exec.pool_rank(), exec.pool_size() );
+
+    ParallelReduce::template exec_range< WorkTag >
+      ( self.m_functor , range.begin() , range.end() 
+      , ValueInit::init( ReducerConditional::select(self.m_functor , self.m_reducer) , exec.reduce_memory() ) );
+
+    exec.template fan_in_reduce< ReducerTypeFwd , WorkTag >( ReducerConditional::select(self.m_functor , self.m_reducer) );
+  }
+
+  template<class Schedule>
+  static
+  typename std::enable_if< std::is_same<Schedule,Kokkos::Dynamic>::value >::type
+    exec_schedule( ThreadsExec & exec , const void * arg )
+  {
+    const ParallelReduce & self = * ((const ParallelReduce *) arg );
+    const WorkRange range( self.m_policy, exec.pool_rank(), exec.pool_size() );
+
+    exec.set_work_range(range.begin(),range.end(),self.m_policy.chunk_size());
+    exec.reset_steal_target();
+    exec.barrier();
+
+    long work_index = exec.get_work_index();
+    reference_type update = ValueInit::init( ReducerConditional::select(self.m_functor , self.m_reducer) , exec.reduce_memory() );
+    while(work_index != -1) {
+      const Member begin = static_cast<Member>(work_index) * self.m_policy.chunk_size();
+      const Member end = begin + self.m_policy.chunk_size() < self.m_policy.end()?begin+self.m_policy.chunk_size():self.m_policy.end();
+      ParallelReduce::template exec_range< WorkTag >
+        ( self.m_functor , begin , end
+        , update );
+      work_index = exec.get_work_index();
+    }
+
+    exec.template fan_in_reduce< ReducerTypeFwd , WorkTag >( ReducerConditional::select(self.m_functor , self.m_reducer) );
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      ThreadsExec::resize_scratch( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) , 0 );
+
+      ThreadsExec::start( & ParallelReduce::exec , this );
+
+      ThreadsExec::fence();
+
+      if ( m_result_ptr ) {
+
+        const pointer_type data =
+          (pointer_type) ThreadsExec::root_reduce_scratch();
+
+        const unsigned n = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer) );
+        for ( unsigned i = 0 ; i < n ; ++i ) { m_result_ptr[i] = data[i]; }
+      }
+    }
+
+  template< class HostViewType >
+  ParallelReduce( const FunctorType  & arg_functor ,
+                  const Policy       & arg_policy ,
+                  const HostViewType & arg_result_view ,
+                  typename std::enable_if<
+                               Kokkos::is_view< HostViewType >::value &&
+                              !Kokkos::is_reducer_type<ReducerType>::value
+                  ,void*>::type = NULL)
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    , m_reducer( InvalidType() )
+    , m_result_ptr( arg_result_view.ptr_on_device() )
+    {
+      static_assert( Kokkos::is_view< HostViewType >::value
+        , "Kokkos::Threads reduce result must be a View" );
+
+      static_assert( std::is_same< typename HostViewType::memory_space , HostSpace >::value
+        , "Kokkos::Threads reduce result must be a View in HostSpace" );
+    }
+
+  inline
+  ParallelReduce( const FunctorType & arg_functor
+                , Policy       arg_policy
+                , const ReducerType& reducer )
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    , m_reducer( reducer )
+    , m_result_ptr(  reducer.result_view().data() )
+    {
+      /*static_assert( std::is_same< typename ViewType::memory_space
+                                      , Kokkos::HostSpace >::value
+        , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace" );*/
+    }
+
+};
+
+//----------------------------------------------------------------------------
+/* ParallelReduce with Kokkos::Threads and TeamPolicy */
+
+template< class FunctorType , class ReducerType, class ... Properties >
+class ParallelReduce< FunctorType
+                    , Kokkos::TeamPolicy< Properties ... >
+                    , ReducerType
+                    , Kokkos::Threads
+                    >
+{
+private:
+
+  typedef Kokkos::Impl::TeamPolicyInternal< Kokkos::Threads, Properties ... >              Policy ;
+  typedef typename Policy::work_tag                                WorkTag ;
+  typedef typename Policy::member_type                             Member ;
+
+  typedef Kokkos::Impl::if_c< std::is_same<InvalidType,ReducerType>::value, FunctorType, ReducerType> ReducerConditional;
+  typedef typename ReducerConditional::type ReducerTypeFwd;
+
+  typedef Kokkos::Impl::FunctorValueTraits< ReducerTypeFwd, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   ReducerTypeFwd, WorkTag > ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+  const ReducerType  m_reducer ;
+  const pointer_type m_result_ptr ;
+  const int          m_shared ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_team( const FunctorType & functor , Member member , reference_type update )
+    {
+      for ( ; member.valid_static() ; member.next_static() ) {
+        functor( member , update );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_team( const FunctorType & functor , Member member , reference_type update )
+    {
+      const TagType t{} ;
+      for ( ; member.valid_static() ; member.next_static() ) {
+        functor( t , member , update );
+      }
+    }
+
+  static void exec( ThreadsExec & exec , const void * arg )
+  {
+    const ParallelReduce & self = * ((const ParallelReduce *) arg );
+
+    ParallelReduce::template exec_team< WorkTag >
+      ( self.m_functor , Member( & exec , self.m_policy , self.m_shared )
+      , ValueInit::init( ReducerConditional::select(self.m_functor , self.m_reducer) , exec.reduce_memory() ) );
+
+    exec.template fan_in_reduce< ReducerTypeFwd , WorkTag >( ReducerConditional::select(self.m_functor , self.m_reducer) );
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      ThreadsExec::resize_scratch( ValueTraits::value_size( ReducerConditional::select(m_functor , m_reducer) ) , Policy::member_type::team_reduce_size() + m_shared );
+
+      ThreadsExec::start( & ParallelReduce::exec , this );
+
+      ThreadsExec::fence();
+
+      if ( m_result_ptr ) {
+
+        const pointer_type data = (pointer_type) ThreadsExec::root_reduce_scratch();
+
+        const unsigned n = ValueTraits::value_count( ReducerConditional::select(m_functor , m_reducer) );
+        for ( unsigned i = 0 ; i < n ; ++i ) { m_result_ptr[i] = data[i]; }
+      }
+    }
+
+  template< class ViewType >
+  inline
+  ParallelReduce( const FunctorType  & arg_functor ,
+                  const Policy       & arg_policy ,
+                  const ViewType     & arg_result ,
+                  typename std::enable_if<
+                    Kokkos::is_view< ViewType >::value &&
+                    !Kokkos::is_reducer_type<ReducerType>::value
+                    ,void*>::type = NULL)
+    : m_functor( arg_functor )
+    , m_policy(  arg_policy )
+    , m_reducer( InvalidType() )
+    , m_result_ptr( arg_result.ptr_on_device() )
+    , m_shared( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , arg_policy.team_size() ) )
+    {}
+
+  inline
+  ParallelReduce( const FunctorType & arg_functor
+    , Policy       arg_policy
+    , const ReducerType& reducer )
+  : m_functor( arg_functor )
+  , m_policy(  arg_policy )
+  , m_reducer( reducer )
+  , m_result_ptr(  reducer.result_view().data() )
+  , m_shared( arg_policy.scratch_size(0) + arg_policy.scratch_size(1) + FunctorTeamShmemSize< FunctorType >::value( arg_functor , arg_policy.team_size() ) )
+  {
+  /*static_assert( std::is_same< typename ViewType::memory_space
+                          , Kokkos::HostSpace >::value
+  , "Reduction result on Kokkos::OpenMP must be a Kokkos::View in HostSpace" );*/
+  }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+/* ParallelScan with Kokkos::Threads and RangePolicy */
+
+template< class FunctorType , class ... Traits >
+class ParallelScan< FunctorType
+                  , Kokkos::RangePolicy< Traits ... >
+                  , Kokkos::Threads
+                  >
+{
+private:
+
+  typedef Kokkos::RangePolicy< Traits ... > Policy ;
+  typedef typename Policy::WorkRange                               WorkRange ;
+  typedef typename Policy::work_tag                                WorkTag ;
+  typedef typename Policy::member_type                             Member ;
+  typedef Kokkos::Impl::FunctorValueTraits< FunctorType, WorkTag > ValueTraits ;
+  typedef Kokkos::Impl::FunctorValueInit<   FunctorType, WorkTag > ValueInit ;
+
+  typedef typename ValueTraits::pointer_type    pointer_type ;
+  typedef typename ValueTraits::reference_type  reference_type ;
+
+  const FunctorType  m_functor ;
+  const Policy       m_policy ;
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member & ibeg , const Member & iend
+            , reference_type update , const bool final )
+    {
+      #if defined( KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION ) && \
+          defined( KOKKOS_HAVE_PRAGMA_IVDEP )
+      #pragma ivdep
+      #endif
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( i , update , final );
+      }
+    }
+
+  template< class TagType >
+  inline static
+  typename std::enable_if< ! std::is_same< TagType , void >::value >::type
+  exec_range( const FunctorType & functor
+            , const Member & ibeg , const Member & iend
+            , reference_type update , const bool final )
+    {
+      const TagType t{} ;
+      #if defined( KOKKOS_OPT_RANGE_AGGRESSIVE_VECTORIZATION ) && \
+          defined( KOKKOS_HAVE_PRAGMA_IVDEP )
+      #pragma ivdep
+      #endif
+      for ( Member i = ibeg ; i < iend ; ++i ) {
+        functor( t , i , update , final );
+      }
+    }
+
+  static void exec( ThreadsExec & exec , const void * arg )
+  {
+    const ParallelScan & self = * ((const ParallelScan *) arg );
+
+    const WorkRange range( self.m_policy, exec.pool_rank(), exec.pool_size() );
+
+    reference_type update =
+      ValueInit::init( self.m_functor , exec.reduce_memory() );
+
+    ParallelScan::template exec_range< WorkTag >
+      ( self.m_functor , range.begin(), range.end(), update, false );
+
+    //  exec.template scan_large<FunctorType,WorkTag>( self.m_functor );
+    exec.template scan_small<FunctorType,WorkTag>( self.m_functor );
+
+    ParallelScan::template exec_range< WorkTag >
+      ( self.m_functor , range.begin(), range.end(), update, true );
+
+    exec.fan_in();
+  }
+
+public:
+
+  inline
+  void execute() const
+    {
+      ThreadsExec::resize_scratch( 2 * ValueTraits::value_size( m_functor ) , 0 );
+      ThreadsExec::start( & ParallelScan::exec , this );
+      ThreadsExec::fence();
+    }
+
+  ParallelScan( const FunctorType & arg_functor
+              , const Policy      & arg_policy )
+    : m_functor( arg_functor )
+    , m_policy( arg_policy )
+    { }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #define KOKKOS_THREADS_PARALLEL_HPP */
+
diff --git a/lib/kokkos/core/src/Threads/Kokkos_Threads_TaskPolicy.cpp b/lib/kokkos/core/src/Threads/Kokkos_Threads_TaskPolicy.cpp
new file mode 100644
index 0000000000..e1599284b2
--- /dev/null
+++ b/lib/kokkos/core/src/Threads/Kokkos_Threads_TaskPolicy.cpp
@@ -0,0 +1,930 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#include <stdio.h>
+#include <iostream>
+#include <sstream>
+#include <Kokkos_Core.hpp>
+#include <Threads/Kokkos_Threads_TaskPolicy.hpp>
+
+#if defined( KOKKOS_HAVE_PTHREAD ) && defined( KOKKOS_ENABLE_TASKPOLICY )
+
+#define QLOCK   (reinterpret_cast<void*>( ~((uintptr_t)0) ))
+#define QDENIED (reinterpret_cast<void*>( ~((uintptr_t)0) - 1 ))
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+void ThreadsTaskPolicyQueue::Destroy::destroy_shared_allocation()
+{
+  // Verify the queue is empty
+
+  if ( m_policy->m_count_ready ||
+       m_policy->m_team[0] ||
+       m_policy->m_team[1] ||
+       m_policy->m_team[2] ||
+       m_policy->m_serial[0] ||
+       m_policy->m_serial[1] ||
+       m_policy->m_serial[2] ) {
+    Kokkos::abort("ThreadsTaskPolicyQueue ERROR : Attempt to destroy non-empty queue" );
+  }
+
+  m_policy->~ThreadsTaskPolicyQueue();
+}
+
+//----------------------------------------------------------------------------
+
+ThreadsTaskPolicyQueue::~ThreadsTaskPolicyQueue()
+{
+}
+
+ThreadsTaskPolicyQueue::ThreadsTaskPolicyQueue
+  ( const unsigned arg_task_max_count
+  , const unsigned arg_task_max_size
+  , const unsigned arg_task_default_dependence_capacity
+  , const unsigned arg_task_team_size
+  )
+  : m_space( Kokkos::Threads::memory_space()
+           , arg_task_max_size * arg_task_max_count * 1.2
+           , 16 /* log2(superblock size) */
+           )
+  , m_team { 0 , 0 , 0 }
+  , m_serial { 0 , 0 , 0 }
+  , m_team_size( arg_task_team_size )
+  , m_default_dependence_capacity( arg_task_default_dependence_capacity )
+  , m_count_ready(0)
+  , m_count_alloc(0)
+{
+  const int threads_total    = Threads::thread_pool_size(0);
+  const int threads_per_numa = Threads::thread_pool_size(1);
+  const int threads_per_core = Threads::thread_pool_size(2);
+
+  if ( 0 == m_team_size ) {
+    // If a team task then claim for execution until count is zero
+    // Issue: team collectives cannot assume which pool members are in the team.
+    // Issue: team must only span a single NUMA region.
+
+    // If more than one thread per core then map cores to work team,
+    // else  map numa to work team.
+
+    if      ( 1 < threads_per_core ) m_team_size = threads_per_core ;
+    else if ( 1 < threads_per_numa ) m_team_size = threads_per_numa ;
+    else                             m_team_size = 1 ;
+  }
+
+  // Verify a valid team size
+  const bool valid_team_size =
+    ( 0 < m_team_size && m_team_size <= threads_total ) &&
+    (
+      ( 1                == m_team_size ) ||
+      ( threads_per_core == m_team_size ) ||
+      ( threads_per_numa == m_team_size )
+    );
+
+  if ( ! valid_team_size ) {
+    std::ostringstream msg ;
+
+    msg << "Kokkos::Experimental::TaskPolicy< Kokkos::Threads > ERROR"
+        << " invalid team_size(" << m_team_size << ")"
+        << " threads_per_core(" << threads_per_core << ")"
+        << " threads_per_numa(" << threads_per_numa << ")"
+        << " threads_total(" << threads_total << ")"
+        ;
+
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  Kokkos::memory_fence();
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsTaskPolicyQueue::driver( Kokkos::Impl::ThreadsExec & exec
+                                   , const void * arg )
+{
+  // Whole thread pool is calling this function
+
+  typedef Kokkos::Impl::ThreadsExecTeamMember member_type ;
+
+  ThreadsTaskPolicyQueue & self =
+    * reinterpret_cast< ThreadsTaskPolicyQueue * >( const_cast<void*>(arg) );
+
+  // Create the thread team member with shared memory for the given task.
+
+  const TeamPolicy< Kokkos::Threads > team_policy( 1 , self.m_team_size );
+
+  member_type team_member( & exec , team_policy , 0 );
+
+  Kokkos::Impl::ThreadsExec & exec_team_base =
+    team_member.threads_exec_team_base();
+
+  task_root_type * volatile * const task_team_ptr =
+    reinterpret_cast<task_root_type**>( exec_team_base.reduce_memory() );
+
+  volatile int * const work_team_ptr =
+    reinterpret_cast<volatile int*>( task_team_ptr + 1 );
+
+  // Each team must iterate this loop synchronously
+  // to insure team-execution of team-task.
+
+  const bool team_lead = team_member.team_fan_in();
+
+  bool work_team = true ;
+
+  while ( work_team ) {
+
+    task_root_type * task = 0 ;
+
+    // Start here with members in a fan_in state
+
+    if ( team_lead ) {
+      // Team lead queries the ready count for a team-consistent view.
+      *work_team_ptr = 0 != self.m_count_ready ;
+
+      // Only the team lead attempts to pop a team task from the queues
+      for ( int i = 0 ; i < int(NPRIORITY) && 0 == task ; ++i ) {
+        if ( ( i < 2 /* regular queue */ )
+             || ( ! self.m_space.is_empty() /* waiting for memory queue */ ) ) {
+          task = pop_ready_task( & self.m_team[i] );
+        }
+      }
+
+      *task_team_ptr = task ;
+    }
+
+    Kokkos::memory_fence();
+
+    team_member.team_fan_out();
+
+    work_team = *work_team_ptr ;
+
+    // Query if team acquired a team task
+
+    if ( 0 != ( task = *task_team_ptr ) ) {
+      // Set shared memory
+      team_member.set_league_shmem( 0 , 1 , task->m_shmem_size );
+
+      (*task->m_team)( task , team_member );
+
+      // The team task called the functor,
+      // called the team_fan_in(), and
+      // if completed the team lead destroyed the task functor.
+
+      if ( team_lead ) {
+        self.complete_executed_task( task );
+      }
+    }
+    else {
+      // No team task acquired, each thread try a serial task
+      // Try the priority queue, then the regular queue.
+      for ( int i = 0 ; i < int(NPRIORITY) && 0 == task ; ++i ) {
+        if ( ( i < 2 /* regular queue */ )
+             || ( ! self.m_space.is_empty() /* waiting for memory queue */ ) ) {
+          task = pop_ready_task( & self.m_serial[i] );
+        }
+      }
+
+      if ( 0 != task ) {
+
+        (*task->m_serial)( task );
+
+        self.complete_executed_task( task );
+      }
+
+      team_member.team_fan_in();
+    }
+  }
+
+  team_member.team_fan_out();
+
+  exec.fan_in();
+}
+
+//----------------------------------------------------------------------------
+
+ThreadsTaskPolicyQueue::task_root_type *
+ThreadsTaskPolicyQueue::pop_ready_task(
+  ThreadsTaskPolicyQueue::task_root_type * volatile * const queue )
+{
+  task_root_type * const q_lock = reinterpret_cast<task_root_type*>(QLOCK);
+  task_root_type * task = 0 ;
+  task_root_type * const task_claim = *queue ;
+
+  if ( ( q_lock != task_claim ) && ( 0 != task_claim ) ) {
+
+    // Queue is not locked and not null, try to claim head of queue.
+    // Is a race among threads to claim the queue.
+
+    if ( task_claim == atomic_compare_exchange(queue,task_claim,q_lock) ) {
+
+      // Aquired the task which must be in the waiting state.
+
+      const int claim_state =
+        atomic_compare_exchange( & task_claim->m_state
+                               , int(TASK_STATE_WAITING)
+                               , int(TASK_STATE_EXECUTING) );
+
+      task_root_type * lock_verify = 0 ;
+
+      if ( claim_state == int(TASK_STATE_WAITING) ) {
+
+        // Transitioned this task from waiting to executing
+        // Update the queue to the next entry and release the lock
+
+        task_root_type * const next =
+          *((task_root_type * volatile *) & task_claim->m_next );
+
+        *((task_root_type * volatile *) & task_claim->m_next ) = 0 ;
+
+        lock_verify = atomic_compare_exchange( queue , q_lock , next );
+      }
+
+      if ( ( claim_state != int(TASK_STATE_WAITING) ) |
+           ( q_lock != lock_verify ) ) {
+
+        fprintf(stderr,"ThreadsTaskPolicyQueue::pop_ready_task(0x%lx) task(0x%lx) state(%d) ERROR %s\n"
+                      , (unsigned long) queue
+                      , (unsigned long) task
+                      , claim_state
+                      , ( claim_state != int(TASK_STATE_WAITING)
+                        ? "NOT WAITING"
+                        : "UNLOCK" ) );
+        fflush(stderr);
+        Kokkos::abort("ThreadsTaskPolicyQueue::pop_ready_task");
+      }
+
+      task = task_claim ;
+    }
+  }
+
+  return task ;
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsTaskPolicyQueue::complete_executed_task(
+  ThreadsTaskPolicyQueue::task_root_type * task )
+{
+  task_root_type * const q_denied = reinterpret_cast<task_root_type*>(QDENIED);
+
+  // State is either executing or if respawned then waiting,
+  // try to transition from executing to complete.
+  // Reads the current value.
+
+  const int state_old =
+    atomic_compare_exchange( & task->m_state
+                           , int(Kokkos::Experimental::TASK_STATE_EXECUTING)
+                           , int(Kokkos::Experimental::TASK_STATE_COMPLETE) );
+
+  if ( int(Kokkos::Experimental::TASK_STATE_WAITING) == state_old ) {
+    // Task requested a respawn so reschedule it.
+    // The reference count will be incremented if placed in a queue.
+    schedule_task( task , false /* not the initial spawn */ );
+  }
+  else if ( int(Kokkos::Experimental::TASK_STATE_EXECUTING) == state_old ) {
+    /* Task is complete */
+
+    // Clear dependences of this task before locking wait queue
+
+    task->clear_dependence();
+
+    // Stop other tasks from adding themselves to this task's wait queue.
+    // The wait queue is updated concurrently so guard with an atomic.
+
+    task_root_type * wait_queue     = *((task_root_type * volatile *) & task->m_wait );
+    task_root_type * wait_queue_old = 0 ;
+
+    do {
+      wait_queue_old = wait_queue ;
+      wait_queue     = atomic_compare_exchange( & task->m_wait , wait_queue_old , q_denied );
+    } while ( wait_queue_old != wait_queue );
+
+    // The task has been removed from ready queue and
+    // execution is complete so decrement the reference count.
+    // The reference count was incremented by the initial spawning.
+    // The task may be deleted if this was the last reference.
+    task_root_type::assign( & task , 0 );
+
+    // Pop waiting tasks and schedule them
+    while ( wait_queue ) {
+      task_root_type * const x = wait_queue ; wait_queue = x->m_next ; x->m_next = 0 ;
+      schedule_task( x , false /* not the initial spawn */ );
+    }
+  }
+  else {
+    fprintf( stderr
+           , "ThreadsTaskPolicyQueue::complete_executed_task(0x%lx) ERROR state_old(%d) dep_size(%d)\n"
+           , (unsigned long)( task )
+           , int(state_old)
+           , task->m_dep_size
+           );
+    fflush( stderr );
+    Kokkos::abort("ThreadsTaskPolicyQueue::complete_executed_task" );
+  }
+
+  // If the task was respawned it may have already been
+  // put in a ready queue and the count incremented.
+  // By decrementing the count last it will never go to zero
+  // with a ready or executing task.
+
+  atomic_fetch_add( & m_count_ready , -1 );
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsTaskPolicyQueue::reschedule_task(
+  ThreadsTaskPolicyQueue::task_root_type * const task )
+{
+  // Reschedule transitions from executing back to waiting.
+  const int old_state =
+    atomic_compare_exchange( & task->m_state
+                           , int(TASK_STATE_EXECUTING)
+                           , int(TASK_STATE_WAITING) );
+
+  if ( old_state != int(TASK_STATE_EXECUTING) ) {
+
+    fprintf( stderr
+           , "ThreadsTaskPolicyQueue::reschedule_task(0x%lx) ERROR state(%d)\n"
+           , (unsigned long) task
+           , old_state
+           );
+    fflush(stderr);
+    Kokkos::abort("ThreadsTaskPolicyQueue::reschedule" );
+  }
+}
+
+void ThreadsTaskPolicyQueue::schedule_task
+  ( ThreadsTaskPolicyQueue::task_root_type * const task 
+  , const bool initial_spawn )
+{
+  task_root_type * const q_lock = reinterpret_cast<task_root_type*>(QLOCK);
+  task_root_type * const q_denied = reinterpret_cast<task_root_type*>(QDENIED);
+
+  //----------------------------------------
+  // State is either constructing or already waiting.
+  // If constructing then transition to waiting.
+
+  {
+    const int old_state = atomic_compare_exchange( & task->m_state
+                                                 , int(TASK_STATE_CONSTRUCTING)
+                                                 , int(TASK_STATE_WAITING) );
+
+    // Head of linked list of tasks waiting on this task
+    task_root_type * const waitTask =
+      *((task_root_type * volatile const *) & task->m_wait );
+
+    // Member of linked list of tasks waiting on some other task
+    task_root_type * const next =
+      *((task_root_type * volatile const *) & task->m_next );
+
+    // An incomplete and non-executing task has:
+    //   task->m_state == TASK_STATE_CONSTRUCTING or TASK_STATE_WAITING
+    //   task->m_wait  != q_denied
+    //   task->m_next  == 0
+    //
+    if ( ( q_denied == waitTask ) ||
+         ( 0 != next ) ||
+         ( old_state != int(TASK_STATE_CONSTRUCTING) &&
+           old_state != int(TASK_STATE_WAITING) ) ) {
+      fprintf(stderr,"ThreadsTaskPolicyQueue::schedule_task(0x%lx) STATE ERROR: state(%d) wait(0x%lx) next(0x%lx)\n"
+                    , (unsigned long) task
+                    , old_state
+                    , (unsigned long) waitTask
+                    , (unsigned long) next );
+      fflush(stderr);
+      Kokkos::abort("ThreadsTaskPolicyQueue::schedule" );
+    }
+  }
+
+  //----------------------------------------
+
+  if ( initial_spawn ) {
+    // The initial spawn of a task increments the reference count
+    // for the task's existence in either a waiting or ready queue
+    // until the task has completed.
+    // Completing the task's execution is the matching
+    // decrement of the reference count.
+
+    task_root_type::assign( 0 , task );
+  }
+
+  //----------------------------------------
+  // Insert this task into a dependence task that is not complete.
+  // Push on to that task's wait queue.
+
+  bool attempt_insert_in_queue = true ;
+
+  task_root_type * volatile * queue =
+    task->m_dep_size ? & task->m_dep[0]->m_wait : (task_root_type **) 0 ;
+
+  for ( int i = 0 ; attempt_insert_in_queue && ( 0 != queue ) ; ) {
+
+    task_root_type * const head_value_old = *queue ;
+
+    if ( q_denied == head_value_old ) {
+      // Wait queue is closed because task is complete,
+      // try again with the next dependence wait queue.
+      ++i ;
+      queue = i < task->m_dep_size ? & task->m_dep[i]->m_wait
+                                   : (task_root_type **) 0 ;
+    }
+    else {
+
+      // Wait queue is open and not denied.
+      // Have exclusive access to this task.
+      // Assign m_next assuming a successfull insertion into the queue.
+      // Fence the memory assignment before attempting the CAS.
+
+      *((task_root_type * volatile *) & task->m_next ) = head_value_old ;
+
+      memory_fence();
+
+      // Attempt to insert this task into the queue.
+      // If fails then continue the attempt.
+
+      attempt_insert_in_queue =
+        head_value_old != atomic_compare_exchange(queue,head_value_old,task);
+    }
+  }
+
+  //----------------------------------------
+  // All dependences are complete, insert into the ready list
+
+  if ( attempt_insert_in_queue ) {
+
+    // Increment the count of ready tasks.
+    // Count will be decremented when task is complete.
+
+    atomic_fetch_add( & m_count_ready , 1 );
+
+    queue = task->m_queue ;
+
+    while ( attempt_insert_in_queue ) {
+
+      // A locked queue is being popped.
+
+      task_root_type * const head_value_old = *queue ;
+
+      if ( q_lock != head_value_old ) {
+        // Read the head of ready queue,
+        // if same as previous value then CAS locks the ready queue
+
+        // Have exclusive access to this task,
+        // assign to head of queue, assuming successful insert
+        // Fence assignment before attempting insert.
+        *((task_root_type * volatile *) & task->m_next ) = head_value_old ;
+
+        memory_fence();
+
+        attempt_insert_in_queue =
+          head_value_old != atomic_compare_exchange(queue,head_value_old,task);
+      }
+    }
+  }
+}
+
+
+void TaskMember< Kokkos::Threads , void , void >::latch_add( const int k )
+{
+  typedef TaskMember< Kokkos::Threads , void , void > task_root_type ;
+
+  task_root_type * const q_denied = reinterpret_cast<task_root_type*>(QDENIED);
+  
+  const bool ok_input = 0 < k ;
+  
+  const int count = ok_input ? atomic_fetch_add( & m_dep_size , -k ) - k
+                             : k ;
+                           
+  const bool ok_count = 0 <= count ;
+  
+  const int state = 0 != count ? TASK_STATE_WAITING :
+    atomic_compare_exchange( & m_state
+                           , TASK_STATE_WAITING
+                           , TASK_STATE_COMPLETE );
+          
+  const bool ok_state = state == TASK_STATE_WAITING ;
+            
+  if ( ! ok_count || ! ok_state ) {
+    printf( "ThreadsTaskPolicyQueue::latch_add[0x%lx](%d) ERROR %s %d\n"
+          , (unsigned long) this
+          , k
+          , ( ! ok_input ? "Non-positive input" :
+            ( ! ok_count ? "Negative count" : "Bad State" ) )
+          , ( ! ok_input ? k :
+            ( ! ok_count ? count : state ) )
+          );
+    Kokkos::abort( "ThreadsTaskPolicyQueue::latch_add ERROR" );
+  } 
+  else if ( 0 == count ) {
+    // Stop other tasks from adding themselves to this latch's wait queue.
+    // The wait queue is updated concurrently so guard with an atomic.
+      
+    ThreadsTaskPolicyQueue & policy = *m_policy ; 
+    task_root_type * wait_queue     = *((task_root_type * volatile *) &m_wait);
+    task_root_type * wait_queue_old = 0 ;
+
+    do {
+      wait_queue_old = wait_queue ;
+      wait_queue     = atomic_compare_exchange( & m_wait , wait_queue_old , q_denied );
+    } while ( wait_queue_old != wait_queue );
+    
+    // Pop waiting tasks and schedule them
+    while ( wait_queue ) {
+      task_root_type * const x = wait_queue ; wait_queue = x->m_next ; x->m_next = 0 ;
+      policy.schedule_task( x , false /* not initial spawn */ );
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+
+void ThreadsTaskPolicyQueue::deallocate_task( void * ptr , unsigned size_alloc )
+{
+/*
+  const int n = atomic_fetch_add( & alloc_count , -1 ) - 1 ;
+
+  fprintf( stderr
+         , "ThreadsTaskPolicyQueue::deallocate_task(0x%lx,%d) count(%d)\n"
+         , (unsigned long) ptr
+         , size_alloc
+         , n
+         );
+  fflush( stderr );
+*/
+
+  m_space.deallocate( ptr , size_alloc );
+
+  Kokkos::atomic_decrement( & m_count_alloc );
+}
+
+ThreadsTaskPolicyQueue::task_root_type *
+ThreadsTaskPolicyQueue::allocate_task
+  ( const unsigned arg_sizeof_task
+  , const unsigned arg_dep_capacity
+  , const unsigned arg_team_shmem
+  )
+{ 
+  const unsigned base_size = arg_sizeof_task +
+    ( arg_sizeof_task % sizeof(task_root_type*)
+    ? sizeof(task_root_type*) - arg_sizeof_task % sizeof(task_root_type*)
+    : 0 );
+    
+  const unsigned dep_capacity
+    = ~0u == arg_dep_capacity
+    ? m_default_dependence_capacity
+    : arg_dep_capacity ;
+
+  const unsigned size_alloc =
+     base_size + sizeof(task_root_type*) * dep_capacity ;
+
+#if 0
+  // User created task memory pool with an estimate,
+  // if estimate is to low then report and throw exception.
+
+  if ( m_space.get_min_block_size() < size_alloc ) {
+    fprintf(stderr,"TaskPolicy<Threads> task allocation requires %d bytes on memory pool with %d byte chunk size\n"
+           , int(size_alloc)
+           , int(m_space.get_min_block_size())
+           );
+    fflush(stderr);
+    Kokkos::Impl::throw_runtime_exception("TaskMember< Threads >::task_allocate");
+  }
+#endif
+
+  task_root_type * const task =
+    reinterpret_cast<task_root_type*>( m_space.allocate( size_alloc ) );
+      
+  if ( task != 0 ) {
+        
+    // Initialize task's root and value data structure
+    // Calling function must copy construct the functor.
+        
+    new( (void*) task ) task_root_type();
+  
+    task->m_policy       = this ;
+    task->m_size_alloc   = size_alloc ;
+    task->m_dep_capacity = dep_capacity ;
+    task->m_shmem_size   = arg_team_shmem ;
+
+    if ( dep_capacity ) {
+      task->m_dep =
+        reinterpret_cast<task_root_type**>(
+        reinterpret_cast<unsigned char*>(task) + base_size );
+
+      for ( unsigned i = 0 ; i < dep_capacity ; ++i )
+        task->task_root_type::m_dep[i] = 0 ;
+    }
+
+    Kokkos::atomic_increment( & m_count_alloc );
+  }
+  return  task ;
+}
+
+
+//----------------------------------------------------------------------------
+
+void ThreadsTaskPolicyQueue::add_dependence
+  ( ThreadsTaskPolicyQueue::task_root_type * const after
+  , ThreadsTaskPolicyQueue::task_root_type * const before
+  )
+{
+  if ( ( after != 0 ) && ( before != 0 ) ) {
+
+    int const state = *((volatile const int *) & after->m_state );
+
+    // Only add dependence during construction or during execution.
+    // Both tasks must have the same policy.
+    // Dependence on non-full memory cannot be mixed with any other dependence.
+
+    const bool ok_state =
+      Kokkos::Experimental::TASK_STATE_CONSTRUCTING == state ||
+      Kokkos::Experimental::TASK_STATE_EXECUTING    == state ;
+
+    const bool ok_capacity =
+      after->m_dep_size < after->m_dep_capacity ;
+
+    const bool ok_policy =
+      after->m_policy == this && before->m_policy == this ;
+
+    if ( ok_state && ok_capacity && ok_policy ) {
+
+      ++after->m_dep_size ;
+
+      task_root_type::assign( after->m_dep + (after->m_dep_size-1) , before );
+
+      memory_fence();
+    }
+    else {
+
+fprintf( stderr
+       , "ThreadsTaskPolicyQueue::add_dependence( 0x%lx , 0x%lx ) ERROR %s\n"
+       , (unsigned long) after
+       , (unsigned long) before
+       , ( ! ok_state    ? "Task not constructing or executing" :
+         ( ! ok_capacity ? "Task Exceeded dependence capacity" 
+                         : "Tasks from different policies" 
+         )) );
+
+fflush( stderr );
+
+      Kokkos::abort("ThreadsTaskPolicyQueue::add_dependence ERROR");
+    }
+  }
+}
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+TaskPolicy< Kokkos::Threads >::TaskPolicy
+  ( const unsigned arg_task_max_count
+  , const unsigned arg_task_max_size // Application's task size
+  , const unsigned arg_task_default_dependence_capacity
+  , const unsigned arg_task_team_size
+  )
+  : m_track()
+  , m_policy(0)
+{
+  typedef Kokkos::Experimental::Impl::SharedAllocationRecord
+    < Kokkos::HostSpace , Impl::ThreadsTaskPolicyQueue::Destroy > record_type ;
+
+  record_type * record =
+    record_type::allocate( Kokkos::HostSpace()
+                         , "Threads task queue"
+                         , sizeof(Impl::ThreadsTaskPolicyQueue)
+                         );
+
+  m_policy =
+    reinterpret_cast< Impl::ThreadsTaskPolicyQueue * >( record->data() );
+
+  // Tasks are allocated with application's task size + sizeof(task_root_type)
+
+  const size_t full_task_size_estimate =
+    arg_task_max_size +
+    sizeof(task_root_type) +
+    sizeof(task_root_type*) * arg_task_default_dependence_capacity ;
+
+  new( m_policy )
+    Impl::ThreadsTaskPolicyQueue( arg_task_max_count
+                                , full_task_size_estimate
+                                , arg_task_default_dependence_capacity
+                                , arg_task_team_size );
+
+  record->m_destroy.m_policy = m_policy ;
+
+  m_track.assign_allocated_record_to_uninitialized( record );
+}
+
+
+TaskPolicy< Kokkos::Threads >::member_type &
+TaskPolicy< Kokkos::Threads >::member_single()
+{
+  static member_type s ;
+  return s ;
+}
+
+void wait( Kokkos::Experimental::TaskPolicy< Kokkos::Threads > & policy )
+{
+  typedef Kokkos::Impl::ThreadsExecTeamMember member_type ;
+
+  enum { BASE_SHMEM = 1024 };
+
+  Kokkos::Impl::ThreadsExec::resize_scratch( 0 , member_type::team_reduce_size() + BASE_SHMEM );
+
+  Kokkos::Impl::ThreadsExec::start( & Impl::ThreadsTaskPolicyQueue::driver
+                                  , policy.m_policy );
+
+  Kokkos::Impl::ThreadsExec::fence();
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+typedef TaskMember< Kokkos::Threads , void , void > Task ;
+
+//----------------------------------------------------------------------------
+
+Task::~TaskMember()
+{
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+
+void Task::assign( Task ** const lhs_ptr , Task * rhs )
+{
+  Task * const q_denied = reinterpret_cast<Task*>(QDENIED);
+
+  // Increment rhs reference count.
+  if ( rhs ) { atomic_fetch_add( & rhs->m_ref_count , 1 ); }
+
+  if ( 0 == lhs_ptr ) return ;
+
+  // Must have exclusive access to *lhs_ptr.
+  // Assign the pointer and retrieve the previous value.
+
+#if 1
+
+  Task * const old_lhs = *lhs_ptr ;
+
+  *lhs_ptr = rhs ;
+
+#elif 0
+
+  Task * const old_lhs = *((Task*volatile*)lhs_ptr);
+
+  *((Task*volatile*)lhs_ptr) = rhs ;
+
+  Kokkos::memory_fence();
+
+#else
+
+  Task * const old_lhs = atomic_exchange( lhs_ptr , rhs );
+
+#endif
+
+  if ( old_lhs && rhs && old_lhs->m_policy != rhs->m_policy ) {
+    Kokkos::abort( "Kokkos::Impl::TaskMember<Kokkos::Threads>::assign ERROR different queues");
+  }
+
+  if ( old_lhs ) {
+
+    // Decrement former lhs reference count.
+    // If reference count is zero task must be complete, then delete task.
+    // Task is ready for deletion when  wait == q_denied
+    int const count = atomic_fetch_add( & (old_lhs->m_ref_count) , -1 ) - 1 ;
+    int const state = old_lhs->m_state ;
+    Task * const wait = *((Task * const volatile *) & old_lhs->m_wait );
+
+    const bool ok_count = 0 <= count ;
+
+    // If count == 0 then will be deleting
+    // and must either be constructing or complete.
+    const bool ok_state = 0 < count ? true :
+      ( ( state == int(TASK_STATE_CONSTRUCTING) && wait == 0 ) ||
+        ( state == int(TASK_STATE_COMPLETE)     && wait == q_denied ) )
+      &&
+     old_lhs->m_next == 0 &&
+     old_lhs->m_dep_size == 0 ;
+
+    if ( ! ok_count || ! ok_state ) {
+
+      fprintf( stderr , "Kokkos::Impl::TaskManager<Kokkos::Threads>::assign ERROR deleting task(0x%lx) m_ref_count(%d) , m_wait(0x%ld)\n"
+                      , (unsigned long) old_lhs
+                      , count
+                      , (unsigned long) wait );
+      fflush(stderr);
+      Kokkos::abort( "Kokkos::Impl::TaskMember<Kokkos::Threads>::assign ERROR deleting");
+    }
+
+    if ( count == 0 ) {
+      // When 'count == 0' this thread has exclusive access to 'old_lhs'
+
+      ThreadsTaskPolicyQueue & queue = *( old_lhs->m_policy );
+
+      queue.deallocate_task( old_lhs , old_lhs->m_size_alloc );
+    }
+  }
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+
+Task * Task::get_dependence( int i ) const
+{
+  Task * const t = m_dep[i] ;
+
+  if ( Kokkos::Experimental::TASK_STATE_EXECUTING != m_state || i < 0 || m_dep_size <= i || 0 == t ) {
+
+fprintf( stderr
+       , "TaskMember< Threads >::get_dependence ERROR : task[%lx]{ state(%d) dep_size(%d) dep[%d] = %lx }\n"
+       , (unsigned long) this
+       , m_state
+       , m_dep_size
+       , i
+       , (unsigned long) t
+       );
+fflush( stderr );
+
+    Kokkos::Impl::throw_runtime_exception("TaskMember< Threads >::get_dependence ERROR");
+  }
+
+  return t ;
+}
+
+//----------------------------------------------------------------------------
+
+void Task::clear_dependence()
+{
+  for ( int i = m_dep_size - 1 ; 0 <= i ; --i ) {
+    assign( m_dep + i , 0 );
+  }
+
+  *((volatile int *) & m_dep_size ) = 0 ;
+
+  memory_fence();
+}
+
+//----------------------------------------------------------------------------
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+#endif /* #if defined( KOKKOS_HAVE_PTHREAD ) && defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
diff --git a/lib/kokkos/core/src/Threads/Kokkos_Threads_TaskPolicy.hpp b/lib/kokkos/core/src/Threads/Kokkos_Threads_TaskPolicy.hpp
new file mode 100644
index 0000000000..116d32e4fc
--- /dev/null
+++ b/lib/kokkos/core/src/Threads/Kokkos_Threads_TaskPolicy.hpp
@@ -0,0 +1,745 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#ifndef KOKKOS_THREADS_TASKPOLICY_HPP
+#define KOKKOS_THREADS_TASKPOLICY_HPP
+
+
+#include <Kokkos_Threads.hpp>
+#include <Kokkos_TaskPolicy.hpp>
+
+#if defined( KOKKOS_HAVE_PTHREAD ) && defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+struct ThreadsTaskPolicyQueue ;
+
+/** \brief  Base class for all Kokkos::Threads tasks */
+template<>
+class TaskMember< Kokkos::Threads , void , void > {
+public:
+
+  template < class > friend class Kokkos::Experimental::TaskPolicy ;
+  friend struct ThreadsTaskPolicyQueue ;
+
+  typedef TaskMember * (* function_verify_type) ( TaskMember * );
+  typedef void         (* function_single_type) ( TaskMember * );
+  typedef void         (* function_team_type)   ( TaskMember * , Kokkos::Impl::ThreadsExecTeamMember & );
+
+private:
+
+
+  ThreadsTaskPolicyQueue * m_policy ;
+  TaskMember * volatile  * m_queue ;
+  function_verify_type     m_verify ;
+  function_team_type       m_team ;         ///< Apply function
+  function_single_type     m_serial ;       ///< Apply function
+  TaskMember **            m_dep ;          ///< Dependences
+  TaskMember *             m_wait ;         ///< Head of linked list of tasks waiting on this task
+  TaskMember *             m_next ;         ///< Member of linked list of tasks
+  int                      m_dep_capacity ; ///< Capacity of dependences
+  int                      m_dep_size ;     ///< Actual count of dependences
+  int                      m_size_alloc ;
+  int                      m_shmem_size ;
+  int                      m_ref_count ;    ///< Reference count
+  int                      m_state ;        ///< State of the task
+
+
+  TaskMember( TaskMember && ) = delete ;
+  TaskMember( const TaskMember & ) = delete ;
+  TaskMember & operator = ( TaskMember && ) = delete ;
+  TaskMember & operator = ( const TaskMember & ) = delete ;
+
+protected:
+
+  TaskMember()
+    : m_policy(0)
+    , m_verify(0)
+    , m_team(0)
+    , m_serial(0)
+    , m_dep(0)
+    , m_wait(0)
+    , m_next(0)
+    , m_dep_capacity(0)
+    , m_dep_size(0)
+    , m_size_alloc(0)
+    , m_shmem_size(0)
+    , m_ref_count(0)
+    , m_state( TASK_STATE_CONSTRUCTING )
+    {}
+
+public:
+
+  ~TaskMember();
+
+  KOKKOS_INLINE_FUNCTION
+  int reference_count() const
+    { return *((volatile int *) & m_ref_count ); }
+
+  template< typename ResultType >
+  KOKKOS_FUNCTION static
+  TaskMember * verify_type( TaskMember * t )
+    {
+      enum { check_type = ! std::is_same< ResultType , void >::value };
+
+      if ( check_type && t != 0 ) {
+
+        // Verify that t->m_verify is this function
+        const function_verify_type self = & TaskMember::template verify_type< ResultType > ;
+
+        if ( t->m_verify != self ) {
+          t = 0 ;
+          Kokkos::abort("TaskPolicy< Threads > verify_result_type" );
+        }
+      }
+      return t ;
+    }
+
+  //----------------------------------------
+  /*  Inheritence Requirements on task types:
+   *
+   *    class TaskMember< Threads , DerivedType::value_type , FunctorType >
+   *      : public TaskMember< Threads , DerivedType::value_type , void >
+   *      , public Functor
+   *      { ... };
+   *
+   *  If value_type != void
+   *    class TaskMember< Threads , value_type , void >
+   *      : public TaskMember< Threads , void , void >
+   *
+   */
+  //----------------------------------------
+
+  template< class DerivedTaskType , class Tag >
+  KOKKOS_FUNCTION static
+  void apply_single(
+    typename std::enable_if
+      <( std::is_same<Tag,void>::value &&
+         std::is_same< typename DerivedTaskType::result_type , void >::value
+       ), TaskMember * >::type t )
+    {
+      {
+        typedef typename DerivedTaskType::functor_type  functor_type ;
+
+        functor_type * const f = 
+          static_cast< functor_type * >( static_cast< DerivedTaskType * >(t) );
+
+        f->apply();
+
+        if ( t->m_state == int(Kokkos::Experimental::TASK_STATE_EXECUTING) ) {
+          f->~functor_type();
+        }
+      }
+    }
+
+  template< class DerivedTaskType , class Tag >
+  KOKKOS_FUNCTION static
+  void apply_single(
+    typename std::enable_if
+      <( std::is_same< Tag , void >::value &&
+         ! std::is_same< typename DerivedTaskType::result_type , void >::value
+       ), TaskMember * >::type t )
+    {
+      {
+        typedef typename DerivedTaskType::functor_type  functor_type ;
+
+        DerivedTaskType * const self = static_cast< DerivedTaskType * >(t);
+        functor_type    * const f    = static_cast< functor_type * >( self );
+
+        f->apply( self->m_result );
+
+        if ( t->m_state == int(Kokkos::Experimental::TASK_STATE_EXECUTING) ) {
+          f->~functor_type();
+        }
+      }
+    }
+
+  //----------------------------------------
+
+  template< class DerivedTaskType , class Tag >
+  KOKKOS_FUNCTION static
+  void apply_team(
+    typename std::enable_if
+      <( std::is_same<Tag,void>::value &&
+         std::is_same<typename DerivedTaskType::result_type,void>::value
+       ), TaskMember * >::type t
+    , Kokkos::Impl::ThreadsExecTeamMember & member
+    )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+
+      functor_type * const f =
+        static_cast< functor_type * >( static_cast< DerivedTaskType * >(t) );
+    
+      f->apply( member );
+
+      // Synchronize for possible functor destruction and
+      // completion of team task.
+      if ( member.team_fan_in() ) {
+        if ( t->m_state == int(Kokkos::Experimental::TASK_STATE_EXECUTING) ) {
+          f->~functor_type();
+        }
+      }
+    }
+
+  template< class DerivedTaskType , class Tag >
+  KOKKOS_FUNCTION static
+  void apply_team(
+    typename std::enable_if
+      <( std::is_same<Tag,void>::value &&
+         ! std::is_same<typename DerivedTaskType::result_type,void>::value
+       ), TaskMember * >::type t
+    , Kokkos::Impl::ThreadsExecTeamMember & member
+    )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+
+      DerivedTaskType * const self = static_cast< DerivedTaskType * >(t);
+      functor_type    * const f    = static_cast< functor_type * >( self );
+    
+      f->apply( member , self->m_result );
+
+      // Synchronize for possible functor destruction and
+      // completion of team task.
+      if ( member.team_fan_in() ) {
+        if ( t->m_state == int(Kokkos::Experimental::TASK_STATE_EXECUTING) ) {
+          f->~functor_type();
+        }
+      }
+    }
+
+  //----------------------------------------
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+  static
+  void assign( TaskMember ** const lhs , TaskMember * const rhs );
+#else
+  KOKKOS_INLINE_FUNCTION static
+  void assign( TaskMember ** const lhs , TaskMember * const rhs ) {}
+#endif
+
+  TaskMember * get_dependence( int i ) const ;
+
+  KOKKOS_INLINE_FUNCTION
+  int get_dependence() const { return m_dep_size ; }
+
+  void clear_dependence();
+
+  void latch_add( const int k );
+
+  //----------------------------------------
+
+  typedef FutureValueTypeIsVoidError get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const { return get_result_type() ; }
+
+  inline static
+  void construct_result( TaskMember * const ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  Kokkos::Experimental::TaskState get_state() const { return Kokkos::Experimental::TaskState( m_state ); }
+
+};
+
+/** \brief  A Future< Kokkos::Threads , ResultType > will cast
+ *          from  TaskMember< Kokkos::Threads , void , void >
+ *          to    TaskMember< Kokkos::Threads , ResultType , void >
+ *          to query the result.
+ */
+template< class ResultType >
+class TaskMember< Kokkos::Threads , ResultType , void >
+  : public TaskMember< Kokkos::Threads , void , void >
+{
+public:
+
+  typedef ResultType result_type ;
+
+  result_type  m_result ;
+
+  typedef const result_type & get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const { return m_result ; }
+
+  inline static
+  void construct_result( TaskMember * const ptr )
+    { 
+      new((void*)(& ptr->m_result)) result_type();
+    }
+
+  inline
+  TaskMember() : TaskMember< Kokkos::Threads , void , void >(), m_result() {}
+
+  TaskMember( TaskMember && ) = delete ;
+  TaskMember( const TaskMember & ) = delete ;
+  TaskMember & operator = ( TaskMember && ) = delete ;
+  TaskMember & operator = ( const TaskMember & ) = delete ;
+};
+
+/** \brief  Callback functions will cast
+ *          from  TaskMember< Kokkos::Threads , void , void >
+ *          to    TaskMember< Kokkos::Threads , ResultType , FunctorType >
+ *          to execute work functions.
+ */
+template< class ResultType , class FunctorType >
+class TaskMember< Kokkos::Threads , ResultType , FunctorType >
+  : public TaskMember< Kokkos::Threads , ResultType , void >
+  , public FunctorType
+{
+public:
+  typedef ResultType   result_type ;
+  typedef FunctorType  functor_type ;
+
+  inline
+  TaskMember( const functor_type & arg_functor )
+    : TaskMember< Kokkos::Threads , ResultType , void >()
+    , functor_type( arg_functor )
+    {}
+
+  inline static
+  void copy_construct( TaskMember * const ptr
+                     , const functor_type & arg_functor )
+    {
+      typedef TaskMember< Kokkos::Threads , ResultType , void > base_type ;
+
+      new((void*)static_cast<FunctorType*>(ptr)) functor_type( arg_functor );
+
+      base_type::construct_result( static_cast<base_type*>( ptr ) );
+    }
+
+  TaskMember() = delete ;
+  TaskMember( TaskMember && ) = delete ;
+  TaskMember( const TaskMember & ) = delete ;
+  TaskMember & operator = ( TaskMember && ) = delete ;
+  TaskMember & operator = ( const TaskMember & ) = delete ;
+};
+
+//----------------------------------------------------------------------------
+
+struct ThreadsTaskPolicyQueue {
+
+  enum { NPRIORITY = 3 };
+
+  typedef Kokkos::Experimental::MemoryPool< Kokkos::Threads >
+    memory_space ;
+
+  typedef Kokkos::Experimental::Impl::TaskMember< Kokkos::Threads, void, void >
+    task_root_type ;
+
+  memory_space     m_space ;
+  task_root_type * m_team[ NPRIORITY ];
+  task_root_type * m_serial[ NPRIORITY ];
+  int              m_team_size ;    ///< Fixed size of a task-team
+  int              m_default_dependence_capacity ;
+  int     volatile m_count_ready ;  ///< Ready plus executing tasks
+  int     volatile m_count_alloc ;  ///< Total allocated tasks
+
+  // Execute tasks until all non-waiting tasks are complete.
+  static void driver( Kokkos::Impl::ThreadsExec & exec
+                    , const void * arg );
+
+  task_root_type * allocate_task
+   ( const unsigned arg_sizeof_task
+   , const unsigned arg_dep_capacity
+   , const unsigned arg_team_shmem
+   );
+
+  void deallocate_task( void * , unsigned );
+  void schedule_task( task_root_type * const
+                    , const bool initial_spawn = true );
+  void reschedule_task( task_root_type * const );
+  void add_dependence( task_root_type * const after
+                     , task_root_type * const before );
+
+  // When a task finishes executing update its dependences
+  // and either deallocate the task if complete
+  // or reschedule the task if respawned.
+  void complete_executed_task( task_root_type * );
+
+  // Pop a task from a ready queue
+  static task_root_type *
+    pop_ready_task( task_root_type * volatile * const queue );
+
+  ThreadsTaskPolicyQueue() = delete ;
+  ThreadsTaskPolicyQueue( ThreadsTaskPolicyQueue && ) = delete ;
+  ThreadsTaskPolicyQueue( const ThreadsTaskPolicyQueue & ) = delete ;
+  ThreadsTaskPolicyQueue & operator = ( ThreadsTaskPolicyQueue && ) = delete ;
+  ThreadsTaskPolicyQueue & operator = ( const ThreadsTaskPolicyQueue & ) = delete ;
+
+  ~ThreadsTaskPolicyQueue();
+
+  ThreadsTaskPolicyQueue
+    ( const unsigned arg_task_max_count
+    , const unsigned arg_task_max_size
+    , const unsigned arg_task_default_dependence_capacity
+    , const unsigned arg_task_team_size
+    );
+
+  // Callback to destroy the shared memory tracked queue.
+  struct Destroy {
+    ThreadsTaskPolicyQueue * m_policy ;
+    void destroy_shared_allocation();
+  };
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+void wait( TaskPolicy< Kokkos::Threads > & );
+
+template<>
+class TaskPolicy< Kokkos::Threads >
+{
+public:
+
+  typedef Kokkos::Threads                      execution_space ;
+  typedef TaskPolicy                           execution_policy ;
+  typedef Kokkos::Impl::ThreadsExecTeamMember  member_type ;
+
+private:
+
+  typedef Impl::TaskMember< Kokkos::Threads , void , void >  task_root_type ;
+  typedef Kokkos::Experimental::MemoryPool< Kokkos::Threads > memory_space ;
+
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker track_type ;
+
+  track_type                      m_track ;
+  Impl::ThreadsTaskPolicyQueue  * m_policy ;
+
+  template< class FunctorType >
+  static inline
+  const task_root_type * get_task_root( const FunctorType * f )
+    {
+      typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
+      return static_cast< const task_root_type * >( static_cast< const task_type * >(f) );
+    }
+
+  template< class FunctorType >
+  static inline
+  task_root_type * get_task_root( FunctorType * f )
+    {
+      typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
+      return static_cast< task_root_type * >( static_cast< task_type * >(f) );
+    }
+
+  /** \brief  Allocate and construct a task.
+   *
+   *  Allocate space for DerivedTaskType followed by TaskMember*[ dependence_capacity ]
+   */
+  template< class DerivedTaskType , class Tag >
+  task_root_type *
+  create( const typename DerivedTaskType::functor_type &  arg_functor
+        , const task_root_type::function_single_type      arg_apply_single
+        , const task_root_type::function_team_type        arg_apply_team
+        , const unsigned                                  arg_team_shmem
+        , const unsigned                                  arg_dependence_capacity
+        )
+    {
+      task_root_type * const t =
+        m_policy->allocate_task( sizeof(DerivedTaskType)
+                               , arg_dependence_capacity
+                               , arg_team_shmem
+                               );
+      if ( t != 0 ) {
+
+        DerivedTaskType * const task = static_cast<DerivedTaskType*>(t);
+
+        DerivedTaskType::copy_construct( task , arg_functor );
+
+        task->task_root_type::m_verify  = & task_root_type::template verify_type< typename DerivedTaskType::value_type > ;
+        task->task_root_type::m_team    = arg_apply_team ;
+        task->task_root_type::m_serial  = arg_apply_single ;
+
+        // Do not proceed until initialization is written to memory
+        Kokkos::memory_fence();
+      }
+      return t ;
+    }
+
+public:
+
+  // Valid team sizes are 1,
+  // Threads::pool_size(1) == threads per numa, or
+  // Threads::pool_size(2) == threads per core
+
+  TaskPolicy
+    ( const unsigned arg_task_max_count
+    , const unsigned arg_task_max_size
+    , const unsigned arg_task_default_dependence_capacity = 4
+    , const unsigned arg_task_team_size = 0 /* choose default */
+    );
+
+  KOKKOS_FUNCTION TaskPolicy() = default ;
+  KOKKOS_FUNCTION TaskPolicy( TaskPolicy && rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy( const TaskPolicy & rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy & operator = ( TaskPolicy && rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy & operator = ( const TaskPolicy & rhs ) = default ;
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  int allocated_task_count() const { return m_policy->m_count_alloc ; }
+
+  //----------------------------------------
+  // Create serial-thread task
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  task_create( const FunctorType & functor
+             , const unsigned dependence_capacity = ~0u )
+    {
+      typedef typename FunctorType::value_type  value_type ;
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >  task_type ;
+
+      return Future< value_type , execution_space >(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        TaskPolicy::create< task_type , void >
+          ( functor
+          , & task_root_type::template apply_single< task_type , void >
+          , task_root_type::function_team_type(0)
+          , 0
+          , dependence_capacity
+          )
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  proc_create( const FunctorType & functor
+             , const unsigned dependence_capacity = ~0u )
+    { return task_create( functor , dependence_capacity ); }
+
+  // Create thread-team task
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  task_create_team( const FunctorType & functor
+                  , const unsigned dependence_capacity = ~0u )
+    {
+      typedef typename FunctorType::value_type  value_type ;
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >  task_type ;
+
+      return Future< value_type , execution_space >(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        TaskPolicy::create< task_type , void >
+          ( functor
+          , task_root_type::function_single_type(0)
+          , & task_root_type::template apply_team< task_type , void >
+          , Kokkos::Impl::FunctorTeamShmemSize< FunctorType >::
+              value( functor , m_policy->m_team_size )
+          , dependence_capacity
+          )
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  proc_create_team( const FunctorType & functor
+                  , const unsigned dependence_capacity = ~0u )
+    { return task_create_team( functor , dependence_capacity ); }
+
+  template< class A1 , class A2 , class A3 , class A4 >
+  KOKKOS_INLINE_FUNCTION
+  void add_dependence( const Future<A1,A2> & after
+                     , const Future<A3,A4> & before
+                     , typename std::enable_if
+                        < std::is_same< typename Future<A1,A2>::execution_space , execution_space >::value
+                          &&
+                          std::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
+                        >::type * = 0
+                      ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      m_policy->add_dependence( after.m_task , before.m_task );
+#endif
+    }
+
+  //----------------------------------------
+
+  Future< Latch , execution_space >
+  KOKKOS_INLINE_FUNCTION
+  create_latch( const int N ) const
+    {
+      task_root_type * const task =
+        m_policy->allocate_task( sizeof(task_root_type) , 0 , 0 );
+      task->m_dep_size = N ; // Using m_dep_size for latch counter
+      task->m_state = TASK_STATE_WAITING ;
+      return Future< Latch , execution_space >( task );
+    }
+
+  //----------------------------------------
+
+  template< class FunctorType , class A3 , class A4 >
+  KOKKOS_INLINE_FUNCTION
+  void add_dependence( FunctorType * task_functor
+                     , const Future<A3,A4> & before
+                     , typename std::enable_if
+                        < std::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
+                        >::type * = 0
+                      ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      m_policy->add_dependence( get_task_root(task_functor) , before.m_task );
+#endif
+    }
+
+  template< class ValueType >
+  const Future< ValueType , execution_space > &
+    spawn( const Future< ValueType , execution_space > & f
+         , const bool priority = false ) const
+      {
+        if ( f.m_task ) {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+          f.m_task->m_queue =
+            ( f.m_task->m_team != 0
+            ? & ( m_policy->m_team[   priority ? 0 : 1 ] )
+            : & ( m_policy->m_serial[ priority ? 0 : 1 ] ) );
+          m_policy->schedule_task( f.m_task );
+#endif
+        }
+        return f ;
+      }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void respawn( FunctorType * task_functor 
+              , const bool priority = false ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      task_root_type * const t = get_task_root(task_functor);
+      t->m_queue =
+        ( t->m_team != 0 ? & ( m_policy->m_team[   priority ? 0 : 1 ] )
+                         : & ( m_policy->m_serial[ priority ? 0 : 1 ] ) );
+      m_policy->reschedule_task( t );
+#endif
+    }
+
+  // When a create method fails by returning a null Future
+  // the task that called the create method may respawn
+  // with a dependence on memory becoming available.
+  // This is a race as more than one task may be respawned
+  // with this need.
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void respawn_needing_memory( FunctorType * task_functor ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      task_root_type * const t = get_task_root(task_functor);
+      t->m_queue =
+        ( t->m_team != 0 ? & ( m_policy->m_team[   2 ] )
+                         : & ( m_policy->m_serial[ 2 ] ) );
+      m_policy->reschedule_task( t );
+#endif
+    }
+
+  //----------------------------------------
+  // Functions for an executing task functor to query dependences,
+  // set new dependences, and respawn itself.
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< void , execution_space >
+  get_dependence( const FunctorType * task_functor , int i ) const
+    {
+      return Future<void,execution_space>(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        get_task_root(task_functor)->get_dependence(i)
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  int get_dependence( const FunctorType * task_functor ) const
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return get_task_root(task_functor)->get_dependence(); }
+#else
+    { return 0 ; }
+#endif
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void clear_dependence( FunctorType * task_functor ) const
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { get_task_root(task_functor)->clear_dependence(); }
+#else
+    {}
+#endif
+
+  //----------------------------------------
+
+  static member_type & member_single();
+
+  friend void wait( TaskPolicy< Kokkos::Threads > & );
+};
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_HAVE_PTHREAD ) && defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #ifndef KOKKOS_THREADS_TASKPOLICY_HPP */
+
+
diff --git a/lib/kokkos/core/src/impl/CMakeLists.txt b/lib/kokkos/core/src/impl/CMakeLists.txt
new file mode 100644
index 0000000000..c543194de3
--- /dev/null
+++ b/lib/kokkos/core/src/impl/CMakeLists.txt
@@ -0,0 +1,18 @@
+
+SET(HEADERS "")
+SET(SOURCES "")
+
+FILE(GLOB HEADERS *.hpp)
+FILE(GLOB SOURCES *.cpp)
+
+TRIBITS_ADD_LIBRARY(
+    kokkoscore_impl
+    NOINSTALLHEADERS ${HEADERS}
+    SOURCES ${SOURCES}
+    DEPLIBS 
+    )
+
+SET(TRILINOS_INCDIR ${CMAKE_INSTALL_PREFIX}/${${PROJECT_NAME}_INSTALL_INCLUDE_DIR})
+
+INSTALL(FILES ${HEADERS} DESTINATION ${TRILINOS_INCDIR}/impl/)
+
diff --git a/lib/kokkos/core/src/impl/KokkosExp_SharedAlloc.cpp b/lib/kokkos/core/src/impl/KokkosExp_SharedAlloc.cpp
new file mode 100644
index 0000000000..96b3704345
--- /dev/null
+++ b/lib/kokkos/core/src/impl/KokkosExp_SharedAlloc.cpp
@@ -0,0 +1,346 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+int SharedAllocationRecord< void , void >::s_tracking_enabled = 1 ;
+
+void SharedAllocationRecord< void , void >::tracking_claim_and_disable()
+{
+  // A host thread claim and disable tracking flag
+
+  while ( ! Kokkos::atomic_compare_exchange_strong( & s_tracking_enabled, 1, 0 ) );
+}
+
+void SharedAllocationRecord< void , void >::tracking_release_and_enable()
+{
+  // The host thread that claimed and disabled the tracking flag
+  // now release and enable tracking.
+
+  if ( ! Kokkos::atomic_compare_exchange_strong( & s_tracking_enabled, 0, 1 ) ){
+    Kokkos::Impl::throw_runtime_exception("Kokkos::Experimental::Impl::SharedAllocationRecord<>::tracking_release_and_enable FAILED, this host process thread did not hold the lock" );
+  }
+}
+
+//----------------------------------------------------------------------------
+
+bool
+SharedAllocationRecord< void , void >::
+is_sane( SharedAllocationRecord< void , void > * arg_record )
+{
+  constexpr static SharedAllocationRecord * zero = 0 ;
+
+  SharedAllocationRecord * const root = arg_record ? arg_record->m_root : 0 ;
+
+  bool ok = root != 0 && root->use_count() == 0 ;
+
+  if ( ok ) {
+    SharedAllocationRecord * root_next = 0 ;
+
+    // Lock the list:
+    while ( ( root_next = Kokkos::atomic_exchange( & root->m_next , zero ) ) == zero );
+
+    for ( SharedAllocationRecord * rec = root_next ; ok && rec != root ; rec = rec->m_next ) {
+      const bool ok_non_null  = rec && rec->m_prev && ( rec == root || rec->m_next );
+      const bool ok_root      = ok_non_null && rec->m_root == root ;
+      const bool ok_prev_next = ok_non_null && ( rec->m_prev != root ? rec->m_prev->m_next == rec : root_next == rec );
+      const bool ok_next_prev = ok_non_null && rec->m_next->m_prev == rec ;
+      const bool ok_count     = ok_non_null && 0 <= rec->use_count() ;
+
+      ok = ok_root && ok_prev_next && ok_next_prev && ok_count ;
+
+if ( ! ok ) {
+  //Formatting dependent on sizeof(uintptr_t) 
+  const char * format_string;
+  
+  if (sizeof(uintptr_t) == sizeof(unsigned long)) {
+     format_string = "Kokkos::Experimental::Impl::SharedAllocationRecord failed is_sane: rec(0x%.12lx){ m_count(%d) m_root(0x%.12lx) m_next(0x%.12lx) m_prev(0x%.12lx) m_next->m_prev(0x%.12lx) m_prev->m_next(0x%.12lx) }\n";
+  }
+  else if (sizeof(uintptr_t) == sizeof(unsigned long long)) {
+     format_string = "Kokkos::Experimental::Impl::SharedAllocationRecord failed is_sane: rec(0x%.12llx){ m_count(%d) m_root(0x%.12llx) m_next(0x%.12llx) m_prev(0x%.12llx) m_next->m_prev(0x%.12llx) m_prev->m_next(0x%.12llx) }\n";
+  }
+
+  fprintf(stderr
+        , format_string 
+        , reinterpret_cast< uintptr_t >( rec )
+        , rec->use_count()
+        , reinterpret_cast< uintptr_t >( rec->m_root )
+        , reinterpret_cast< uintptr_t >( rec->m_next )
+        , reinterpret_cast< uintptr_t >( rec->m_prev )
+        , reinterpret_cast< uintptr_t >( rec->m_next != NULL ? rec->m_next->m_prev : NULL )
+        , reinterpret_cast< uintptr_t >( rec->m_prev != rec->m_root ? rec->m_prev->m_next : root_next )
+        );
+}
+
+    }
+
+    if ( zero != Kokkos::atomic_exchange( & root->m_next , root_next ) ) {
+      Kokkos::Impl::throw_runtime_exception("Kokkos::Experimental::Impl::SharedAllocationRecord failed is_sane unlocking");
+    }
+  }
+
+  return ok ; 
+}
+
+SharedAllocationRecord<void,void> *
+SharedAllocationRecord<void,void>::find( SharedAllocationRecord<void,void> * const arg_root , void * const arg_data_ptr )
+{
+  constexpr static SharedAllocationRecord * zero = 0 ;
+
+  SharedAllocationRecord * root_next = 0 ;
+
+  // Lock the list:
+  while ( ( root_next = Kokkos::atomic_exchange( & arg_root->m_next , zero ) ) == zero );
+
+  // Iterate searching for the record with this data pointer
+
+  SharedAllocationRecord * r = root_next ;
+
+  while ( ( r != arg_root ) && ( r->data() != arg_data_ptr ) ) { r = r->m_next ; }
+
+  if ( r == arg_root ) { r = 0 ; }
+
+  if ( zero != Kokkos::atomic_exchange( & arg_root->m_next , root_next ) ) {
+    Kokkos::Impl::throw_runtime_exception("Kokkos::Experimental::Impl::SharedAllocationRecord failed locking/unlocking");
+  }
+
+  return r ;
+}
+
+
+/**\brief  Construct and insert into 'arg_root' tracking set.
+ *         use_count is zero.
+ */
+SharedAllocationRecord< void , void >::
+SharedAllocationRecord( SharedAllocationRecord<void,void> * arg_root
+                      , SharedAllocationHeader            * arg_alloc_ptr
+                      , size_t                              arg_alloc_size
+                      , SharedAllocationRecord< void , void >::function_type  arg_dealloc
+                      )
+  : m_alloc_ptr(  arg_alloc_ptr )
+  , m_alloc_size( arg_alloc_size )
+  , m_dealloc(    arg_dealloc )
+  , m_root( arg_root )
+  , m_prev( 0 )
+  , m_next( 0 )
+  , m_count( 0 )
+{
+  constexpr static SharedAllocationRecord * zero = 0 ;
+
+  if ( 0 != arg_alloc_ptr ) {
+
+    // Insert into the root double-linked list for tracking
+    //
+    // before:  arg_root->m_next == next ; next->m_prev == arg_root
+    // after:   arg_root->m_next == this ; this->m_prev == arg_root ;
+    //              this->m_next == next ; next->m_prev == this
+
+    m_prev = m_root ;
+
+    // Read root->m_next and lock by setting to zero
+    while ( ( m_next = Kokkos::atomic_exchange( & m_root->m_next , zero ) ) == zero );
+
+    m_next->m_prev = this ;
+
+    // memory fence before completing insertion into linked list
+    Kokkos::memory_fence();
+
+    if ( zero != Kokkos::atomic_exchange( & m_root->m_next , this ) ) {
+      Kokkos::Impl::throw_runtime_exception("Kokkos::Experimental::Impl::SharedAllocationRecord failed locking/unlocking");
+    }
+  }
+  else {
+    Kokkos::Impl::throw_runtime_exception("Kokkos::Experimental::Impl::SharedAllocationRecord given NULL allocation");
+  }
+}
+
+void
+SharedAllocationRecord< void , void >::
+increment( SharedAllocationRecord< void , void > * arg_record )
+{
+  const int old_count = Kokkos::atomic_fetch_add( & arg_record->m_count , 1 );
+
+  if ( old_count < 0 ) { // Error
+    Kokkos::Impl::throw_runtime_exception("Kokkos::Experimental::Impl::SharedAllocationRecord failed increment");
+  }
+}
+
+SharedAllocationRecord< void , void > *
+SharedAllocationRecord< void , void >::
+decrement( SharedAllocationRecord< void , void > * arg_record )
+{
+  constexpr static SharedAllocationRecord * zero = 0 ;
+
+  const int old_count = Kokkos::atomic_fetch_add( & arg_record->m_count , -1 );
+
+#if 0
+  if ( old_count <= 1 ) {
+    fprintf(stderr,"Kokkos::Experimental::Impl::SharedAllocationRecord '%s' at 0x%lx delete count = %d\n", arg_record->m_alloc_ptr->m_label , (unsigned long) arg_record , old_count );
+    fflush(stderr);
+  }
+#endif
+
+
+  if ( old_count == 1 ) {
+
+    // before:  arg_record->m_prev->m_next == arg_record  &&
+    //          arg_record->m_next->m_prev == arg_record
+    //
+    // after:   arg_record->m_prev->m_next == arg_record->m_next  &&
+    //          arg_record->m_next->m_prev == arg_record->m_prev
+
+    SharedAllocationRecord * root_next = 0 ;
+
+    // Lock the list:
+    while ( ( root_next = Kokkos::atomic_exchange( & arg_record->m_root->m_next , zero ) ) == zero );
+
+    arg_record->m_next->m_prev = arg_record->m_prev ;
+
+    if ( root_next != arg_record ) {
+      arg_record->m_prev->m_next = arg_record->m_next ;
+    }
+    else {
+      // before:  arg_record->m_root == arg_record->m_prev
+      // after:   arg_record->m_root == arg_record->m_next
+      root_next = arg_record->m_next ; 
+    }
+
+    // Unlock the list:
+    if ( zero != Kokkos::atomic_exchange( & arg_record->m_root->m_next , root_next ) ) {
+      Kokkos::Impl::throw_runtime_exception("Kokkos::Experimental::Impl::SharedAllocationRecord failed decrement unlocking");
+    }
+
+    arg_record->m_next = 0 ;
+    arg_record->m_prev = 0 ;
+
+    function_type d = arg_record->m_dealloc ;
+    (*d)( arg_record );
+    arg_record = 0 ;
+  }
+  else if ( old_count < 1 ) { // Error
+    fprintf(stderr,"Kokkos::Experimental::Impl::SharedAllocationRecord '%s' failed decrement count = %d\n", arg_record->m_alloc_ptr->m_label , old_count );
+    fflush(stderr);
+    Kokkos::Impl::throw_runtime_exception("Kokkos::Experimental::Impl::SharedAllocationRecord failed decrement count");
+  }
+
+  return arg_record ;
+}
+
+void
+SharedAllocationRecord< void , void >::
+print_host_accessible_records( std::ostream & s
+                             , const char * const space_name
+                             , const SharedAllocationRecord * const root
+                             , const bool detail )
+{
+  const SharedAllocationRecord< void , void > * r = root ;
+
+  char buffer[256] ;
+
+  if ( detail ) {
+    do {
+      //Formatting dependent on sizeof(uintptr_t) 
+      const char * format_string;
+
+      if (sizeof(uintptr_t) == sizeof(unsigned long)) {
+        format_string = "%s addr( 0x%.12lx ) list( 0x%.12lx 0x%.12lx ) extent[ 0x%.12lx + %.8ld ] count(%d) dealloc(0x%.12lx) %s\n";
+      }
+      else if (sizeof(uintptr_t) == sizeof(unsigned long long)) {
+        format_string = "%s addr( 0x%.12llx ) list( 0x%.12llx 0x%.12llx ) extent[ 0x%.12llx + %.8ld ] count(%d) dealloc(0x%.12llx) %s\n";
+      }
+
+      snprintf( buffer , 256
+              , format_string
+              , space_name
+              , reinterpret_cast<uintptr_t>( r )
+              , reinterpret_cast<uintptr_t>( r->m_prev )
+              , reinterpret_cast<uintptr_t>( r->m_next )
+              , reinterpret_cast<uintptr_t>( r->m_alloc_ptr )
+              , r->m_alloc_size
+              , r->use_count()
+              , reinterpret_cast<uintptr_t>( r->m_dealloc )
+              , r->m_alloc_ptr->m_label
+              );
+      std::cout << buffer ;
+      r = r->m_next ;
+    } while ( r != root );
+  }
+  else {
+    do {
+      if ( r->m_alloc_ptr ) {
+        //Formatting dependent on sizeof(uintptr_t) 
+        const char * format_string;
+
+        if (sizeof(uintptr_t) == sizeof(unsigned long)) { 
+          format_string = "%s [ 0x%.12lx + %ld ] %s\n";
+        }
+        else if (sizeof(uintptr_t) == sizeof(unsigned long long)) { 
+          format_string = "%s [ 0x%.12llx + %ld ] %s\n";
+        }
+
+        snprintf( buffer , 256
+                , format_string
+                , space_name
+                , reinterpret_cast< uintptr_t >( r->data() )
+                , r->size()
+                , r->m_alloc_ptr->m_label
+                );
+      }
+      else {
+        snprintf( buffer , 256 , "%s [ 0 + 0 ]\n" , space_name );
+      }
+      std::cout << buffer ;
+      r = r->m_next ;
+    } while ( r != root );
+  }
+}
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+
diff --git a/lib/kokkos/core/src/impl/KokkosExp_SharedAlloc.hpp b/lib/kokkos/core/src/impl/KokkosExp_SharedAlloc.hpp
new file mode 100644
index 0000000000..1498eafb00
--- /dev/null
+++ b/lib/kokkos/core/src/impl/KokkosExp_SharedAlloc.hpp
@@ -0,0 +1,400 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_SHARED_ALLOC_HPP_
+#define KOKKOS_SHARED_ALLOC_HPP_
+
+#include <stdint.h>
+#include <string>
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template< class MemorySpace = void , class DestroyFunctor = void >
+class SharedAllocationRecord ;
+
+class SharedAllocationHeader {
+private:
+
+  typedef SharedAllocationRecord<void,void>  Record ;
+
+  static constexpr unsigned maximum_label_length = ( 1u << 7 /* 128 */ ) - sizeof(Record*);
+
+  template< class , class > friend class SharedAllocationRecord ;
+
+  Record * m_record ;
+  char     m_label[ maximum_label_length ];
+
+public:
+
+  /* Given user memory get pointer to the header */
+  KOKKOS_INLINE_FUNCTION static
+  const SharedAllocationHeader * get_header( void * alloc_ptr )
+    { return reinterpret_cast<SharedAllocationHeader*>( reinterpret_cast<char*>(alloc_ptr) - sizeof(SharedAllocationHeader) ); }
+};
+
+template<>
+class SharedAllocationRecord< void , void > {
+protected:
+
+  static_assert( sizeof(SharedAllocationHeader) == ( 1u << 7 /* 128 */ ) , "sizeof(SharedAllocationHeader) != 128" );
+
+  template< class , class > friend class SharedAllocationRecord ;
+
+  typedef void (* function_type )( SharedAllocationRecord<void,void> * );
+
+  static int s_tracking_enabled ;
+
+  SharedAllocationHeader * const m_alloc_ptr ;
+  size_t                   const m_alloc_size ;
+  function_type            const m_dealloc ;
+  SharedAllocationRecord * const m_root ;
+  SharedAllocationRecord *       m_prev ;
+  SharedAllocationRecord *       m_next ;
+  int                            m_count ;
+
+  SharedAllocationRecord( SharedAllocationRecord && ) = delete ;
+  SharedAllocationRecord( const SharedAllocationRecord & ) = delete ;
+  SharedAllocationRecord & operator = ( SharedAllocationRecord && ) = delete ;
+  SharedAllocationRecord & operator = ( const SharedAllocationRecord & ) = delete ;
+
+  /**\brief  Construct and insert into 'arg_root' tracking set.
+   *         use_count is zero.
+   */
+  SharedAllocationRecord( SharedAllocationRecord * arg_root
+                        , SharedAllocationHeader * arg_alloc_ptr
+                        , size_t                   arg_alloc_size
+                        , function_type            arg_dealloc
+                        );
+
+public:
+
+  static int tracking_enabled() { return s_tracking_enabled ; }
+
+  /**\brief A host process thread claims and disables the 
+   *        shared allocation tracking flag.
+   */
+  static void tracking_claim_and_disable();
+
+  /**\brief A host process thread releases and enables the 
+   *        shared allocation tracking flag.
+   */
+  static void tracking_release_and_enable();
+
+  ~SharedAllocationRecord() = default ;
+
+  SharedAllocationRecord()
+    : m_alloc_ptr( 0 )
+    , m_alloc_size( 0 )
+    , m_dealloc( 0 )
+    , m_root( this )
+    , m_prev( this )
+    , m_next( this )
+    , m_count( 0 )
+    {}
+
+  static constexpr unsigned maximum_label_length = SharedAllocationHeader::maximum_label_length ;
+
+  KOKKOS_INLINE_FUNCTION
+  const SharedAllocationHeader * head() const { return m_alloc_ptr ; }
+
+  /* User's memory begins at the end of the header */
+  KOKKOS_INLINE_FUNCTION
+  void * data() const { return reinterpret_cast<void*>( m_alloc_ptr + 1 ); }
+
+  /* User's memory begins at the end of the header */
+  size_t size() const { return m_alloc_size - sizeof(SharedAllocationHeader) ; }
+
+  /* Cannot be 'constexpr' because 'm_count' is volatile */
+  int use_count() const { return *static_cast<const volatile int *>(&m_count); }
+
+  /* Increment use count */
+  static void increment( SharedAllocationRecord * );
+
+  /* Decrement use count. If 1->0 then remove from the tracking list and invoke m_dealloc */
+  static SharedAllocationRecord * decrement( SharedAllocationRecord * );
+
+  /* Given a root record and data pointer find the record */
+  static SharedAllocationRecord * find( SharedAllocationRecord * const , void * const );
+
+  /*  Sanity check for the whole set of records to which the input record belongs.
+   *  Locks the set's insert/erase operations until the sanity check is complete.
+   */
+  static bool is_sane( SharedAllocationRecord * );
+
+  /*  Print host-accessible records */
+  static void print_host_accessible_records( std::ostream &
+                                           , const char * const space_name
+                                           , const SharedAllocationRecord * const root
+                                           , const bool detail );
+};
+
+namespace {
+
+/* Taking the address of this function so make sure it is unique */
+template < class MemorySpace , class DestroyFunctor >
+void deallocate( SharedAllocationRecord<void,void> * record_ptr )
+{
+  typedef SharedAllocationRecord< MemorySpace , void > base_type ;
+  typedef SharedAllocationRecord< MemorySpace , DestroyFunctor > this_type ;
+
+  this_type * const ptr = static_cast< this_type * >(
+                          static_cast< base_type * >( record_ptr ) );
+
+  ptr->m_destroy.destroy_shared_allocation();
+
+  delete ptr ;
+}
+
+}
+
+/*
+ *  Memory space specialization of SharedAllocationRecord< Space , void > requires :
+ *
+ *  SharedAllocationRecord< Space , void > : public SharedAllocationRecord< void , void >
+ *  {
+ *    // delete allocated user memory via static_cast to this type.
+ *    static void deallocate( const SharedAllocationRecord<void,void> * );
+ *    Space m_space ;
+ *  }
+ */
+template< class MemorySpace , class DestroyFunctor >
+class SharedAllocationRecord : public SharedAllocationRecord< MemorySpace , void >
+{
+private:
+
+  SharedAllocationRecord( const MemorySpace & arg_space
+                        , const std::string & arg_label
+                        , const size_t        arg_alloc
+                        )
+    /*  Allocate user memory as [ SharedAllocationHeader , user_memory ] */
+    : SharedAllocationRecord< MemorySpace , void >( arg_space , arg_label , arg_alloc , & Kokkos::Experimental::Impl::deallocate< MemorySpace , DestroyFunctor > )
+    , m_destroy()
+    {}
+
+  SharedAllocationRecord() = delete ;
+  SharedAllocationRecord( const SharedAllocationRecord & ) = delete ;
+  SharedAllocationRecord & operator = ( const SharedAllocationRecord & ) = delete ;
+
+public:
+
+  DestroyFunctor  m_destroy ;
+
+  // Allocate with a zero use count.  Incrementing the use count from zero to one
+  // inserts the record into the tracking list.  Decrementing the count from one to zero
+  // removes from the trakcing list and deallocates.
+  KOKKOS_INLINE_FUNCTION static
+  SharedAllocationRecord * allocate( const MemorySpace & arg_space 
+                                   , const std::string & arg_label
+                                   , const size_t        arg_alloc
+                                   )
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      return new SharedAllocationRecord( arg_space , arg_label , arg_alloc );
+#else
+      return (SharedAllocationRecord *) 0 ;
+#endif
+    }
+};
+
+union SharedAllocationTracker {
+private:
+
+  typedef SharedAllocationRecord<void,void>  Record ;
+
+  enum : uintptr_t { DO_NOT_DEREF_FLAG = 0x01ul };
+
+  // The allocation record resides in Host memory space
+  uintptr_t m_record_bits ;
+  Record  * m_record ;
+
+public:
+
+  // Use macros instead of inline functions to reduce
+  // pressure on compiler optimization by reducing
+  // number of symbols and inline functons.
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+
+#define KOKKOS_SHARED_ALLOCATION_TRACKER_ENABLED	\
+  Record::tracking_enabled()
+
+#define KOKKOS_SHARED_ALLOCATION_TRACKER_INCREMENT	\
+  if ( ! ( m_record_bits & DO_NOT_DEREF_FLAG ) ) Record::increment( m_record );
+
+#define KOKKOS_SHARED_ALLOCATION_TRACKER_DECREMENT	\
+  if ( ! ( m_record_bits & DO_NOT_DEREF_FLAG ) ) Record::decrement( m_record );
+
+#else
+
+#define KOKKOS_SHARED_ALLOCATION_TRACKER_ENABLED  0
+
+#define KOKKOS_SHARED_ALLOCATION_TRACKER_INCREMENT /* */
+
+#define KOKKOS_SHARED_ALLOCATION_TRACKER_DECREMENT /* */
+
+#endif
+
+  /** \brief  Assign a specialized record */
+  inline
+  void assign_allocated_record_to_uninitialized( Record * arg_record )
+    {
+      if ( arg_record ) {
+        Record::increment( m_record = arg_record );
+      }
+      else {
+        m_record_bits = DO_NOT_DEREF_FLAG ;
+      }
+    }
+
+  template< class MemorySpace >
+  constexpr
+  SharedAllocationRecord< MemorySpace , void > &
+  get_record() const
+    { return * static_cast< SharedAllocationRecord< MemorySpace , void > * >( m_record ); }
+
+  template< class MemorySpace >
+  std::string get_label() const
+    {
+      return ( m_record_bits & DO_NOT_DEREF_FLAG )
+             ? std::string()
+             : static_cast< SharedAllocationRecord< MemorySpace , void > * >( m_record )->get_label()
+             ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  int use_count() const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      Record * const tmp = reinterpret_cast<Record*>( m_record_bits & ~DO_NOT_DEREF_FLAG );
+      return ( tmp ? tmp->use_count() : 0 );
+#else
+      return 0 ;
+#endif
+    }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  ~SharedAllocationTracker()
+    { KOKKOS_SHARED_ALLOCATION_TRACKER_DECREMENT }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  constexpr SharedAllocationTracker()
+    : m_record_bits( DO_NOT_DEREF_FLAG ) {}
+
+  // Move:
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  SharedAllocationTracker( SharedAllocationTracker && rhs )
+    : m_record_bits( rhs.m_record_bits )
+    { rhs.m_record_bits = DO_NOT_DEREF_FLAG ; }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  SharedAllocationTracker & operator = ( SharedAllocationTracker && rhs )
+    {
+      // If this is tracking then must decrement
+      KOKKOS_SHARED_ALLOCATION_TRACKER_DECREMENT
+      // Move and reset RHS to default constructed value.
+      m_record_bits = rhs.m_record_bits ;
+      rhs.m_record_bits = DO_NOT_DEREF_FLAG ;
+      return *this ;
+    }
+
+  // Copy:
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  SharedAllocationTracker( const SharedAllocationTracker & rhs )
+    : m_record_bits( KOKKOS_SHARED_ALLOCATION_TRACKER_ENABLED
+                   ? rhs.m_record_bits
+                   : rhs.m_record_bits | DO_NOT_DEREF_FLAG )
+    {
+      KOKKOS_SHARED_ALLOCATION_TRACKER_INCREMENT
+    }
+
+  /** \brief  Copy construction may disable tracking. */
+  KOKKOS_FORCEINLINE_FUNCTION
+  SharedAllocationTracker( const SharedAllocationTracker & rhs
+                         , const bool enable_tracking )
+    : m_record_bits( KOKKOS_SHARED_ALLOCATION_TRACKER_ENABLED
+                     && enable_tracking
+                   ? rhs.m_record_bits
+                   : rhs.m_record_bits | DO_NOT_DEREF_FLAG )
+    { KOKKOS_SHARED_ALLOCATION_TRACKER_INCREMENT }
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  SharedAllocationTracker & operator = ( const SharedAllocationTracker & rhs )
+    {
+      // If this is tracking then must decrement
+      KOKKOS_SHARED_ALLOCATION_TRACKER_DECREMENT
+      m_record_bits = KOKKOS_SHARED_ALLOCATION_TRACKER_ENABLED
+                    ? rhs.m_record_bits
+                    : rhs.m_record_bits | DO_NOT_DEREF_FLAG ;
+      KOKKOS_SHARED_ALLOCATION_TRACKER_INCREMENT
+      return *this ;
+    }
+
+  /** \brief  Copy assignment may disable tracking */
+  KOKKOS_FORCEINLINE_FUNCTION
+  void assign( const SharedAllocationTracker & rhs
+             , const bool enable_tracking )
+    {
+      KOKKOS_SHARED_ALLOCATION_TRACKER_DECREMENT
+      m_record_bits = KOKKOS_SHARED_ALLOCATION_TRACKER_ENABLED
+                      && enable_tracking
+                    ? rhs.m_record_bits
+                    : rhs.m_record_bits | DO_NOT_DEREF_FLAG ;
+      KOKKOS_SHARED_ALLOCATION_TRACKER_INCREMENT
+    }
+
+#undef KOKKOS_SHARED_ALLOCATION_TRACKER_ENABLED
+#undef KOKKOS_SHARED_ALLOCATION_TRACKER_INCREMENT
+#undef KOKKOS_SHARED_ALLOCATION_TRACKER_DECREMENT
+
+};
+
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+#endif
diff --git a/lib/kokkos/core/src/impl/KokkosExp_ViewArray.hpp b/lib/kokkos/core/src/impl/KokkosExp_ViewArray.hpp
new file mode 100644
index 0000000000..17d28ace4d
--- /dev/null
+++ b/lib/kokkos/core/src/impl/KokkosExp_ViewArray.hpp
@@ -0,0 +1,606 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXPERIMENTAL_VIEW_ARRAY_MAPPING_HPP
+#define KOKKOS_EXPERIMENTAL_VIEW_ARRAY_MAPPING_HPP
+
+#include <Kokkos_Array.hpp>
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template< class DataType , class ArrayLayout , class V , size_t N , class P >
+struct ViewDataAnalysis< DataType , ArrayLayout , Kokkos::Array<V,N,P> >
+{
+private:
+
+  typedef ViewArrayAnalysis<DataType> array_analysis ;
+
+  static_assert( std::is_same<P,void>::value , "" );
+  static_assert( std::is_same<typename array_analysis::non_const_value_type , Kokkos::Array<V,N,P> >::value , "" );
+  static_assert( std::is_scalar<V>::value , "View of Array type must be of a scalar type" );
+
+public:
+
+  typedef Kokkos::Array<>  specialize ;
+
+  typedef typename array_analysis::dimension  dimension ;
+
+private:
+
+  enum { is_const = std::is_same< typename array_analysis::value_type
+                                , typename array_analysis::const_value_type
+                                >::value };
+
+  typedef typename dimension::template append<N>::type array_scalar_dimension ;
+
+  typedef typename std::conditional< is_const , const V , V >::type  scalar_type ;
+  typedef V       non_const_scalar_type ;
+  typedef const V const_scalar_type ;
+
+public:
+
+  typedef typename array_analysis::value_type            value_type ;
+  typedef typename array_analysis::const_value_type      const_value_type ;
+  typedef typename array_analysis::non_const_value_type  non_const_value_type ;
+
+  typedef typename ViewDataType<           value_type , dimension >::type  type ;
+  typedef typename ViewDataType<     const_value_type , dimension >::type  const_type ;
+  typedef typename ViewDataType< non_const_value_type , dimension >::type  non_const_type ;
+
+  typedef typename ViewDataType<           scalar_type , array_scalar_dimension >::type  scalar_array_type ;
+  typedef typename ViewDataType<     const_scalar_type , array_scalar_dimension >::type  const_scalar_array_type ;
+  typedef typename ViewDataType< non_const_scalar_type , array_scalar_dimension >::type  non_const_scalar_array_type ;
+};
+
+}}} // namespace Kokkos::Experimental::Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+/** \brief  View mapping for non-specialized data type and standard layout */
+template< class Traits >
+class ViewMapping< Traits ,
+  typename std::enable_if<(
+    std::is_same< typename Traits::specialize , Kokkos::Array<> >::value &&
+    ( std::is_same< typename Traits::array_layout , Kokkos::LayoutLeft >::value ||
+      std::is_same< typename Traits::array_layout , Kokkos::LayoutRight >::value ||
+      std::is_same< typename Traits::array_layout , Kokkos::LayoutStride >::value )
+  )>::type >
+{
+private:
+
+  template< class , class ... > friend class ViewMapping ;
+  template< class , class ... > friend class Kokkos::Experimental::View ;
+
+  typedef ViewOffset< typename Traits::dimension
+                    , typename Traits::array_layout
+                    , void
+                    >  offset_type ;
+
+  typedef typename Traits::value_type::pointer handle_type ;
+
+  handle_type  m_handle ;
+  offset_type  m_offset ;
+  size_t       m_stride ;
+
+  typedef typename Traits::value_type::value_type scalar_type ;
+
+  typedef Kokkos::Array< scalar_type , ~size_t(0) , Kokkos::Array<>::contiguous >  contiguous_reference ;
+  typedef Kokkos::Array< scalar_type , ~size_t(0) , Kokkos::Array<>::strided >     strided_reference ;
+
+  enum { is_contiguous_reference =
+    ( Traits::rank == 0 ) || ( std::is_same< typename Traits::array_layout , Kokkos::LayoutRight >::value ) };
+
+  enum { Array_N = Traits::value_type::size() };
+  enum { Array_S = is_contiguous_reference ? Array_N : 1 };
+
+  KOKKOS_INLINE_FUNCTION
+  ViewMapping( const handle_type & arg_handle , const offset_type & arg_offset )
+    : m_handle( arg_handle )
+    , m_offset( arg_offset )
+    , m_stride( is_contiguous_reference ? 0 : arg_offset.span() )
+    {}
+
+public:
+
+  //----------------------------------------
+  // Domain dimensions
+
+  enum { Rank = Traits::dimension::rank };
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr size_t extent( const iType & r ) const
+    { return m_offset.m_dim.extent(r); }
+
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename Traits::array_layout layout() const
+    { return m_offset.layout(); }
+
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_0() const { return m_offset.dimension_0(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return m_offset.dimension_1(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return m_offset.dimension_2(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return m_offset.dimension_3(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return m_offset.dimension_4(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return m_offset.dimension_5(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return m_offset.dimension_6(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return m_offset.dimension_7(); }
+
+  // Is a regular layout with uniform striding for each index.
+  using is_regular = typename offset_type::is_regular ;
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return m_offset.stride_0(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return m_offset.stride_1(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return m_offset.stride_2(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return m_offset.stride_3(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return m_offset.stride_4(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return m_offset.stride_5(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return m_offset.stride_6(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return m_offset.stride_7(); }
+
+  //----------------------------------------
+  // Range span
+
+  /** \brief  Span of the mapped range */
+  KOKKOS_INLINE_FUNCTION constexpr size_t span() const
+    { return m_offset.span() * Array_N ; }
+
+  /** \brief  Is the mapped range span contiguous */
+  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const
+    { return m_offset.span_is_contiguous(); }
+
+  typedef typename std::conditional< is_contiguous_reference , contiguous_reference , strided_reference >::type  reference_type ;
+
+  typedef handle_type pointer_type ;
+
+  /** \brief  If data references are lvalue_reference than can query pointer to memory */
+  KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const
+    { return m_handle ; }
+
+  //----------------------------------------
+  // The View class performs all rank and bounds checking before
+  // calling these element reference methods.
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference() const { return reference_type( m_handle + 0 , Array_N , 0 ); }
+
+  template< typename I0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type
+  reference( const I0 & i0 ) const
+    { return reference_type( m_handle + m_offset(i0) * Array_S , Array_N , m_stride ); }
+
+  template< typename I0 , typename I1 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 ) const
+    { return reference_type( m_handle + m_offset(i0,i1) * Array_S , Array_N , m_stride ); }
+
+  template< typename I0 , typename I1 , typename I2 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 ) const
+    { return reference_type( m_handle + m_offset(i0,i1,i2) * Array_S , Array_N , m_stride ); }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 ) const
+    { return reference_type( m_handle + m_offset(i0,i1,i2,i3) * Array_S , Array_N , m_stride ); }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+                          , const I4 & i4 ) const
+    { return reference_type( m_handle + m_offset(i0,i1,i2,i3,i4) * Array_S , Array_N , m_stride ); }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+                          , const I4 & i4 , const I5 & i5 ) const
+    { return reference_type( m_handle + m_offset(i0,i1,i2,i3,i4,i5) * Array_S , Array_N , m_stride ); }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 , typename I6 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+                          , const I4 & i4 , const I5 & i5 , const I6 & i6 ) const
+    { return reference_type( m_handle + m_offset(i0,i1,i2,i3,i4,i5,i6) * Array_S , Array_N , m_stride ); }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 , typename I6 , typename I7 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+                          , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7 ) const
+    { return reference_type( m_handle + m_offset(i0,i1,i2,i3,i4,i5,i6,i7) * Array_S , Array_N , m_stride ); }
+
+  //----------------------------------------
+
+private:
+
+  enum { MemorySpanMask = 8 - 1 /* Force alignment on 8 byte boundary */ };
+  enum { MemorySpanSize = sizeof(scalar_type) };
+
+public:
+
+  /** \brief  Span, in bytes, of the referenced memory */
+  KOKKOS_INLINE_FUNCTION constexpr size_t memory_span() const
+    {
+      return ( m_offset.span() * Array_N * MemorySpanSize + MemorySpanMask ) & ~size_t(MemorySpanMask);
+    }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION ~ViewMapping() {}
+  KOKKOS_INLINE_FUNCTION ViewMapping() : m_handle(), m_offset(), m_stride(0) {}
+  KOKKOS_INLINE_FUNCTION ViewMapping( const ViewMapping & rhs )
+    : m_handle( rhs.m_handle ), m_offset( rhs.m_offset ), m_stride( rhs.m_stride ) {}
+  KOKKOS_INLINE_FUNCTION ViewMapping & operator = ( const ViewMapping & rhs )
+    { m_handle = rhs.m_handle ; m_offset = rhs.m_offset ; m_stride = rhs.m_stride ; ; return *this ; }
+
+  KOKKOS_INLINE_FUNCTION ViewMapping( ViewMapping && rhs )
+    : m_handle( rhs.m_handle ), m_offset( rhs.m_offset ), m_stride( rhs.m_stride ) {}
+  KOKKOS_INLINE_FUNCTION ViewMapping & operator = ( ViewMapping && rhs )
+    { m_handle = rhs.m_handle ; m_offset = rhs.m_offset ; m_stride = rhs.m_stride ; return *this ; }
+
+  //----------------------------------------
+
+  template< class ... Args >
+  KOKKOS_INLINE_FUNCTION
+  ViewMapping( pointer_type ptr , Args ... args )
+    : m_handle( ptr )
+    , m_offset( std::integral_constant< unsigned , 0 >() , args... )
+    , m_stride( m_offset.span() )
+    {}
+
+  //----------------------------------------
+
+  template< class ... P >
+  SharedAllocationRecord<> *
+  allocate_shared( ViewCtorProp< P... > const & arg_prop
+                 , typename Traits::array_layout const & arg_layout
+                 )
+  {
+    typedef ViewCtorProp< P... > alloc_prop ;
+
+    typedef typename alloc_prop::execution_space  execution_space ;
+    typedef typename Traits::memory_space         memory_space ;
+    typedef ViewValueFunctor< execution_space , scalar_type > functor_type ;
+    typedef SharedAllocationRecord< memory_space , functor_type > record_type ;
+
+    // Query the mapping for byte-size of allocation.
+    typedef std::integral_constant< unsigned ,
+      alloc_prop::allow_padding ? sizeof(scalar_type) : 0 > padding ;
+
+    m_offset = offset_type( padding(), arg_layout );
+
+    const size_t alloc_size =
+      ( m_offset.span() * Array_N * MemorySpanSize + MemorySpanMask ) & ~size_t(MemorySpanMask);
+
+    // Allocate memory from the memory space and create tracking record.
+    record_type * const record =
+      record_type::allocate( ((ViewCtorProp<void,memory_space> const &) arg_prop ).value
+                           , ((ViewCtorProp<void,std::string>  const &) arg_prop ).value
+                           , alloc_size );
+
+    if ( alloc_size ) {
+      m_handle =
+        handle_type( reinterpret_cast< pointer_type >( record->data() ) );
+
+      if ( alloc_prop::initialize ) {
+        // The functor constructs and destroys
+        record->m_destroy = functor_type( ((ViewCtorProp<void,execution_space> const & )arg_prop).value
+                                        , (pointer_type) m_handle
+                                        , m_offset.span() * Array_N
+                                        );
+
+        record->m_destroy.construct_shared_allocation();
+      }
+    }
+
+    return record ;
+  }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+/** \brief  Assign compatible default mappings */
+
+template< class DstTraits , class SrcTraits >
+class ViewMapping< DstTraits , SrcTraits ,
+  typename std::enable_if<(
+    std::is_same< typename DstTraits::memory_space , typename SrcTraits::memory_space >::value
+    &&
+    std::is_same< typename DstTraits::specialize , Kokkos::Array<> >::value
+    &&
+    (
+      std::is_same< typename DstTraits::array_layout , Kokkos::LayoutLeft >::value ||
+      std::is_same< typename DstTraits::array_layout , Kokkos::LayoutRight >::value ||
+      std::is_same< typename DstTraits::array_layout , Kokkos::LayoutStride >::value
+    )
+    &&
+    std::is_same< typename SrcTraits::specialize , Kokkos::Array<> >::value
+    &&
+    (
+      std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value ||
+      std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value ||
+      std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutStride >::value
+    )
+  )>::type >
+{
+public:
+
+  enum { is_assignable = true };
+
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker  TrackType ;
+  typedef ViewMapping< DstTraits , void >  DstType ;
+  typedef ViewMapping< SrcTraits , void >  SrcType ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void assign( DstType & dst , const SrcType & src , const TrackType & src_track )
+    {
+      static_assert( std::is_same< typename DstTraits::value_type , typename SrcTraits::value_type >::value ||
+                     std::is_same< typename DstTraits::value_type , typename SrcTraits::const_value_type >::value
+                   , "View assignment must have same value type or const = non-const" );
+
+      static_assert( ViewDimensionAssignable< typename DstTraits::dimension , typename SrcTraits::dimension >::value
+                   , "View assignment must have compatible dimensions" );
+
+      static_assert( std::is_same< typename DstTraits::array_layout , typename SrcTraits::array_layout >::value ||
+                     std::is_same< typename DstTraits::array_layout , Kokkos::LayoutStride >::value ||
+                     ( DstTraits::dimension::rank == 0 ) ||
+                     ( DstTraits::dimension::rank == 1 && DstTraits::dimension::rank_dynamic == 1 )
+                   , "View assignment must have compatible layout or have rank <= 1" );
+
+      typedef typename DstType::offset_type  dst_offset_type ;
+
+      dst.m_offset = dst_offset_type( src.m_offset );
+      dst.m_handle = src.m_handle ;
+      dst.m_stride = src.m_stride ;
+    }
+};
+
+/** \brief Assign Array to non-Array */
+
+template< class DstTraits , class SrcTraits >
+class ViewMapping< DstTraits , SrcTraits ,
+  typename std::enable_if<(
+    std::is_same< typename DstTraits::memory_space , typename SrcTraits::memory_space >::value
+    &&
+    std::is_same< typename DstTraits::specialize , void >::value
+    &&
+    (
+      std::is_same< typename DstTraits::array_layout , Kokkos::LayoutLeft >::value ||
+      std::is_same< typename DstTraits::array_layout , Kokkos::LayoutRight >::value ||
+      std::is_same< typename DstTraits::array_layout , Kokkos::LayoutStride >::value
+    )
+    &&
+    std::is_same< typename SrcTraits::specialize , Kokkos::Array<> >::value
+    &&
+    (
+      std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value ||
+      std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value ||
+      std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutStride >::value
+    )
+  )>::type >
+{
+public:
+
+  // Can only convert to View::array_type
+
+  enum { is_assignable = std::is_same< typename DstTraits::data_type ,    typename SrcTraits::scalar_array_type >::value &&
+                         std::is_same< typename DstTraits::array_layout , typename SrcTraits::array_layout >::value };
+
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker  TrackType ;
+  typedef ViewMapping< DstTraits , void >  DstType ;
+  typedef ViewMapping< SrcTraits , void >  SrcType ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void assign( DstType & dst , const SrcType & src , const TrackType & src_track )
+    {
+      static_assert( is_assignable , "Can only convert to array_type" );
+
+      typedef typename DstType::offset_type  dst_offset_type ;
+
+      // Array dimension becomes the last dimension.
+      // Arguments beyond the destination rank are ignored.
+      if ( src.span_is_contiguous() ) { // not padded
+        dst.m_offset = dst_offset_type( std::integral_constant<unsigned,0>() ,
+          typename DstTraits::array_layout
+            ( ( 0 < SrcType::Rank ? src.dimension_0() : SrcTraits::value_type::size() )
+            , ( 1 < SrcType::Rank ? src.dimension_1() : SrcTraits::value_type::size() )
+            , ( 2 < SrcType::Rank ? src.dimension_2() : SrcTraits::value_type::size() )
+            , ( 3 < SrcType::Rank ? src.dimension_3() : SrcTraits::value_type::size() )
+            , ( 4 < SrcType::Rank ? src.dimension_4() : SrcTraits::value_type::size() )
+            , ( 5 < SrcType::Rank ? src.dimension_5() : SrcTraits::value_type::size() )
+            , ( 6 < SrcType::Rank ? src.dimension_6() : SrcTraits::value_type::size() )
+            , ( 7 < SrcType::Rank ? src.dimension_7() : SrcTraits::value_type::size() )
+            ) );
+      }
+      else { // is padded
+        typedef std::integral_constant<unsigned,sizeof(typename SrcTraits::value_type::value_type)> padded ;
+
+        dst.m_offset = dst_offset_type( padded() ,
+          typename DstTraits::array_layout
+            ( ( 0 < SrcType::Rank ? src.dimension_0() : SrcTraits::value_type::size() )
+            , ( 1 < SrcType::Rank ? src.dimension_1() : SrcTraits::value_type::size() )
+            , ( 2 < SrcType::Rank ? src.dimension_2() : SrcTraits::value_type::size() )
+            , ( 3 < SrcType::Rank ? src.dimension_3() : SrcTraits::value_type::size() )
+            , ( 4 < SrcType::Rank ? src.dimension_4() : SrcTraits::value_type::size() )
+            , ( 5 < SrcType::Rank ? src.dimension_5() : SrcTraits::value_type::size() )
+            , ( 6 < SrcType::Rank ? src.dimension_6() : SrcTraits::value_type::size() )
+            , ( 7 < SrcType::Rank ? src.dimension_7() : SrcTraits::value_type::size() )
+            ) );
+      }
+
+      dst.m_handle = src.m_handle ;
+    }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+template< class SrcTraits , class ... Args >
+struct ViewMapping
+  < typename std::enable_if<(
+      std::is_same< typename SrcTraits::specialize , Kokkos::Array<> >::value
+      &&
+      (
+        std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value ||
+        std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value ||
+        std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutStride >::value
+      )
+    )>::type
+  , SrcTraits
+  , Args ... >
+{
+private:
+
+  static_assert( SrcTraits::rank == sizeof...(Args) , "" );
+
+  enum : bool
+    { R0 = is_integral_extent<0,Args...>::value
+    , R1 = is_integral_extent<1,Args...>::value
+    , R2 = is_integral_extent<2,Args...>::value
+    , R3 = is_integral_extent<3,Args...>::value
+    , R4 = is_integral_extent<4,Args...>::value
+    , R5 = is_integral_extent<5,Args...>::value
+    , R6 = is_integral_extent<6,Args...>::value
+    , R7 = is_integral_extent<7,Args...>::value
+    };
+
+  enum { rank = unsigned(R0) + unsigned(R1) + unsigned(R2) + unsigned(R3)
+              + unsigned(R4) + unsigned(R5) + unsigned(R6) + unsigned(R7) };
+
+  // Whether right-most rank is a range.
+  enum { R0_rev = 0 == SrcTraits::rank ? false : (
+                  1 == SrcTraits::rank ? R0 : (
+                  2 == SrcTraits::rank ? R1 : (
+                  3 == SrcTraits::rank ? R2 : (
+                  4 == SrcTraits::rank ? R3 : (
+                  5 == SrcTraits::rank ? R4 : (
+                  6 == SrcTraits::rank ? R5 : (
+                  7 == SrcTraits::rank ? R6 : R7 ))))))) };
+
+  // Subview's layout
+  typedef typename std::conditional<
+      ( /* Same array layout IF */
+        ( rank == 0 ) /* output rank zero */
+        ||
+        // OutputRank 1 or 2, InputLayout Left, Interval 0
+        // because single stride one or second index has a stride.
+        ( rank <= 2 && R0 && std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value )
+        ||
+        // OutputRank 1 or 2, InputLayout Right, Interval [InputRank-1]
+        // because single stride one or second index has a stride.
+        ( rank <= 2 && R0_rev && std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value )
+      ), typename SrcTraits::array_layout , Kokkos::LayoutStride
+      >::type array_layout ;
+
+  typedef typename SrcTraits::value_type  value_type ;
+
+  typedef typename std::conditional< rank == 0 , value_type ,
+          typename std::conditional< rank == 1 , value_type * ,
+          typename std::conditional< rank == 2 , value_type ** ,
+          typename std::conditional< rank == 3 , value_type *** ,
+          typename std::conditional< rank == 4 , value_type **** ,
+          typename std::conditional< rank == 5 , value_type ***** ,
+          typename std::conditional< rank == 6 , value_type ****** ,
+          typename std::conditional< rank == 7 , value_type ******* ,
+                                                 value_type ********
+          >::type >::type >::type >::type >::type >::type >::type >::type
+     data_type ;
+
+public:
+
+  typedef Kokkos::Experimental::ViewTraits
+    < data_type
+    , array_layout
+    , typename SrcTraits::device_type
+    , typename SrcTraits::memory_traits > traits_type ;
+
+  typedef Kokkos::Experimental::View
+    < data_type
+    , array_layout
+    , typename SrcTraits::device_type
+    , typename SrcTraits::memory_traits > type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void assign( ViewMapping< traits_type , void > & dst
+                    , ViewMapping< SrcTraits , void > const & src
+                    , Args ... args )
+    {
+      typedef ViewMapping< traits_type , void >  DstType ;
+
+      typedef typename DstType::offset_type  dst_offset_type ;
+      typedef typename DstType::handle_type  dst_handle_type ;
+
+      const SubviewExtents< SrcTraits::rank , rank >
+        extents( src.m_offset.m_dim , args... );
+
+      dst.m_offset = dst_offset_type( src.m_offset , extents );
+      dst.m_handle = dst_handle_type( src.m_handle +
+                                      src.m_offset( extents.domain_offset(0)
+                                                  , extents.domain_offset(1)
+                                                  , extents.domain_offset(2)
+                                                  , extents.domain_offset(3)
+                                                  , extents.domain_offset(4)
+                                                  , extents.domain_offset(5)
+                                                  , extents.domain_offset(6)
+                                                  , extents.domain_offset(7)
+                                                  ) );
+    }
+};
+
+}}} // namespace Kokkos::Experimental::Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_EXPERIMENTAL_VIEW_ARRAY_MAPPING_HPP */
+
diff --git a/lib/kokkos/core/src/impl/KokkosExp_ViewCtor.hpp b/lib/kokkos/core/src/impl/KokkosExp_ViewCtor.hpp
new file mode 100644
index 0000000000..6525fed0a5
--- /dev/null
+++ b/lib/kokkos/core/src/impl/KokkosExp_ViewCtor.hpp
@@ -0,0 +1,252 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXPERIMENTAL_IMPL_VIEW_CTOR_PROP_HPP
+#define KOKKOS_EXPERIMENTAL_IMPL_VIEW_CTOR_PROP_HPP
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+/* For backward compatibility */
+
+struct ViewAllocateWithoutInitializing {
+
+  const std::string label ;
+
+  ViewAllocateWithoutInitializing() : label() {}
+
+  explicit
+  ViewAllocateWithoutInitializing( const std::string & arg_label ) : label( arg_label ) {}
+
+  explicit
+  ViewAllocateWithoutInitializing( const char * const  arg_label ) : label( arg_label ) {}
+};
+
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+struct WithoutInitializing_t {};
+struct AllowPadding_t {};
+struct NullSpace_t {};
+
+//----------------------------------------------------------------------------
+/**\brief Whether a type can be used for a view label */
+
+template < typename >
+struct is_view_label : public std::false_type {};
+
+template<>
+struct is_view_label< std::string > : public std::true_type {};
+
+template< unsigned N >
+struct is_view_label< char[N] > : public std::true_type {};
+
+template< unsigned N >
+struct is_view_label< const char[N] > : public std::true_type {};
+
+//----------------------------------------------------------------------------
+
+template< typename ... P >
+struct ViewCtorProp ;
+
+/*  std::integral_constant<unsigned,I> are dummy arguments
+ *  that avoid duplicate base class errors
+ */
+template< unsigned I >
+struct ViewCtorProp< void , std::integral_constant<unsigned,I> >
+{
+  ViewCtorProp() = default ;
+  ViewCtorProp( const ViewCtorProp & ) = default ;
+  ViewCtorProp & operator = ( const ViewCtorProp & ) = default ;
+
+  template< typename P >
+  ViewCtorProp( const P & ) {}
+};
+
+/* Property flags have constexpr value */
+template< typename P >
+struct ViewCtorProp
+  < typename std::enable_if<
+      std::is_same< P , AllowPadding_t >::value ||
+      std::is_same< P , WithoutInitializing_t >::value
+    >::type
+  , P
+  >
+{
+  ViewCtorProp() = default ;
+  ViewCtorProp( const ViewCtorProp & ) = default ;
+  ViewCtorProp & operator = ( const ViewCtorProp & ) = default ;
+
+  typedef P type ;
+
+  ViewCtorProp( const type & ) {}
+
+  static constexpr type value = type();
+};
+
+/* Map input label type to std::string */
+template< typename Label >
+struct ViewCtorProp
+  < typename std::enable_if< is_view_label< Label >::value >::type
+  , Label
+  >
+{
+  ViewCtorProp() = default ;
+  ViewCtorProp( const ViewCtorProp & ) = default ;
+  ViewCtorProp & operator = ( const ViewCtorProp & ) = default ;
+
+  typedef std::string type ;
+
+  ViewCtorProp( const type & arg ) : value( arg ) {}
+  ViewCtorProp( type && arg ) : value( arg ) {}
+
+  type value ;
+};
+
+template< typename Space >
+struct ViewCtorProp
+  < typename std::enable_if<
+      Kokkos::Impl::is_memory_space<Space>::value ||
+      Kokkos::Impl::is_execution_space<Space>::value
+    >::type
+  , Space
+  >
+{
+  ViewCtorProp() = default ;
+  ViewCtorProp( const ViewCtorProp & ) = default ;
+  ViewCtorProp & operator = ( const ViewCtorProp & ) = default ;
+
+  typedef Space type ;
+
+  ViewCtorProp( const type & arg ) : value( arg ) {}
+
+  type value ;
+};
+
+
+template< typename T >
+struct ViewCtorProp < void , T * >
+{
+  ViewCtorProp() = default ;
+  ViewCtorProp( const ViewCtorProp & ) = default ;
+  ViewCtorProp & operator = ( const ViewCtorProp & ) = default ;
+
+  typedef T * type ;
+
+  KOKKOS_INLINE_FUNCTION
+  ViewCtorProp( const type arg ) : value( arg ) {}
+
+  type value ;
+};
+
+
+template< typename ... P >
+struct ViewCtorProp : public ViewCtorProp< void , P > ...
+{
+private:
+
+  typedef Kokkos::Impl::has_condition< void , Kokkos::Impl::is_memory_space , P ... >
+    var_memory_space ;
+
+  typedef Kokkos::Impl::has_condition< void , Kokkos::Impl::is_execution_space , P ... >
+    var_execution_space ;
+
+  struct VOIDDUMMY{};
+
+  typedef Kokkos::Impl::has_condition< VOIDDUMMY , std::is_pointer , P ... >
+    var_pointer ;
+
+public:
+
+  /* Flags for the common properties */
+  enum { has_memory_space    = var_memory_space::value };
+  enum { has_execution_space = var_execution_space::value };
+  enum { has_pointer         = var_pointer::value };
+  enum { has_label           = Kokkos::Impl::has_type< std::string , P... >::value };
+  enum { allow_padding       = Kokkos::Impl::has_type< AllowPadding_t , P... >::value };
+  enum { initialize          = ! Kokkos::Impl::has_type< WithoutInitializing_t , P ... >::value };
+
+  typedef typename var_memory_space::type     memory_space ;
+  typedef typename var_execution_space::type  execution_space ;
+  typedef typename var_pointer::type          pointer_type ;
+
+  /*  Copy from a matching argument list.
+   *  Requires  std::is_same< P , ViewCtorProp< void , Args >::value ...
+   */
+  template< typename ... Args >
+  inline
+  ViewCtorProp( Args const & ... args )
+    : ViewCtorProp< void , P >( args ) ...
+    {}
+
+  template< typename ... Args >
+  KOKKOS_INLINE_FUNCTION
+  ViewCtorProp( pointer_type arg0 , Args const & ... args )
+    : ViewCtorProp< void , pointer_type >( arg0 )
+    , ViewCtorProp< void , typename ViewCtorProp< void , Args >::type >( args ) ...
+    {}
+
+  /* Copy from a matching property subset */
+  template< typename ... Args >
+  ViewCtorProp( ViewCtorProp< Args ... > const & arg )
+    : ViewCtorProp< void , Args >( ((ViewCtorProp<void,Args> const &) arg ) ) ...
+    {}
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif
+
diff --git a/lib/kokkos/core/src/impl/KokkosExp_ViewMapping.hpp b/lib/kokkos/core/src/impl/KokkosExp_ViewMapping.hpp
new file mode 100644
index 0000000000..ed56536cd9
--- /dev/null
+++ b/lib/kokkos/core/src/impl/KokkosExp_ViewMapping.hpp
@@ -0,0 +1,2932 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXPERIMENTAL_VIEW_MAPPING_HPP
+#define KOKKOS_EXPERIMENTAL_VIEW_MAPPING_HPP
+
+#include <type_traits>
+#include <initializer_list>
+
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_Pair.hpp>
+#include <Kokkos_Layout.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/KokkosExp_ViewCtor.hpp>
+#include <impl/Kokkos_Atomic_View.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template< unsigned I , size_t ... Args >
+struct variadic_size_t
+  { enum { value = ~size_t(0) }; };
+
+template< size_t Val , size_t ... Args >
+struct variadic_size_t< 0 , Val , Args ... >
+  { enum { value = Val }; };
+
+template< unsigned I , size_t Val , size_t ... Args >
+struct variadic_size_t< I , Val , Args ... >
+  { enum { value = variadic_size_t< I - 1 , Args ... >::value }; };
+
+template< size_t ... Args >
+struct rank_dynamic ;
+
+template<>
+struct rank_dynamic<> { enum { value = 0 }; };
+
+template< size_t Val , size_t ... Args >
+struct rank_dynamic< Val , Args... >
+{
+  enum { value = ( Val == 0 ? 1 : 0 ) + rank_dynamic< Args... >::value };
+};
+
+#define KOKKOS_IMPL_VIEW_DIMENSION( R ) \
+  template< size_t V , unsigned > struct ViewDimension ## R \
+    { \
+      enum { ArgN ## R = ( V != ~size_t(0) ? V : 1 ) }; \
+      enum { N ## R = ( V != ~size_t(0) ? V : 1 ) }; \
+      KOKKOS_INLINE_FUNCTION explicit ViewDimension ## R ( size_t ) {} \
+      ViewDimension ## R () = default ; \
+      ViewDimension ## R ( const ViewDimension ## R  & ) = default ; \
+      ViewDimension ## R & operator = ( const ViewDimension ## R  & ) = default ; \
+    }; \
+  template< unsigned RD > struct ViewDimension ## R < 0 , RD > \
+    { \
+      enum { ArgN ## R = 0 }; \
+      typename std::conditional<( RD < 3 ), size_t , unsigned >::type N ## R ; \
+      ViewDimension ## R () = default ; \
+      ViewDimension ## R ( const ViewDimension ## R  & ) = default ; \
+      ViewDimension ## R & operator = ( const ViewDimension ## R  & ) = default ; \
+      KOKKOS_INLINE_FUNCTION explicit ViewDimension ## R ( size_t V ) : N ## R ( V ) {} \
+    };
+
+KOKKOS_IMPL_VIEW_DIMENSION( 0 )
+KOKKOS_IMPL_VIEW_DIMENSION( 1 )
+KOKKOS_IMPL_VIEW_DIMENSION( 2 )
+KOKKOS_IMPL_VIEW_DIMENSION( 3 )
+KOKKOS_IMPL_VIEW_DIMENSION( 4 )
+KOKKOS_IMPL_VIEW_DIMENSION( 5 )
+KOKKOS_IMPL_VIEW_DIMENSION( 6 )
+KOKKOS_IMPL_VIEW_DIMENSION( 7 )
+
+#undef KOKKOS_IMPL_VIEW_DIMENSION
+
+template< size_t ... Vals >
+struct ViewDimension
+  : public ViewDimension0< variadic_size_t<0,Vals...>::value 
+                         , rank_dynamic< Vals... >::value >
+  , public ViewDimension1< variadic_size_t<1,Vals...>::value 
+                         , rank_dynamic< Vals... >::value >
+  , public ViewDimension2< variadic_size_t<2,Vals...>::value 
+                         , rank_dynamic< Vals... >::value >
+  , public ViewDimension3< variadic_size_t<3,Vals...>::value 
+                         , rank_dynamic< Vals... >::value >
+  , public ViewDimension4< variadic_size_t<4,Vals...>::value 
+                         , rank_dynamic< Vals... >::value >
+  , public ViewDimension5< variadic_size_t<5,Vals...>::value 
+                         , rank_dynamic< Vals... >::value >
+  , public ViewDimension6< variadic_size_t<6,Vals...>::value 
+                         , rank_dynamic< Vals... >::value >
+  , public ViewDimension7< variadic_size_t<7,Vals...>::value 
+                         , rank_dynamic< Vals... >::value >
+{
+  typedef ViewDimension0< variadic_size_t<0,Vals...>::value 
+                        , rank_dynamic< Vals... >::value > D0 ;
+  typedef ViewDimension1< variadic_size_t<1,Vals...>::value 
+                        , rank_dynamic< Vals... >::value > D1 ;
+  typedef ViewDimension2< variadic_size_t<2,Vals...>::value 
+                        , rank_dynamic< Vals... >::value > D2 ;
+  typedef ViewDimension3< variadic_size_t<3,Vals...>::value 
+                        , rank_dynamic< Vals... >::value > D3 ;
+  typedef ViewDimension4< variadic_size_t<4,Vals...>::value 
+                        , rank_dynamic< Vals... >::value > D4 ;
+  typedef ViewDimension5< variadic_size_t<5,Vals...>::value 
+                        , rank_dynamic< Vals... >::value > D5 ;
+  typedef ViewDimension6< variadic_size_t<6,Vals...>::value 
+                        , rank_dynamic< Vals... >::value > D6 ;
+  typedef ViewDimension7< variadic_size_t<7,Vals...>::value 
+                        , rank_dynamic< Vals... >::value > D7 ;
+
+  using D0::ArgN0 ;
+  using D1::ArgN1 ;
+  using D2::ArgN2 ;
+  using D3::ArgN3 ;
+  using D4::ArgN4 ;
+  using D5::ArgN5 ;
+  using D6::ArgN6 ;
+  using D7::ArgN7 ;
+
+  using D0::N0 ;
+  using D1::N1 ;
+  using D2::N2 ;
+  using D3::N3 ;
+  using D4::N4 ;
+  using D5::N5 ;
+  using D6::N6 ;
+  using D7::N7 ;
+
+  enum { rank = sizeof...(Vals) };
+  enum { rank_dynamic = Impl::rank_dynamic< Vals... >::value };
+
+  ViewDimension() = default ;
+  ViewDimension( const ViewDimension & ) = default ;
+  ViewDimension & operator = ( const ViewDimension & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr
+  ViewDimension( size_t n0 , size_t n1 , size_t n2 , size_t n3
+               , size_t n4 , size_t n5 , size_t n6 , size_t n7 )
+    : D0( n0 )
+    , D1( n1 )
+    , D2( n2 )
+    , D3( n3 )
+    , D4( n4 )
+    , D5( n5 )
+    , D6( n6 )
+    , D7( n7 )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_t extent( const unsigned r ) const
+    {
+      return r == 0 ? N0 : (
+             r == 1 ? N1 : (
+             r == 2 ? N2 : (
+             r == 3 ? N3 : (
+             r == 4 ? N4 : (
+             r == 5 ? N5 : (
+             r == 6 ? N6 : (
+             r == 7 ? N7 : 0 )))))));
+    }
+
+  template< size_t N >
+  struct prepend { typedef ViewDimension< N , Vals... > type ; };
+
+  template< size_t N >
+  struct append { typedef ViewDimension< Vals... , N > type ; };
+};
+
+template< class A , class B >
+struct ViewDimensionJoin ;
+
+template< size_t ... A , size_t ... B >
+struct ViewDimensionJoin< ViewDimension< A... > , ViewDimension< B... > > {
+  typedef ViewDimension< A... , B... > type ;
+};
+
+//----------------------------------------------------------------------------
+
+template< class DstDim , class SrcDim >
+struct ViewDimensionAssignable ;
+
+template< size_t ... DstArgs , size_t ... SrcArgs >
+struct ViewDimensionAssignable< ViewDimension< DstArgs ... >
+                              , ViewDimension< SrcArgs ... > >
+{
+  typedef ViewDimension< DstArgs... > dst ;
+  typedef ViewDimension< SrcArgs... > src ;
+
+  enum { value =
+    unsigned(dst::rank) == unsigned(src::rank) && (
+      //Compile time check that potential static dimensions match
+      ( ( 1 > dst::rank_dynamic && 1 > src::rank_dynamic ) ? (size_t(dst::ArgN0) == size_t(src::ArgN0)) : true ) &&
+      ( ( 2 > dst::rank_dynamic && 2 > src::rank_dynamic ) ? (size_t(dst::ArgN1) == size_t(src::ArgN1)) : true ) &&
+      ( ( 3 > dst::rank_dynamic && 3 > src::rank_dynamic ) ? (size_t(dst::ArgN2) == size_t(src::ArgN2)) : true ) &&
+      ( ( 4 > dst::rank_dynamic && 4 > src::rank_dynamic ) ? (size_t(dst::ArgN3) == size_t(src::ArgN3)) : true ) &&
+      ( ( 5 > dst::rank_dynamic && 5 > src::rank_dynamic ) ? (size_t(dst::ArgN4) == size_t(src::ArgN4)) : true ) &&
+      ( ( 6 > dst::rank_dynamic && 6 > src::rank_dynamic ) ? (size_t(dst::ArgN5) == size_t(src::ArgN5)) : true ) &&
+      ( ( 7 > dst::rank_dynamic && 7 > src::rank_dynamic ) ? (size_t(dst::ArgN6) == size_t(src::ArgN6)) : true ) &&
+      ( ( 8 > dst::rank_dynamic && 8 > src::rank_dynamic ) ? (size_t(dst::ArgN7) == size_t(src::ArgN7)) : true )
+    )};
+
+};
+
+}}} // namespace Kokkos::Experimental::Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+struct ALL_t {
+  KOKKOS_INLINE_FUNCTION
+  constexpr const ALL_t & operator()() const { return *this ; }
+};
+
+template< class T >
+struct is_integral_extent_type
+{ enum { value = std::is_same<T,Kokkos::Experimental::Impl::ALL_t>::value ? 1 : 0 }; };
+
+template< class iType >
+struct is_integral_extent_type< std::pair<iType,iType> >
+{ enum { value = std::is_integral<iType>::value ? 1 : 0 }; };
+
+template< class iType >
+struct is_integral_extent_type< Kokkos::pair<iType,iType> >
+{ enum { value = std::is_integral<iType>::value ? 1 : 0 }; };
+
+// Assuming '2 == initializer_list<iType>::size()'
+template< class iType >
+struct is_integral_extent_type< std::initializer_list<iType> >
+{ enum { value = std::is_integral<iType>::value ? 1 : 0 }; };
+
+template < unsigned I , class ... Args >
+struct is_integral_extent
+{
+  // get_type is void when sizeof...(Args) <= I
+  typedef typename std::remove_cv<
+          typename std::remove_reference<
+          typename Kokkos::Impl::get_type<I,Args...
+          >::type >::type >::type type ;
+
+  enum { value = is_integral_extent_type<type>::value };
+
+  static_assert( value ||
+                 std::is_integral<type>::value ||
+                 std::is_same<type,void>::value 
+               , "subview argument must be either integral or integral extent" );
+};
+
+template< unsigned DomainRank , unsigned RangeRank >
+struct SubviewExtents {
+private:
+
+  // Cannot declare zero-length arrays
+  enum { InternalRangeRank = RangeRank ? RangeRank : 1u };
+
+  size_t   m_begin[  DomainRank ];
+  size_t   m_length[ InternalRangeRank ];
+  unsigned m_index[  InternalRangeRank ];
+
+  template< size_t ... DimArgs >
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool set( unsigned domain_rank
+          , unsigned range_rank
+          , const ViewDimension< DimArgs ... > & dim )
+    { return true ; }
+
+  template< class T , size_t ... DimArgs , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool set( unsigned domain_rank
+          , unsigned range_rank
+          , const ViewDimension< DimArgs ... > & dim
+          , const T & val
+          , Args ... args )
+    {
+      const size_t v = static_cast<size_t>(val);
+
+      m_begin[ domain_rank ] = v ;
+
+      return set( domain_rank + 1 , range_rank , dim , args... )
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+             && ( v < dim.extent( domain_rank ) )
+#endif
+      ;
+    }
+
+  // ALL_t
+  template< size_t ... DimArgs , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool set( unsigned domain_rank
+          , unsigned range_rank
+          , const ViewDimension< DimArgs ... > & dim
+          , const Kokkos::Experimental::Impl::ALL_t 
+          , Args ... args )
+    {
+      m_begin[  domain_rank ] = 0 ;
+      m_length[ range_rank  ] = dim.extent( domain_rank );
+      m_index[  range_rank  ] = domain_rank ;
+
+      return set( domain_rank + 1 , range_rank + 1 , dim , args... );
+    }
+
+  // std::pair range
+  template< class T , size_t ... DimArgs , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool set( unsigned domain_rank
+          , unsigned range_rank
+          , const ViewDimension< DimArgs ... > & dim
+          , const std::pair<T,T> & val
+          , Args ... args )
+    {
+      const size_t b = static_cast<size_t>( val.first );
+      const size_t e = static_cast<size_t>( val.second );
+
+      m_begin[  domain_rank ] = b ;
+      m_length[ range_rank  ] = e - b ;
+      m_index[  range_rank  ] = domain_rank ;
+
+      return set( domain_rank + 1 , range_rank + 1 , dim , args... )
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+             && ( e <= b + dim.extent( domain_rank ) )
+#endif
+      ;
+    }
+
+  // Kokkos::pair range
+  template< class T , size_t ... DimArgs , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool set( unsigned domain_rank
+          , unsigned range_rank
+          , const ViewDimension< DimArgs ... > & dim
+          , const Kokkos::pair<T,T> & val
+          , Args ... args )
+    {
+      const size_t b = static_cast<size_t>( val.first );
+      const size_t e = static_cast<size_t>( val.second );
+
+      m_begin[  domain_rank ] = b ;
+      m_length[ range_rank  ] = e - b ;
+      m_index[  range_rank  ] = domain_rank ;
+
+      return set( domain_rank + 1 , range_rank + 1 , dim , args... )
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+             && ( e <= b + dim.extent( domain_rank ) )
+#endif
+      ;
+    }
+
+  // { begin , end } range
+  template< class T , size_t ... DimArgs , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  bool set( unsigned domain_rank
+          , unsigned range_rank
+          , const ViewDimension< DimArgs ... > & dim
+          , const std::initializer_list< T > & val
+          , Args ... args )
+    {
+      const size_t b = static_cast<size_t>( val.begin()[0] );
+      const size_t e = static_cast<size_t>( val.begin()[1] );
+
+      m_begin[  domain_rank ] = b ;
+      m_length[ range_rank  ] = e - b ;
+      m_index[  range_rank  ] = domain_rank ;
+
+      return set( domain_rank + 1 , range_rank + 1 , dim , args... )
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+             && ( val.size() == 2 )
+             && ( e <= b + dim.extent( domain_rank ) )
+#endif
+      ;
+    }
+
+  //------------------------------
+
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+
+  template< size_t ... DimArgs >
+  void error( char *
+            , int
+            , unsigned
+            , unsigned
+            , const ViewDimension< DimArgs ... > & ) const
+    {}
+
+  template< class T , size_t ... DimArgs , class ... Args >
+  void error( char * buf , int buf_len
+            , unsigned domain_rank
+            , unsigned range_rank
+            , const ViewDimension< DimArgs ... > & dim
+            , const T & val
+            , Args ... args ) const
+    {
+      const int n = std::min( buf_len ,
+        snprintf( buf , buf_len
+                , " %lu < %lu %c"
+                , static_cast<unsigned long>(val)
+                , static_cast<unsigned long>( dim.extent( domain_rank ) )
+                , int( sizeof...(Args) ? ',' : ')' ) ) );
+
+      error( buf+n, buf_len-n, domain_rank + 1 , range_rank , dim , args... );
+    }
+
+  // std::pair range
+  template< size_t ... DimArgs , class ... Args >
+  void error( char * buf , int buf_len
+            , unsigned domain_rank
+            , unsigned range_rank
+            , const ViewDimension< DimArgs ... > & dim
+            , const Kokkos::Experimental::Impl::ALL_t 
+            , Args ... args ) const
+    {
+      const int n = std::min( buf_len ,
+        snprintf( buf , buf_len
+                , " Kokkos::ALL %c" 
+                , int( sizeof...(Args) ? ',' : ')' ) ) );
+
+      error( buf+n , buf_len-n , domain_rank + 1 , range_rank + 1 , dim , args... );
+    }
+
+  // std::pair range
+  template< class T , size_t ... DimArgs , class ... Args >
+  void error( char * buf , int buf_len
+            , unsigned domain_rank
+            , unsigned range_rank
+            , const ViewDimension< DimArgs ... > & dim
+            , const std::pair<T,T> & val
+            , Args ... args ) const
+    {
+      // d <= e - b
+      const int n = std::min( buf_len ,
+        snprintf( buf , buf_len
+                , " %lu <= %lu - %lu %c"
+                , static_cast<unsigned long>( dim.extent( domain_rank ) )
+                , static_cast<unsigned long>( val.second )
+                , static_cast<unsigned long>( val.begin )
+                , int( sizeof...(Args) ? ',' : ')' ) ) );
+
+      error( buf+n , buf_len-n , domain_rank + 1 , range_rank + 1 , dim , args... );
+    }
+
+  // Kokkos::pair range
+  template< class T , size_t ... DimArgs , class ... Args >
+  void error( char * buf , int buf_len
+            , unsigned domain_rank
+            , unsigned range_rank
+            , const ViewDimension< DimArgs ... > & dim
+            , const Kokkos::pair<T,T> & val
+            , Args ... args ) const
+    {
+      // d <= e - b
+      const int n = std::min( buf_len ,
+        snprintf( buf , buf_len
+                , " %lu <= %lu - %lu %c"
+                , static_cast<unsigned long>( dim.extent( domain_rank ) )
+                , static_cast<unsigned long>( val.second )
+                , static_cast<unsigned long>( val.begin )
+                , int( sizeof...(Args) ? ',' : ')' ) ) );
+
+      error( buf+n , buf_len-n , domain_rank + 1 , range_rank + 1 , dim , args... );
+    }
+
+  // { begin , end } range
+  template< class T , size_t ... DimArgs , class ... Args >
+  void error( char * buf , int buf_len
+            , unsigned domain_rank
+            , unsigned range_rank
+            , const ViewDimension< DimArgs ... > & dim
+            , const std::initializer_list< T > & val
+            , Args ... args ) const
+    {
+      // d <= e - b
+      int n = 0 ;
+      if ( val.size() == 2 ) {
+        n = std::min( buf_len ,
+          snprintf( buf , buf_len
+                  , " %lu <= %lu - %lu %c"
+                  , static_cast<unsigned long>( dim.extent( domain_rank ) )
+                  , static_cast<unsigned long>( val.begin()[0] )
+                  , static_cast<unsigned long>( val.begin()[1] )
+                  , int( sizeof...(Args) ? ',' : ')' ) ) );
+      }
+      else {
+        n = std::min( buf_len ,
+          snprintf( buf , buf_len
+                  , " { ... }.size() == %u %c"
+                  , unsigned(val.size())
+                  , int( sizeof...(Args) ? ',' : ')' ) ) );
+      }
+
+      error( buf+n , buf_len-n , domain_rank + 1 , range_rank + 1 , dim , args... );
+    }
+
+  template< size_t ... DimArgs , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  void error( const ViewDimension< DimArgs ... > & dim , Args ... args ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_SPACE_HOST )
+      enum { LEN = 1024 };
+      char buffer[ LEN ];
+
+      const int n = snprintf(buffer,LEN,"Kokkos::subview bounds error (");
+      error( buffer+n , LEN-n , 0 , 0 , dim , args... );
+
+      Kokkos::Impl::throw_runtime_exception(std::string(buffer));
+#else
+      Kokkos::abort("Kokkos::subview bounds error");
+#endif
+    }
+
+#else
+
+  template< size_t ... DimArgs , class ... Args >
+  KOKKOS_FORCEINLINE_FUNCTION
+  void error( const ViewDimension< DimArgs ... > & , Args ... ) const {}
+
+#endif
+
+public:
+
+  template< size_t ... DimArgs , class ... Args >
+  KOKKOS_INLINE_FUNCTION
+  SubviewExtents( const ViewDimension< DimArgs ... > & dim , Args ... args )
+    {
+      static_assert( DomainRank == sizeof...(DimArgs) , "" );
+      static_assert( DomainRank == sizeof...(Args) , "" );
+
+      // Verifies that all arguments, up to 8, are integral types,
+      // integral extents, or don't exist.
+      static_assert( RangeRank ==
+        unsigned( is_integral_extent<0,Args...>::value ) +
+        unsigned( is_integral_extent<1,Args...>::value ) +
+        unsigned( is_integral_extent<2,Args...>::value ) +
+        unsigned( is_integral_extent<3,Args...>::value ) +
+        unsigned( is_integral_extent<4,Args...>::value ) +
+        unsigned( is_integral_extent<5,Args...>::value ) +
+        unsigned( is_integral_extent<6,Args...>::value ) +
+        unsigned( is_integral_extent<7,Args...>::value ) , "" );
+
+      if ( RangeRank == 0 ) { m_length[0] = 0 ; m_index[0] = ~0u ; }
+
+      if ( ! set( 0 , 0 , dim , args... ) ) error( dim , args... );
+    }
+
+  template < typename iType >
+  KOKKOS_FORCEINLINE_FUNCTION
+  constexpr size_t domain_offset( const iType i ) const
+    { return unsigned(i) < DomainRank ? m_begin[i] : 0 ; }
+
+  template < typename iType >
+  KOKKOS_FORCEINLINE_FUNCTION
+  constexpr size_t range_extent( const iType i ) const
+    { return unsigned(i) < InternalRangeRank ? m_length[i] : 0 ; }
+
+  template < typename iType >
+  KOKKOS_FORCEINLINE_FUNCTION
+  constexpr unsigned range_index( const iType i ) const
+    { return unsigned(i) < InternalRangeRank ? m_index[i] : ~0u ; }
+};
+
+}}} // namespace Kokkos::Experimental::Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+/** \brief  Given a value type and dimension generate the View data type */
+template< class T , class Dim >
+struct ViewDataType ;
+
+template< class T >
+struct ViewDataType< T , ViewDimension<> >
+{
+  typedef T type ;
+};
+
+template< class T , size_t ... Args >
+struct ViewDataType< T , ViewDimension< 0 , Args... > >
+{
+  typedef typename ViewDataType<T*,ViewDimension<Args...> >::type type ;
+};
+
+template< class T , size_t N , size_t ... Args >
+struct ViewDataType< T , ViewDimension< N , Args... > >
+{
+  typedef typename ViewDataType<T,ViewDimension<Args...> >::type type[N] ;
+};
+
+/**\brief  Analysis of View data type.
+ *
+ *  Data type conforms to one of the following patterns :
+ *    {const} value_type [][#][#][#]
+ *    {const} value_type ***[#][#][#]
+ *  Where the sum of counts of '*' and '[#]' is at most ten.
+ *
+ *  Provide typedef for the ViewDimension<...> and value_type.
+ */
+template< class T >
+struct ViewArrayAnalysis 
+{
+  typedef T                                      value_type ;
+  typedef typename std::add_const<    T >::type  const_value_type ;
+  typedef typename std::remove_const< T >::type  non_const_value_type ;
+  typedef ViewDimension<>                        static_dimension ;
+  typedef ViewDimension<>                        dynamic_dimension ;
+  typedef ViewDimension<>                        dimension ;
+};
+
+template< class T , size_t N >
+struct ViewArrayAnalysis< T[N] >
+{
+private:
+  typedef ViewArrayAnalysis< T > nested ;
+public:
+  typedef typename nested::value_type            value_type ;
+  typedef typename nested::const_value_type      const_value_type ;
+  typedef typename nested::non_const_value_type  non_const_value_type ;
+
+  typedef typename nested::static_dimension::template prepend<N>::type
+    static_dimension ;
+
+  typedef typename nested::dynamic_dimension dynamic_dimension ;
+
+  typedef typename
+    ViewDimensionJoin< dynamic_dimension , static_dimension >::type
+      dimension ;
+};
+
+template< class T >
+struct ViewArrayAnalysis< T[] >
+{
+private:
+  typedef ViewArrayAnalysis< T > nested ;
+  typedef typename nested::dimension nested_dimension ;
+public:
+  typedef typename nested::value_type            value_type ;
+  typedef typename nested::const_value_type      const_value_type ;
+  typedef typename nested::non_const_value_type  non_const_value_type ;
+
+  typedef typename nested::dynamic_dimension::template prepend<0>::type
+    dynamic_dimension ;
+
+  typedef typename nested::static_dimension static_dimension ;
+
+  typedef typename
+    ViewDimensionJoin< dynamic_dimension , static_dimension >::type
+      dimension ;
+};
+
+template< class T >
+struct ViewArrayAnalysis< T* >
+{
+private:
+  typedef ViewArrayAnalysis< T > nested ;
+public:
+  typedef typename nested::value_type            value_type ;
+  typedef typename nested::const_value_type      const_value_type ;
+  typedef typename nested::non_const_value_type  non_const_value_type ;
+
+  typedef typename nested::dynamic_dimension::template prepend<0>::type
+    dynamic_dimension ;
+
+  typedef typename nested::static_dimension static_dimension ;
+
+  typedef typename
+    ViewDimensionJoin< dynamic_dimension , static_dimension >::type
+      dimension ;
+};
+
+
+template< class DataType , class ArrayLayout , class ValueType >
+struct ViewDataAnalysis
+{
+private:
+
+  typedef ViewArrayAnalysis< DataType > array_analysis ;
+
+  // ValueType is opportunity for partial specialization.
+  // Must match array analysis when this default template is used.
+  static_assert( std::is_same< ValueType , typename array_analysis::non_const_value_type >::value , "" );
+
+public:
+
+  typedef void specialize ; // No specialization
+
+  typedef typename array_analysis::dimension             dimension ;
+  typedef typename array_analysis::value_type            value_type ;
+  typedef typename array_analysis::const_value_type      const_value_type ;
+  typedef typename array_analysis::non_const_value_type  non_const_value_type ;
+
+  // Generate analogous multidimensional array specification type.
+  typedef typename ViewDataType<           value_type , dimension >::type  type ;
+  typedef typename ViewDataType<     const_value_type , dimension >::type  const_type ;
+  typedef typename ViewDataType< non_const_value_type , dimension >::type  non_const_type ;
+
+  // Generate "flattened" multidimensional array specification type.
+  typedef type            scalar_array_type ;
+  typedef const_type      const_scalar_array_type ;
+  typedef non_const_type  non_const_scalar_array_type ;
+};
+
+}}} // namespace Kokkos::Experimental::Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template < class Dimension , class Layout , typename Enable = void >
+struct ViewOffset {
+  using is_mapping_plugin = std::false_type ;
+};
+
+//----------------------------------------------------------------------------
+// LayoutLeft AND ( 1 >= rank OR 0 == rank_dynamic ) : no padding / striding
+template < class Dimension >
+struct ViewOffset< Dimension , Kokkos::LayoutLeft
+                 , typename std::enable_if<( 1 >= Dimension::rank
+                                             ||
+                                             0 == Dimension::rank_dynamic
+                                           )>::type >
+{
+  using is_mapping_plugin = std::true_type ;
+  using is_regular        = std::true_type ;
+
+  typedef size_t             size_type ;
+  typedef Dimension          dimension_type ;
+  typedef Kokkos::LayoutLeft array_layout ;
+
+  dimension_type m_dim ;
+
+  //----------------------------------------
+
+  // rank 1
+  template< typename I0 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 ) const { return i0 ; }
+
+  // rank 2
+  template < typename I0 , typename I1 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 , I1 const & i1 ) const
+    { return i0 + m_dim.N0 * i1 ; }
+
+  //rank 3
+  template < typename I0, typename I1, typename I2 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
+  {
+    return i0 + m_dim.N0 * ( i1 + m_dim.N1 * i2 );
+  }
+
+  //rank 4
+  template < typename I0, typename I1, typename I2, typename I3 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
+  {
+    return i0 + m_dim.N0 * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * i3 ));
+  }
+
+  //rank 5
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4 ) const
+  {
+    return i0 + m_dim.N0 * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * (
+           i3 + m_dim.N3 * i4 )));
+  }
+
+  //rank 6
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5 ) const
+  {
+    return i0 + m_dim.N0 * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * (
+           i3 + m_dim.N3 * (
+           i4 + m_dim.N4 * i5 ))));
+  }
+
+  //rank 7
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6 ) const
+  {
+    return i0 + m_dim.N0 * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * (
+           i3 + m_dim.N3 * (
+           i4 + m_dim.N4 * (
+           i5 + m_dim.N5 * i6 )))));
+  }
+
+  //rank 8
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
+  {
+    return i0 + m_dim.N0 * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * (
+           i3 + m_dim.N3 * (
+           i4 + m_dim.N4 * (
+           i5 + m_dim.N5 * (
+           i6 + m_dim.N6 * i7 ))))));
+  }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr array_layout layout() const
+    {
+      return array_layout( m_dim.N0 , m_dim.N1 , m_dim.N2 , m_dim.N3
+                         , m_dim.N4 , m_dim.N5 , m_dim.N6 , m_dim.N7 );
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
+
+  /* Cardinality of the domain index space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type size() const
+    { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
+
+  /* Span of the range space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type span() const
+    { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
+
+  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return true ; }
+
+  /* Strides of dimensions */
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_dim.N0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_dim.N0 * m_dim.N1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 ; }
+
+  // Stride with [ rank ] value is the total length
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      s[0] = 1 ;
+      if ( 0 < dimension_type::rank ) { s[1] = m_dim.N0 ; }
+      if ( 1 < dimension_type::rank ) { s[2] = s[1] * m_dim.N1 ; }
+      if ( 2 < dimension_type::rank ) { s[3] = s[2] * m_dim.N2 ; }
+      if ( 3 < dimension_type::rank ) { s[4] = s[3] * m_dim.N3 ; }
+      if ( 4 < dimension_type::rank ) { s[5] = s[4] * m_dim.N4 ; }
+      if ( 5 < dimension_type::rank ) { s[6] = s[5] * m_dim.N5 ; }
+      if ( 6 < dimension_type::rank ) { s[7] = s[6] * m_dim.N6 ; }
+      if ( 7 < dimension_type::rank ) { s[8] = s[7] * m_dim.N7 ; }
+    }
+
+  //----------------------------------------
+
+  ViewOffset() = default ;
+  ViewOffset( const ViewOffset & ) = default ;
+  ViewOffset & operator = ( const ViewOffset & ) = default ;
+
+  template< unsigned TrivialScalarSize >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset
+    ( std::integral_constant<unsigned,TrivialScalarSize> const &
+    , Kokkos::LayoutLeft const & arg_layout
+    )
+    : m_dim( arg_layout.dimension[0], 0, 0, 0, 0, 0, 0, 0 )
+    {}
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs )
+    : m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3 
+           , rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
+    {
+      static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
+      // Also requires equal static dimensions ...
+    } 
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs )
+    : m_dim( rhs.m_dim.N0, 0, 0, 0, 0, 0, 0, 0 )
+    {
+      static_assert( DimRHS::rank == 1 && dimension_type::rank == 1 && dimension_type::rank_dynamic == 1
+                   , "ViewOffset LayoutLeft and LayoutRight are only compatible when rank == 1" );
+    }
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutStride , void > & rhs )
+    : m_dim( rhs.m_dim.N0, 0, 0, 0, 0, 0, 0, 0 )
+    {
+      static_assert( DimRHS::rank == 1 && dimension_type::rank == 1 && dimension_type::rank_dynamic == 1
+                   , "ViewOffset LayoutLeft and LayoutStride are only compatible when rank == 1" );
+      if ( rhs.m_stride.S0 != 1 ) {
+        Kokkos::abort("Kokkos::Experimental::ViewOffset assignment of LayoutLeft from LayoutStride  requires stride == 1" );
+      }
+    }
+
+  //----------------------------------------
+  // Subview construction
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset(
+    const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs ,
+    const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub )
+    : m_dim( sub.range_extent(0), 0, 0, 0, 0, 0, 0, 0 )
+    {
+      static_assert( ( 0 == dimension_type::rank ) ||
+                     ( 1 == dimension_type::rank && 1 == dimension_type::rank_dynamic && 1 <= DimRHS::rank )
+                   , "ViewOffset subview construction requires compatible rank" );
+    }
+};
+
+//----------------------------------------------------------------------------
+// LayoutLeft AND ( 1 < rank AND 0 < rank_dynamic ) : has padding / striding
+template < class Dimension >
+struct ViewOffset< Dimension , Kokkos::LayoutLeft
+                 , typename std::enable_if<( 1 < Dimension::rank
+                                             &&
+                                             0 < Dimension::rank_dynamic
+                                           )>::type >
+{
+  using is_mapping_plugin = std::true_type ;
+  using is_regular        = std::true_type ;
+
+  typedef size_t             size_type ;
+  typedef Dimension          dimension_type ;
+  typedef Kokkos::LayoutLeft array_layout ;
+
+  dimension_type m_dim ;
+  size_type      m_stride ;
+
+  //----------------------------------------
+
+  // rank 1
+  template< typename I0 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 ) const { return i0 ; }
+
+  // rank 2
+  template < typename I0 , typename I1 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 , I1 const & i1 ) const
+    { return i0 + m_stride * i1 ; }
+
+  //rank 3
+  template < typename I0, typename I1, typename I2 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
+  {
+    return i0 + m_stride * ( i1 + m_dim.N1 * i2 );
+  }
+
+  //rank 4
+  template < typename I0, typename I1, typename I2, typename I3 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
+  {
+    return i0 + m_stride * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * i3 ));
+  }
+
+  //rank 5
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4 ) const
+  {
+    return i0 + m_stride * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * (
+           i3 + m_dim.N3 * i4 )));
+  }
+
+  //rank 6
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5 ) const
+  {
+    return i0 + m_stride * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * (
+           i3 + m_dim.N3 * (
+           i4 + m_dim.N4 * i5 ))));
+  }
+
+  //rank 7
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6 ) const
+  {
+    return i0 + m_stride * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * (
+           i3 + m_dim.N3 * (
+           i4 + m_dim.N4 * (
+           i5 + m_dim.N5 * i6 )))));
+  }
+
+  //rank 8
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
+  {
+    return i0 + m_stride * (
+           i1 + m_dim.N1 * (
+           i2 + m_dim.N2 * (
+           i3 + m_dim.N3 * (
+           i4 + m_dim.N4 * (
+           i5 + m_dim.N5 * (
+           i6 + m_dim.N6 * i7 ))))));
+  }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr array_layout layout() const
+    {
+      return array_layout( m_dim.N0 , m_dim.N1 , m_dim.N2 , m_dim.N3
+                         , m_dim.N4 , m_dim.N5 , m_dim.N6 , m_dim.N7 );
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
+
+  /* Cardinality of the domain index space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type size() const
+    { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
+
+  /* Span of the range space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type span() const
+    { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
+
+  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return m_stride == m_dim.N0 ; }
+
+  /* Strides of dimensions */
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_stride ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_stride * m_dim.N1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_stride * m_dim.N1 * m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return m_stride * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 ; }
+
+  // Stride with [ rank ] value is the total length
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      s[0] = 1 ;
+      if ( 0 < dimension_type::rank ) { s[1] = m_stride ; }
+      if ( 1 < dimension_type::rank ) { s[2] = s[1] * m_dim.N1 ; }
+      if ( 2 < dimension_type::rank ) { s[3] = s[2] * m_dim.N2 ; }
+      if ( 3 < dimension_type::rank ) { s[4] = s[3] * m_dim.N3 ; }
+      if ( 4 < dimension_type::rank ) { s[5] = s[4] * m_dim.N4 ; }
+      if ( 5 < dimension_type::rank ) { s[6] = s[5] * m_dim.N5 ; }
+      if ( 6 < dimension_type::rank ) { s[7] = s[6] * m_dim.N6 ; }
+      if ( 7 < dimension_type::rank ) { s[8] = s[7] * m_dim.N7 ; }
+    }
+
+  //----------------------------------------
+
+private:
+
+  template< unsigned TrivialScalarSize >
+  struct Padding {
+    enum { div = TrivialScalarSize == 0 ? 0 : Kokkos::Impl::MEMORY_ALIGNMENT / ( TrivialScalarSize ? TrivialScalarSize : 1 ) };
+    enum { mod = TrivialScalarSize == 0 ? 0 : Kokkos::Impl::MEMORY_ALIGNMENT % ( TrivialScalarSize ? TrivialScalarSize : 1 ) };
+
+    // If memory alignment is a multiple of the trivial scalar size then attempt to align.
+    enum { align = 0 != TrivialScalarSize && 0 == mod ? div : 0 };
+    enum { div_ok = div ? div : 1 }; // To valid modulo zero in constexpr
+
+    KOKKOS_INLINE_FUNCTION
+    static constexpr size_t stride( size_t const N )
+      {
+        return ( align && ( Kokkos::Impl::MEMORY_ALIGNMENT_THRESHOLD * align < N ) && ( N % div_ok ) )
+               ? N + align - ( N % div_ok ) : N ;
+      }
+  };
+
+public:
+
+  ViewOffset() = default ;
+  ViewOffset( const ViewOffset & ) = default ;
+  ViewOffset & operator = ( const ViewOffset & ) = default ;
+
+  /* Enable padding for trivial scalar types with non-zero trivial scalar size */
+  template< unsigned TrivialScalarSize >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset
+    ( std::integral_constant<unsigned,TrivialScalarSize> const & padding_type_size
+    , Kokkos::LayoutLeft const & arg_layout
+    )
+    : m_dim( arg_layout.dimension[0] , arg_layout.dimension[1]
+           , arg_layout.dimension[2] , arg_layout.dimension[3]
+           , arg_layout.dimension[4] , arg_layout.dimension[5]
+           , arg_layout.dimension[6] , arg_layout.dimension[7]
+           )
+    , m_stride( Padding<TrivialScalarSize>::stride( arg_layout.dimension[0] ) )
+    {}
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs )
+    : m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3 
+           , rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
+    , m_stride( rhs.stride_1() )
+    {
+      static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
+      // Also requires equal static dimensions ...
+    } 
+
+  //----------------------------------------
+  // Subview construction
+  // This subview must be 2 == rank and 2 == rank_dynamic
+  // due to only having stride #0.
+  // The source dimension #0 must be non-zero for stride-one leading dimension.
+  // At most subsequent dimension can be non-zero.
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset
+    ( const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs ,
+      const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub )
+    : m_dim( sub.range_extent(0)
+           , sub.range_extent(1)
+           , 0, 0, 0, 0, 0, 0 )
+    , m_stride( ( 1 == sub.range_index(1) ? rhs.stride_1() :
+                ( 2 == sub.range_index(1) ? rhs.stride_2() :
+                ( 3 == sub.range_index(1) ? rhs.stride_3() :
+                ( 4 == sub.range_index(1) ? rhs.stride_4() :
+                ( 5 == sub.range_index(1) ? rhs.stride_5() :
+                ( 6 == sub.range_index(1) ? rhs.stride_6() :
+                ( 7 == sub.range_index(1) ? rhs.stride_7() : 0 ))))))))
+    {
+      static_assert( ( 2 == dimension_type::rank ) &&
+                     ( 2 == dimension_type::rank_dynamic ) &&
+                     ( 2 <= DimRHS::rank )
+                   , "ViewOffset subview construction requires compatible rank" );
+    }
+};
+
+//----------------------------------------------------------------------------
+// LayoutRight AND ( 1 >= rank OR 0 == rank_dynamic ) : no padding / striding
+template < class Dimension >
+struct ViewOffset< Dimension , Kokkos::LayoutRight
+                 , typename std::enable_if<( 1 >= Dimension::rank
+                                             ||
+                                             0 == Dimension::rank_dynamic
+                                           )>::type >
+{
+  using is_mapping_plugin = std::true_type ;
+  using is_regular        = std::true_type ;
+
+  typedef size_t              size_type ;
+  typedef Dimension           dimension_type ;
+  typedef Kokkos::LayoutRight array_layout ;
+
+  dimension_type m_dim ;
+
+  //----------------------------------------
+
+  // rank 1
+  template< typename I0 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 ) const { return i0 ; }
+
+  // rank 2
+  template < typename I0 , typename I1 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 , I1 const & i1 ) const
+    { return i1 + m_dim.N1 * i0 ; }
+
+  //rank 3
+  template < typename I0, typename I1, typename I2 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
+  {
+    return i2 + m_dim.N2 * ( i1 + m_dim.N1 * ( i0 ));
+  }
+
+  //rank 4
+  template < typename I0, typename I1, typename I2, typename I3 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
+  {
+    return i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * (
+           i1 + m_dim.N1 * ( i0 )));
+  }
+
+  //rank 5
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4 ) const
+  {
+    return i4 + m_dim.N4 * (
+           i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * (
+           i1 + m_dim.N1 * ( i0 ))));
+  }
+
+  //rank 6
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5 ) const
+  {
+    return i5 + m_dim.N5 * (
+           i4 + m_dim.N4 * (
+           i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * (
+           i1 + m_dim.N1 * ( i0 )))));
+  }
+
+  //rank 7
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6 ) const
+  {
+    return i6 + m_dim.N6 * (
+           i5 + m_dim.N5 * (
+           i4 + m_dim.N4 * (
+           i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * (
+           i1 + m_dim.N1 * ( i0 ))))));
+  }
+
+  //rank 8
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
+  {
+    return i7 + m_dim.N7 * (
+           i6 + m_dim.N6 * (
+           i5 + m_dim.N5 * (
+           i4 + m_dim.N4 * (
+           i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * (
+           i1 + m_dim.N1 * ( i0 )))))));
+  }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr array_layout layout() const
+    {
+      return array_layout( m_dim.N0 , m_dim.N1 , m_dim.N2 , m_dim.N3
+                         , m_dim.N4 , m_dim.N5 , m_dim.N6 , m_dim.N7 );
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
+
+  /* Cardinality of the domain index space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type size() const
+    { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
+
+  /* Span of the range space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type span() const
+    { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
+
+  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return true ; }
+
+  /* Strides of dimensions */
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_dim.N7 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_dim.N7 * m_dim.N6 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 * m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 * m_dim.N2 * m_dim.N1 ; }
+
+  // Stride with [ rank ] value is the total length
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      size_type n = 1 ;
+      if ( 7 < dimension_type::rank ) { s[7] = n ; n *= m_dim.N7 ; }
+      if ( 6 < dimension_type::rank ) { s[6] = n ; n *= m_dim.N6 ; }
+      if ( 5 < dimension_type::rank ) { s[5] = n ; n *= m_dim.N5 ; }
+      if ( 4 < dimension_type::rank ) { s[4] = n ; n *= m_dim.N4 ; }
+      if ( 3 < dimension_type::rank ) { s[3] = n ; n *= m_dim.N3 ; }
+      if ( 2 < dimension_type::rank ) { s[2] = n ; n *= m_dim.N2 ; }
+      if ( 1 < dimension_type::rank ) { s[1] = n ; n *= m_dim.N1 ; }
+      if ( 0 < dimension_type::rank ) { s[0] = n ; }
+      s[dimension_type::rank] = n * m_dim.N0 ;
+    }
+
+  //----------------------------------------
+
+  ViewOffset() = default ;
+  ViewOffset( const ViewOffset & ) = default ;
+  ViewOffset & operator = ( const ViewOffset & ) = default ;
+
+  template< unsigned TrivialScalarSize >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset
+    ( std::integral_constant<unsigned,TrivialScalarSize> const &
+    , Kokkos::LayoutRight const & arg_layout
+    )
+    : m_dim( arg_layout.dimension[0], 0, 0, 0, 0, 0, 0, 0 )
+    {}
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs )
+    : m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3 
+           , rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
+    {
+      static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
+      // Also requires equal static dimensions ...
+    } 
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutLeft , void > & rhs )
+    : m_dim( rhs.m_dim.N0, 0, 0, 0, 0, 0, 0, 0 )
+    {
+      static_assert( DimRHS::rank == 1 && dimension_type::rank == 1 && dimension_type::rank_dynamic == 1
+                   , "ViewOffset LayoutRight and LayoutLeft are only compatible when rank == 1" );
+    }
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutStride , void > & rhs )
+    : m_dim( rhs.m_dim.N0, 0, 0, 0, 0, 0, 0, 0 )
+    {
+      static_assert( DimRHS::rank == 1 && dimension_type::rank == 1 && dimension_type::rank_dynamic == 1
+                   , "ViewOffset LayoutLeft/Right and LayoutStride are only compatible when rank == 1" );
+      if ( rhs.m_stride.S0 != 1 ) {
+        Kokkos::abort("Kokkos::Experimental::ViewOffset assignment of LayoutLeft/Right from LayoutStride  requires stride == 1" );
+      }
+    }
+
+  //----------------------------------------
+  // Subview construction
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset
+    ( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs
+    , const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub
+    )
+    : m_dim( sub.range_extent(0) , 0, 0, 0, 0, 0, 0, 0 )
+    {
+      static_assert( ( 0 == dimension_type::rank_dynamic ) ||
+                     ( 1 == dimension_type::rank && 1 == dimension_type::rank_dynamic && 1 <= DimRHS::rank )
+                   , "ViewOffset subview construction requires compatible rank" );
+    }
+};
+
+//----------------------------------------------------------------------------
+// LayoutRight AND ( 1 < rank AND 0 < rank_dynamic ) : has padding / striding
+template < class Dimension >
+struct ViewOffset< Dimension , Kokkos::LayoutRight
+                 , typename std::enable_if<( 1 < Dimension::rank
+                                             &&
+                                             0 < Dimension::rank_dynamic
+                                           )>::type >
+{
+  using is_mapping_plugin = std::true_type ;
+  using is_regular        = std::true_type ;
+
+  typedef size_t               size_type ;
+  typedef Dimension            dimension_type ;
+  typedef Kokkos::LayoutRight  array_layout ;
+
+  dimension_type m_dim ;
+  size_type      m_stride ;
+
+  //----------------------------------------
+
+  // rank 1
+  template< typename I0 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 ) const { return i0 ; }
+
+  // rank 2
+  template < typename I0 , typename I1 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 , I1 const & i1 ) const
+  { return i1 + i0 * m_stride ; }
+
+  //rank 3
+  template < typename I0, typename I1, typename I2 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
+  { return i2 + m_dim.N2 * ( i1 ) + i0 * m_stride ; }
+
+  //rank 4
+  template < typename I0, typename I1, typename I2, typename I3 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
+  {
+    return i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * ( i1 )) +
+           i0 * m_stride ;
+  }
+
+  //rank 5
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4 ) const
+  {
+    return i4 + m_dim.N4 * (
+           i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * ( i1 ))) +
+           i0 * m_stride ;
+  }
+
+  //rank 6
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5 ) const
+  {
+    return i5 + m_dim.N5 * (
+           i4 + m_dim.N4 * (
+           i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * ( i1 )))) +
+           i0 * m_stride ;
+  }
+
+  //rank 7
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6 ) const
+  {
+    return i6 + m_dim.N6 * (
+           i5 + m_dim.N5 * (
+           i4 + m_dim.N4 * (
+           i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * ( i1 ))))) +
+           i0 * m_stride ;
+  }
+
+  //rank 8
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
+  {
+    return i7 + m_dim.N7 * (
+           i6 + m_dim.N6 * (
+           i5 + m_dim.N5 * (
+           i4 + m_dim.N4 * (
+           i3 + m_dim.N3 * (
+           i2 + m_dim.N2 * ( i1 )))))) +
+           i0 * m_stride ;
+  }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr array_layout layout() const
+    {
+      return array_layout( m_dim.N0 , m_dim.N1 , m_dim.N2 , m_dim.N3
+                         , m_dim.N4 , m_dim.N5 , m_dim.N6 , m_dim.N7 );
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
+
+  /* Cardinality of the domain index space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type size() const
+    { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
+
+  /* Span of the range space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type span() const
+    { return m_dim.N0 * m_stride ; }
+
+  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const
+    { return m_stride == m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 * m_dim.N2 * m_dim.N1 ; }
+
+  /* Strides of dimensions */
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_dim.N7 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_dim.N7 * m_dim.N6 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_dim.N7 * m_dim.N6 * m_dim.N5 * m_dim.N4 * m_dim.N3 * m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return m_stride ; }
+
+  // Stride with [ rank ] value is the total length
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      size_type n = 1 ;
+      if ( 7 < dimension_type::rank ) { s[7] = n ; n *= m_dim.N7 ; }
+      if ( 6 < dimension_type::rank ) { s[6] = n ; n *= m_dim.N6 ; }
+      if ( 5 < dimension_type::rank ) { s[5] = n ; n *= m_dim.N5 ; }
+      if ( 4 < dimension_type::rank ) { s[4] = n ; n *= m_dim.N4 ; }
+      if ( 3 < dimension_type::rank ) { s[3] = n ; n *= m_dim.N3 ; }
+      if ( 2 < dimension_type::rank ) { s[2] = n ; n *= m_dim.N2 ; }
+      if ( 1 < dimension_type::rank ) { s[1] = n ; }
+      if ( 0 < dimension_type::rank ) { s[0] = m_stride ; }
+      s[dimension_type::rank] = m_stride * m_dim.N0 ;
+    }
+
+  //----------------------------------------
+
+private:
+
+  template< unsigned TrivialScalarSize >
+  struct Padding {
+    enum { div = TrivialScalarSize == 0 ? 0 : Kokkos::Impl::MEMORY_ALIGNMENT / ( TrivialScalarSize ? TrivialScalarSize : 1 ) };
+    enum { mod = TrivialScalarSize == 0 ? 0 : Kokkos::Impl::MEMORY_ALIGNMENT % ( TrivialScalarSize ? TrivialScalarSize : 1 ) };
+
+    // If memory alignment is a multiple of the trivial scalar size then attempt to align.
+    enum { align = 0 != TrivialScalarSize && 0 == mod ? div : 0 };
+    enum { div_ok = div ? div : 1 }; // To valid modulo zero in constexpr
+
+    KOKKOS_INLINE_FUNCTION
+    static constexpr size_t stride( size_t const N )
+    {
+      return ( align && ( Kokkos::Impl::MEMORY_ALIGNMENT_THRESHOLD * align < N ) && ( N % div_ok ) )
+             ? N + align - ( N % div_ok ) : N ;
+    }
+  };
+
+public:
+
+  ViewOffset() = default ;
+  ViewOffset( const ViewOffset & ) = default ;
+  ViewOffset & operator = ( const ViewOffset & ) = default ;
+
+  /* Enable padding for trivial scalar types with non-zero trivial scalar size.  */
+  template< unsigned TrivialScalarSize >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset
+    ( std::integral_constant<unsigned,TrivialScalarSize> const & padding_type_size
+    , Kokkos::LayoutRight const & arg_layout
+    )
+    : m_dim( arg_layout.dimension[0] , arg_layout.dimension[1]
+           , arg_layout.dimension[2] , arg_layout.dimension[3]
+           , arg_layout.dimension[4] , arg_layout.dimension[5]
+           , arg_layout.dimension[6] , arg_layout.dimension[7]
+           )
+    , m_stride( Padding<TrivialScalarSize>::
+                  stride( /* 2 <= rank */
+                          m_dim.N1 * ( dimension_type::rank == 2 ? 1 :
+                          m_dim.N2 * ( dimension_type::rank == 3 ? 1 :
+                          m_dim.N3 * ( dimension_type::rank == 4 ? 1 :
+                          m_dim.N4 * ( dimension_type::rank == 5 ? 1 :
+                          m_dim.N5 * ( dimension_type::rank == 6 ? 1 :
+                          m_dim.N6 * ( dimension_type::rank == 7 ? 1 : m_dim.N7 )))))) ))
+    {}
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs )
+    : m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3 
+           , rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
+    , m_stride( rhs.stride_0() )
+    {
+      static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
+      // Also requires equal static dimensions ...
+    } 
+
+  //----------------------------------------
+  // Subview construction
+  // Last dimension must be non-zero
+
+  template< class DimRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset
+    ( const ViewOffset< DimRHS , Kokkos::LayoutRight , void > & rhs
+    , const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub
+    )
+    : m_dim( sub.range_extent(0)
+           , sub.range_extent(1)
+           , 0, 0, 0, 0, 0, 0 ) 
+    , m_stride( 0 == sub.range_index(0) ? rhs.stride_0() : (
+                1 == sub.range_index(0) ? rhs.stride_1() : (
+                2 == sub.range_index(0) ? rhs.stride_2() : (
+                3 == sub.range_index(0) ? rhs.stride_3() : (
+                4 == sub.range_index(0) ? rhs.stride_4() : (
+                5 == sub.range_index(0) ? rhs.stride_5() : (
+                6 == sub.range_index(0) ? rhs.stride_6() : 0 )))))))
+    {
+      // This subview must be 2 == rank and 2 == rank_dynamic
+      // due to only having stride #0.
+      // The source dimension #0 must be non-zero for stride-one leading dimension.
+      // At most subsequent dimension can be non-zero.
+
+      static_assert( ( 2 == dimension_type::rank ) &&
+                     ( 2 <= DimRHS::rank )
+                   , "ViewOffset subview construction requires compatible rank" );
+    }
+};
+
+//----------------------------------------------------------------------------
+/* Strided array layout only makes sense for 0 < rank */
+/* rank = 0 included for DynRankView case */
+
+template< unsigned Rank >
+struct ViewStride ;
+
+template<>
+struct ViewStride<0> {
+  enum { S0 = 0 , S1 = 0 , S2 = 0 , S3 = 0 , S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t , size_t , size_t , size_t
+                      , size_t , size_t , size_t , size_t )
+    {}
+};
+
+template<>
+struct ViewStride<1> {
+  size_t S0 ;
+  enum { S1 = 0 , S2 = 0 , S3 = 0 , S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t aS0 , size_t , size_t , size_t
+                      , size_t , size_t , size_t , size_t )
+    : S0( aS0 )
+    {}
+};
+
+template<>
+struct ViewStride<2> {
+  size_t S0 , S1 ;
+  enum { S2 = 0 , S3 = 0 , S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t aS0 , size_t aS1 , size_t , size_t
+                      , size_t , size_t , size_t , size_t )
+    : S0( aS0 ) , S1( aS1 )
+    {}
+};
+
+template<>
+struct ViewStride<3> {
+  size_t S0 , S1 , S2 ;
+  enum { S3 = 0 , S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t
+                      , size_t , size_t , size_t , size_t )
+    : S0( aS0 ) , S1( aS1 ) , S2( aS2 )
+    {}
+};
+
+template<>
+struct ViewStride<4> {
+  size_t S0 , S1 , S2 , S3 ;
+  enum { S4 = 0 , S5 = 0 , S6 = 0 , S7 = 0 };
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
+                      , size_t , size_t , size_t , size_t )
+    : S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
+    {}
+};
+
+template<>
+struct ViewStride<5> {
+  size_t S0 , S1 , S2 , S3 , S4 ;
+  enum { S5 = 0 , S6 = 0 , S7 = 0 };
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
+                      , size_t aS4 , size_t , size_t , size_t )
+    : S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
+    , S4( aS4 )
+    {}
+};
+
+template<>
+struct ViewStride<6> {
+  size_t S0 , S1 , S2 , S3 , S4 , S5 ;
+  enum { S6 = 0 , S7 = 0 };
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
+                      , size_t aS4 , size_t aS5 , size_t , size_t )
+    : S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
+    , S4( aS4 ) , S5( aS5 )
+    {}
+};
+
+template<>
+struct ViewStride<7> {
+  size_t S0 , S1 , S2 , S3 , S4 , S5 , S6 ;
+  enum { S7 = 0 };
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
+                      , size_t aS4 , size_t aS5 , size_t aS6 , size_t )
+    : S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
+    , S4( aS4 ) , S5( aS5 ) , S6( aS6 )
+    {}
+};
+
+template<>
+struct ViewStride<8> {
+  size_t S0 , S1 , S2 , S3 , S4 , S5 , S6 , S7 ;
+
+  ViewStride() = default ;
+  ViewStride( const ViewStride & ) = default ;
+  ViewStride & operator = ( const ViewStride & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewStride( size_t aS0 , size_t aS1 , size_t aS2 , size_t aS3
+                      , size_t aS4 , size_t aS5 , size_t aS6 , size_t aS7 )
+    : S0( aS0 ) , S1( aS1 ) , S2( aS2 ) , S3( aS3 )
+    , S4( aS4 ) , S5( aS5 ) , S6( aS6 ) , S7( aS7 )
+    {}
+};
+
+template < class Dimension >
+struct ViewOffset< Dimension , Kokkos::LayoutStride
+                 , void >
+{
+private:
+  typedef ViewStride< Dimension::rank >  stride_type ;
+public:
+
+  using is_mapping_plugin = std::true_type ;
+  using is_regular        = std::true_type ;
+
+  typedef size_t                size_type ;
+  typedef Dimension             dimension_type ;
+  typedef Kokkos::LayoutStride  array_layout ;
+
+  dimension_type  m_dim ;
+  stride_type     m_stride ;
+
+  //----------------------------------------
+
+  // rank 1
+  template< typename I0 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 ) const
+  {
+    return i0 * m_stride.S0 ;
+  }
+
+  // rank 2
+  template < typename I0 , typename I1 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 , I1 const & i1 ) const
+  {
+    return i0 * m_stride.S0 +
+           i1 * m_stride.S1 ;
+  }
+
+  //rank 3
+  template < typename I0, typename I1, typename I2 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2 ) const
+  {
+    return i0 * m_stride.S0 +
+           i1 * m_stride.S1 +
+           i2 * m_stride.S2 ;
+  }
+
+  //rank 4
+  template < typename I0, typename I1, typename I2, typename I3 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3 ) const
+  {
+    return i0 * m_stride.S0 +
+           i1 * m_stride.S1 +
+           i2 * m_stride.S2 +
+           i3 * m_stride.S3 ;
+  }
+
+  //rank 5
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4 ) const
+  {
+    return i0 * m_stride.S0 +
+           i1 * m_stride.S1 +
+           i2 * m_stride.S2 +
+           i3 * m_stride.S3 +
+           i4 * m_stride.S4 ;
+  }
+
+  //rank 6
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5 ) const
+  {
+    return i0 * m_stride.S0 +
+           i1 * m_stride.S1 +
+           i2 * m_stride.S2 +
+           i3 * m_stride.S3 +
+           i4 * m_stride.S4 +
+           i5 * m_stride.S5 ;
+  }
+
+  //rank 7
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6 ) const
+  {
+    return i0 * m_stride.S0 +
+           i1 * m_stride.S1 +
+           i2 * m_stride.S2 +
+           i3 * m_stride.S3 +
+           i4 * m_stride.S4 +
+           i5 * m_stride.S5 +
+           i6 * m_stride.S6 ;
+  }
+
+  //rank 8
+  template < typename I0, typename I1, typename I2, typename I3
+           , typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0, I1 const & i1, I2 const & i2, I3 const & i3
+                      , I4 const & i4, I5 const & i5, I6 const & i6, I7 const & i7 ) const
+  {
+    return i0 * m_stride.S0 +
+           i1 * m_stride.S1 +
+           i2 * m_stride.S2 +
+           i3 * m_stride.S3 +
+           i4 * m_stride.S4 +
+           i5 * m_stride.S5 +
+           i6 * m_stride.S6 +
+           i7 * m_stride.S7 ;
+  }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr array_layout layout() const
+    {
+      return array_layout( m_dim.N0 , m_stride.S0
+                         , m_dim.N1 , m_stride.S1
+                         , m_dim.N2 , m_stride.S2
+                         , m_dim.N3 , m_stride.S3
+                         , m_dim.N4 , m_stride.S4
+                         , m_dim.N5 , m_stride.S5
+                         , m_dim.N6 , m_stride.S6
+                         , m_dim.N7 , m_stride.S7
+                         );
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return m_dim.N2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return m_dim.N3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return m_dim.N4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return m_dim.N5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return m_dim.N6 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return m_dim.N7 ; }
+
+  /* Cardinality of the domain index space */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type size() const
+    { return m_dim.N0 * m_dim.N1 * m_dim.N2 * m_dim.N3 * m_dim.N4 * m_dim.N5 * m_dim.N6 * m_dim.N7 ; }
+
+private:
+
+  KOKKOS_INLINE_FUNCTION
+  static constexpr size_type Max( size_type lhs , size_type rhs )
+    { return lhs < rhs ? rhs : lhs ; }
+
+public:
+
+  /* Span of the range space, largest stride * dimension */
+  KOKKOS_INLINE_FUNCTION
+  constexpr size_type span() const
+    {
+      return Max( m_dim.N0 * m_stride.S0 ,
+             Max( m_dim.N1 * m_stride.S1 ,
+             Max( m_dim.N2 * m_stride.S2 ,
+             Max( m_dim.N3 * m_stride.S3 ,
+             Max( m_dim.N4 * m_stride.S4 ,
+             Max( m_dim.N5 * m_stride.S5 ,
+             Max( m_dim.N6 * m_stride.S6 ,
+                  m_dim.N7 * m_stride.S7 )))))));
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return span() == size(); }
+
+  /* Strides of dimensions */
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return m_stride.S0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return m_stride.S1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return m_stride.S2 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return m_stride.S3 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return m_stride.S4 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return m_stride.S5 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return m_stride.S6 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return m_stride.S7 ; }
+
+  // Stride with [ rank ] value is the total length
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      if ( 0 < dimension_type::rank ) { s[0] = m_stride.S0 ; }
+      if ( 1 < dimension_type::rank ) { s[1] = m_stride.S1 ; }
+      if ( 2 < dimension_type::rank ) { s[2] = m_stride.S2 ; }
+      if ( 3 < dimension_type::rank ) { s[3] = m_stride.S3 ; }
+      if ( 4 < dimension_type::rank ) { s[4] = m_stride.S4 ; }
+      if ( 5 < dimension_type::rank ) { s[5] = m_stride.S5 ; }
+      if ( 6 < dimension_type::rank ) { s[6] = m_stride.S6 ; }
+      if ( 7 < dimension_type::rank ) { s[7] = m_stride.S7 ; }
+      s[dimension_type::rank] = span();
+    }
+
+  //----------------------------------------
+
+  ViewOffset() = default ;
+  ViewOffset( const ViewOffset & ) = default ;
+  ViewOffset & operator = ( const ViewOffset & ) = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( std::integral_constant<unsigned,0> const &
+                      , Kokkos::LayoutStride const & rhs )
+    : m_dim( rhs.dimension[0] , rhs.dimension[1] , rhs.dimension[2] , rhs.dimension[3]
+           , rhs.dimension[4] , rhs.dimension[5] , rhs.dimension[6] , rhs.dimension[7] )
+    , m_stride( rhs.stride[0] , rhs.stride[1] , rhs.stride[2] , rhs.stride[3]
+              , rhs.stride[4] , rhs.stride[5] , rhs.stride[6] , rhs.stride[7] )
+    {}
+
+  template< class DimRHS , class LayoutRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( const ViewOffset< DimRHS , LayoutRHS , void > & rhs )
+    : m_dim( rhs.m_dim.N0 , rhs.m_dim.N1 , rhs.m_dim.N2 , rhs.m_dim.N3 
+           , rhs.m_dim.N4 , rhs.m_dim.N5 , rhs.m_dim.N6 , rhs.m_dim.N7 )
+    , m_stride( rhs.stride_0() , rhs.stride_1() , rhs.stride_2() , rhs.stride_3()
+              , rhs.stride_4() , rhs.stride_5() , rhs.stride_6() , rhs.stride_7() )
+    {
+      static_assert( int(DimRHS::rank) == int(dimension_type::rank) , "ViewOffset assignment requires equal rank" );
+      // Also requires equal static dimensions ...
+    }
+
+  //----------------------------------------
+  // Subview construction
+
+private:
+
+  template< class DimRHS , class LayoutRHS >
+  KOKKOS_INLINE_FUNCTION static
+  constexpr size_t stride
+    ( unsigned r , const ViewOffset< DimRHS , LayoutRHS , void > & rhs )
+    {
+      return r >  7 ? 0 : (
+             r == 0 ? rhs.stride_0() : (
+             r == 1 ? rhs.stride_1() : (
+             r == 2 ? rhs.stride_2() : (
+             r == 3 ? rhs.stride_3() : (
+             r == 4 ? rhs.stride_4() : (
+             r == 5 ? rhs.stride_5() : (
+             r == 6 ? rhs.stride_6() : rhs.stride_7() )))))));
+    }
+
+public:
+
+  template< class DimRHS , class LayoutRHS >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset
+    ( const ViewOffset< DimRHS , LayoutRHS , void > & rhs
+    , const SubviewExtents< DimRHS::rank , dimension_type::rank > & sub
+    )
+    // range_extent(r) returns 0 when dimension_type::rank <= r
+    : m_dim( sub.range_extent(0)
+           , sub.range_extent(1)
+           , sub.range_extent(2)
+           , sub.range_extent(3)
+           , sub.range_extent(4)
+           , sub.range_extent(5)
+           , sub.range_extent(6)
+           , sub.range_extent(7)
+           )
+    // range_index(r) returns ~0u when dimension_type::rank <= r
+    , m_stride( stride( sub.range_index(0), rhs )
+              , stride( sub.range_index(1), rhs )
+              , stride( sub.range_index(2), rhs )
+              , stride( sub.range_index(3), rhs )
+              , stride( sub.range_index(4), rhs )
+              , stride( sub.range_index(5), rhs )
+              , stride( sub.range_index(6), rhs )
+              , stride( sub.range_index(7), rhs )
+              )
+    {}
+};
+
+}}} // namespace Kokkos::Experimental::Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+/** \brief  ViewDataHandle provides the type of the 'data handle' which the view
+ *          uses to access data with the [] operator. It also provides
+ *          an allocate function and a function to extract a raw ptr from the
+ *          data handle. ViewDataHandle also defines an enum ReferenceAble which
+ *          specifies whether references/pointers to elements can be taken and a
+ *          'return_type' which is what the view operators will give back.
+ *          Specialisation of this object allows three things depending
+ *          on ViewTraits and compiler options:
+ *          (i)   Use special allocator (e.g. huge pages/small pages and pinned memory)
+ *          (ii)  Use special data handle type (e.g. add Cuda Texture Object)
+ *          (iii) Use special access intrinsics (e.g. texture fetch and non-caching loads)
+ */
+template< class Traits , class Enable = void >
+struct ViewDataHandle {
+
+  typedef typename Traits::value_type   value_type  ;
+  typedef typename Traits::value_type * handle_type ;
+  typedef typename Traits::value_type & return_type ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker  track_type  ;
+
+  KOKKOS_INLINE_FUNCTION
+  static handle_type assign( value_type * arg_data_ptr
+                           , track_type const & /*arg_tracker*/ )
+  {
+    return handle_type( arg_data_ptr );
+  }
+};
+
+template< class Traits >
+struct ViewDataHandle< Traits ,
+  typename std::enable_if<( std::is_same< typename Traits::non_const_value_type
+                                        , typename Traits::value_type >::value
+                            &&
+                            std::is_same< typename Traits::specialize , void >::value
+                            &&
+                            Traits::memory_traits::Atomic
+                          )>::type >
+{
+  typedef typename Traits::value_type  value_type ;
+  typedef typename Kokkos::Impl::AtomicViewDataHandle< Traits >  handle_type ;
+  typedef typename Kokkos::Impl::AtomicDataElement< Traits >     return_type ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker    track_type  ;
+
+  KOKKOS_INLINE_FUNCTION
+  static handle_type assign( value_type * arg_data_ptr
+                           , track_type const & /*arg_tracker*/ )
+  {
+    return handle_type( arg_data_ptr );
+  }
+};
+
+}}} // namespace Kokkos::Experimental::Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+
+/*
+ *  The construction, assignment to default, and destruction
+ *  are merged into a single functor.
+ *  Primarily to work around an unresolved CUDA back-end bug
+ *  that would lose the destruction cuda device function when
+ *  called from the shared memory tracking destruction.
+ *  Secondarily to have two fewer partial specializations.
+ */
+template< class ExecSpace
+        , class ValueType
+        , bool IsScalar = std::is_scalar< ValueType >::value
+        >
+struct ViewValueFunctor ;
+
+template< class ExecSpace , class ValueType >
+struct ViewValueFunctor< ExecSpace , ValueType , false /* is_scalar */ >
+{
+  typedef Kokkos::RangePolicy< ExecSpace > PolicyType ;
+
+  ExecSpace   space ;
+  ValueType * ptr ;
+  size_t      n ;
+  bool        destroy ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_t i ) const
+    {
+      if ( destroy ) { (ptr+i)->~ValueType(); }
+      else           { new (ptr+i) ValueType(); }
+    }
+
+  ViewValueFunctor() = default ;
+  ViewValueFunctor( const ViewValueFunctor & ) = default ;
+  ViewValueFunctor & operator = ( const ViewValueFunctor & ) = default ;
+
+  ViewValueFunctor( ExecSpace   const & arg_space
+                  , ValueType * const arg_ptr
+                  , size_t      const arg_n )
+    : space( arg_space )
+    , ptr( arg_ptr )
+    , n( arg_n )
+    , destroy( false )
+    {}
+
+  void execute( bool arg )
+    {
+      destroy = arg ;
+      if ( ! space.in_parallel() ) {
+        const Kokkos::Impl::ParallelFor< ViewValueFunctor , PolicyType >
+          closure( *this , PolicyType( 0 , n ) );
+        closure.execute();
+        space.fence();
+      }
+      else {
+        for ( size_t i = 0 ; i < n ; ++i ) operator()(i);
+      }
+    }
+
+  void construct_shared_allocation()
+    { execute( false ); }
+
+  void destroy_shared_allocation()
+    { execute( true ); }
+};
+
+
+template< class ExecSpace , class ValueType >
+struct ViewValueFunctor< ExecSpace , ValueType , true /* is_scalar */ >
+{
+  typedef Kokkos::RangePolicy< ExecSpace > PolicyType ;
+
+  ExecSpace   space ;
+  ValueType * ptr ;
+  size_t      n ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_t i ) const
+    { ptr[i] = ValueType(); }
+
+  ViewValueFunctor() = default ;
+  ViewValueFunctor( const ViewValueFunctor & ) = default ;
+  ViewValueFunctor & operator = ( const ViewValueFunctor & ) = default ;
+
+  ViewValueFunctor( ExecSpace   const & arg_space
+                  , ValueType * const arg_ptr
+                  , size_t      const arg_n )
+    : space( arg_space )
+    , ptr( arg_ptr )
+    , n( arg_n )
+    {}
+
+  void construct_shared_allocation()
+    {
+      if ( ! space.in_parallel() ) {
+        const Kokkos::Impl::ParallelFor< ViewValueFunctor , PolicyType >
+          closure( *this , PolicyType( 0 , n ) );
+        closure.execute();
+        space.fence();
+      }
+      else {
+        for ( size_t i = 0 ; i < n ; ++i ) operator()(i);
+      }
+    }
+
+  void destroy_shared_allocation() {}
+};
+
+//----------------------------------------------------------------------------
+/** \brief  View mapping for non-specialized data type and standard layout */
+template< class Traits >
+class ViewMapping< Traits ,
+  typename std::enable_if<(
+    std::is_same< typename Traits::specialize , void >::value
+    &&
+    ViewOffset< typename Traits::dimension
+              , typename Traits::array_layout
+              , void >::is_mapping_plugin::value
+  )>::type >
+{
+private:
+
+  template< class , class ... > friend class ViewMapping ;
+  template< class , class ... > friend class Kokkos::Experimental::View ;
+
+  typedef ViewOffset< typename Traits::dimension
+                    , typename Traits::array_layout
+                    , void
+                    >  offset_type ;
+
+  typedef typename ViewDataHandle< Traits >::handle_type  handle_type ;
+
+  handle_type  m_handle ;
+  offset_type  m_offset ;
+
+  KOKKOS_INLINE_FUNCTION
+  ViewMapping( const handle_type & arg_handle , const offset_type & arg_offset )
+    : m_handle( arg_handle )
+    , m_offset( arg_offset )
+    {}
+
+public:
+
+  //----------------------------------------
+  // Domain dimensions
+
+  enum { Rank = Traits::dimension::rank };
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION constexpr size_t extent( const iType & r ) const
+    { return m_offset.m_dim.extent(r); }
+
+  KOKKOS_INLINE_FUNCTION constexpr
+  typename Traits::array_layout layout() const
+    { return m_offset.layout(); }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_0() const { return m_offset.dimension_0(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return m_offset.dimension_1(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return m_offset.dimension_2(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return m_offset.dimension_3(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return m_offset.dimension_4(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return m_offset.dimension_5(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return m_offset.dimension_6(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return m_offset.dimension_7(); }
+
+  // Is a regular layout with uniform striding for each index.
+  using is_regular = typename offset_type::is_regular ;
+
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return m_offset.stride_0(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return m_offset.stride_1(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return m_offset.stride_2(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return m_offset.stride_3(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return m_offset.stride_4(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return m_offset.stride_5(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return m_offset.stride_6(); }
+  KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return m_offset.stride_7(); }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION void stride( iType * const s ) const { m_offset.stride(s); }
+
+  //----------------------------------------
+  // Range span
+
+  /** \brief  Span of the mapped range */
+  KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return m_offset.span(); }
+
+  /** \brief  Is the mapped range span contiguous */
+  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return m_offset.span_is_contiguous(); }
+
+  typedef typename ViewDataHandle< Traits >::return_type  reference_type ;
+  typedef typename Traits::value_type *                   pointer_type ;
+
+  /** \brief  If data references are lvalue_reference than can query pointer to memory */
+  KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const
+    {
+      return std::is_lvalue_reference< reference_type >::value
+             ? (pointer_type) m_handle
+             : (pointer_type) 0 ;
+    }
+
+  //----------------------------------------
+  // The View class performs all rank and bounds checking before
+  // calling these element reference methods.
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference() const { return m_handle[0]; }
+
+  template< typename I0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename
+    std::enable_if< std::is_integral<I0>::value &&
+                    ! std::is_same< typename Traits::array_layout , Kokkos::LayoutStride >::value
+                  , reference_type >::type
+  reference( const I0 & i0 ) const { return m_handle[i0]; }
+
+  template< typename I0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename
+    std::enable_if< std::is_integral<I0>::value &&
+                    std::is_same< typename Traits::array_layout , Kokkos::LayoutStride >::value
+                  , reference_type >::type
+  reference( const I0 & i0 ) const { return m_handle[ m_offset(i0) ]; }
+
+  template< typename I0 , typename I1 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 ) const
+    { return m_handle[ m_offset(i0,i1) ]; }
+
+  template< typename I0 , typename I1 , typename I2 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 ) const
+    { return m_handle[ m_offset(i0,i1,i2) ]; }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 ) const
+    { return m_handle[ m_offset(i0,i1,i2,i3) ]; }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+                          , const I4 & i4 ) const
+    { return m_handle[ m_offset(i0,i1,i2,i3,i4) ]; }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+                          , const I4 & i4 , const I5 & i5 ) const
+    { return m_handle[ m_offset(i0,i1,i2,i3,i4,i5) ]; }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 , typename I6 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+                          , const I4 & i4 , const I5 & i5 , const I6 & i6 ) const
+    { return m_handle[ m_offset(i0,i1,i2,i3,i4,i5,i6) ]; }
+
+  template< typename I0 , typename I1 , typename I2 , typename I3
+          , typename I4 , typename I5 , typename I6 , typename I7 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  reference_type reference( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3
+                          , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7 ) const
+    { return m_handle[ m_offset(i0,i1,i2,i3,i4,i5,i6,i7) ]; }
+
+  //----------------------------------------
+
+private:
+
+  enum { MemorySpanMask = 8 - 1 /* Force alignment on 8 byte boundary */ };
+  enum { MemorySpanSize = sizeof(typename Traits::value_type) };
+
+public:
+
+  /** \brief  Span, in bytes, of the referenced memory */
+  KOKKOS_INLINE_FUNCTION constexpr size_t memory_span() const
+    {
+      return ( m_offset.span() * sizeof(typename Traits::value_type) + MemorySpanMask ) & ~size_t(MemorySpanMask);
+    }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION ~ViewMapping() {}
+  KOKKOS_INLINE_FUNCTION ViewMapping() : m_handle(), m_offset() {}
+  KOKKOS_INLINE_FUNCTION ViewMapping( const ViewMapping & rhs )
+    : m_handle( rhs.m_handle ), m_offset( rhs.m_offset ) {}
+  KOKKOS_INLINE_FUNCTION ViewMapping & operator = ( const ViewMapping & rhs )
+    { m_handle = rhs.m_handle ; m_offset = rhs.m_offset ; return *this ; }
+
+  KOKKOS_INLINE_FUNCTION ViewMapping( ViewMapping && rhs )
+    : m_handle( rhs.m_handle ), m_offset( rhs.m_offset ) {}
+  KOKKOS_INLINE_FUNCTION ViewMapping & operator = ( ViewMapping && rhs )
+    { m_handle = rhs.m_handle ; m_offset = rhs.m_offset ; return *this ; }
+
+  //----------------------------------------
+
+  /**\brief  Span, in bytes, of the required memory */
+  KOKKOS_INLINE_FUNCTION
+  static constexpr size_t memory_span( typename Traits::array_layout const & arg_layout )
+    {
+      typedef std::integral_constant< unsigned , 0 >  padding ;
+      return ( offset_type( padding(), arg_layout ).span() * MemorySpanSize + MemorySpanMask ) & ~size_t(MemorySpanMask);
+    }
+
+  /**\brief  Wrap a span of memory */
+  template< class ... P >
+  KOKKOS_INLINE_FUNCTION
+  ViewMapping( ViewCtorProp< P ... > const & arg_prop
+             , typename Traits::array_layout const & arg_layout
+             )
+    : m_handle( ( (ViewCtorProp<void,pointer_type> const &) arg_prop ).value )
+    , m_offset( std::integral_constant< unsigned , 0 >() , arg_layout )
+    {}
+
+  //----------------------------------------
+  /*  Allocate and construct mapped array.
+   *  Allocate via shared allocation record and
+   *  return that record for allocation tracking.
+   */
+  template< class ... P >
+  SharedAllocationRecord<> *
+  allocate_shared( ViewCtorProp< P... > const & arg_prop
+                 , typename Traits::array_layout const & arg_layout )
+  {
+    typedef ViewCtorProp< P... > alloc_prop ;
+
+    typedef typename alloc_prop::execution_space  execution_space ;
+    typedef typename Traits::memory_space         memory_space ;
+    typedef typename Traits::value_type           value_type ;
+    typedef ViewValueFunctor< execution_space , value_type > functor_type ;
+    typedef SharedAllocationRecord< memory_space , functor_type > record_type ;
+
+    // Query the mapping for byte-size of allocation.
+    // If padding is allowed then pass in sizeof value type
+    // for padding computation.
+    typedef std::integral_constant
+      < unsigned
+      , alloc_prop::allow_padding ? sizeof(value_type) : 0
+      > padding ;
+
+    m_offset = offset_type( padding(), arg_layout );
+
+    const size_t alloc_size =
+      ( m_offset.span() * MemorySpanSize + MemorySpanMask ) & ~size_t(MemorySpanMask);
+
+    // Create shared memory tracking record with allocate memory from the memory space
+    record_type * const record =
+      record_type::allocate( ( (ViewCtorProp<void,memory_space> const &) arg_prop ).value
+                           , ( (ViewCtorProp<void,std::string>  const &) arg_prop ).value
+                           , alloc_size );
+
+    //  Only set the the pointer and initialize if the allocation is non-zero.
+    //  May be zero if one of the dimensions is zero.
+    if ( alloc_size ) {
+
+      m_handle = handle_type( reinterpret_cast< pointer_type >( record->data() ) );
+
+      if ( alloc_prop::initialize ) {
+        // Assume destruction is only required when construction is requested.
+        // The ViewValueFunctor has both value construction and destruction operators.
+        record->m_destroy = functor_type( ( (ViewCtorProp<void,execution_space> const &) arg_prop).value
+                                        , (value_type *) m_handle
+                                        , m_offset.span()
+                                        );
+
+        // Construct values
+        record->m_destroy.construct_shared_allocation();
+      }
+    }
+
+    return record ;
+  }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+/** \brief  Assign compatible default mappings */
+
+template< class DstTraits , class SrcTraits >
+class ViewMapping< DstTraits , SrcTraits ,
+  typename std::enable_if<(
+    std::is_same< typename DstTraits::memory_space , typename SrcTraits::memory_space >::value
+    &&
+    std::is_same< typename DstTraits::specialize , void >::value
+    &&
+    std::is_same< typename SrcTraits::specialize , void >::value
+    &&
+    (
+      std::is_same< typename DstTraits::array_layout , typename SrcTraits::array_layout >::value
+      ||
+      (
+        (
+          std::is_same< typename DstTraits::array_layout , Kokkos::LayoutLeft >::value ||
+          std::is_same< typename DstTraits::array_layout , Kokkos::LayoutRight >::value ||
+          std::is_same< typename DstTraits::array_layout , Kokkos::LayoutStride >::value
+        )
+        &&
+        (
+          std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value ||
+          std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value ||
+          std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutStride >::value
+        )
+      )
+    )
+  )>::type >
+{
+private:
+
+  enum { is_assignable_value_type =
+    std::is_same< typename DstTraits::value_type
+                , typename SrcTraits::value_type >::value ||
+    std::is_same< typename DstTraits::value_type
+                , typename SrcTraits::const_value_type >::value };
+
+  enum { is_assignable_dimension =
+    ViewDimensionAssignable< typename DstTraits::dimension
+                           , typename SrcTraits::dimension >::value };
+
+  enum { is_assignable_layout =
+    std::is_same< typename DstTraits::array_layout
+                , typename SrcTraits::array_layout >::value ||
+    std::is_same< typename DstTraits::array_layout
+                , Kokkos::LayoutStride >::value ||
+    ( DstTraits::dimension::rank == 0 ) ||
+    ( DstTraits::dimension::rank == 1 &&
+      DstTraits::dimension::rank_dynamic == 1 )
+    };
+
+public:
+
+  enum { is_assignable = is_assignable_value_type &&
+                         is_assignable_dimension &&
+                         is_assignable_layout };
+
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker  TrackType ;
+  typedef ViewMapping< DstTraits , void >  DstType ;
+  typedef ViewMapping< SrcTraits , void >  SrcType ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void assign( DstType & dst , const SrcType & src , const TrackType & src_track )
+    {
+      static_assert( is_assignable_value_type
+                   , "View assignment must have same value type or const = non-const" );
+
+      static_assert( is_assignable_dimension
+                   , "View assignment must have compatible dimensions" );
+
+      static_assert( is_assignable_layout
+                   , "View assignment must have compatible layout or have rank <= 1" );
+
+      typedef typename DstType::offset_type  dst_offset_type ;
+
+      if ( size_t(DstTraits::dimension::rank_dynamic) < size_t(SrcTraits::dimension::rank_dynamic) ) {
+        typedef typename DstTraits::dimension dst_dim;
+        bool assignable =
+          ( ( 1 > DstTraits::dimension::rank_dynamic && 1 <= SrcTraits::dimension::rank_dynamic ) ?
+            dst_dim::ArgN0 == src.dimension_0() : true ) &&
+          ( ( 2 > DstTraits::dimension::rank_dynamic && 2 <= SrcTraits::dimension::rank_dynamic ) ?
+            dst_dim::ArgN1 == src.dimension_1() : true ) &&
+          ( ( 3 > DstTraits::dimension::rank_dynamic && 3 <= SrcTraits::dimension::rank_dynamic ) ?
+            dst_dim::ArgN2 == src.dimension_2() : true ) &&
+          ( ( 4 > DstTraits::dimension::rank_dynamic && 4 <= SrcTraits::dimension::rank_dynamic ) ?
+            dst_dim::ArgN3 == src.dimension_3() : true ) &&
+          ( ( 5 > DstTraits::dimension::rank_dynamic && 5 <= SrcTraits::dimension::rank_dynamic ) ?
+            dst_dim::ArgN4 == src.dimension_4() : true ) &&
+          ( ( 6 > DstTraits::dimension::rank_dynamic && 6 <= SrcTraits::dimension::rank_dynamic ) ?
+            dst_dim::ArgN5 == src.dimension_5() : true ) &&
+          ( ( 7 > DstTraits::dimension::rank_dynamic && 7 <= SrcTraits::dimension::rank_dynamic ) ?
+            dst_dim::ArgN6 == src.dimension_6() : true ) &&
+          ( ( 8 > DstTraits::dimension::rank_dynamic && 8 <= SrcTraits::dimension::rank_dynamic ) ?
+            dst_dim::ArgN7 == src.dimension_7() : true )
+          ;
+        if(!assignable)
+          Kokkos::abort("View Assignment: trying to assign runtime dimension to non matching compile time dimension.");
+      }
+      dst.m_offset = dst_offset_type( src.m_offset );
+      dst.m_handle = Kokkos::Experimental::Impl::ViewDataHandle< DstTraits >::assign( src.m_handle , src_track );
+    }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// Subview mapping.
+// Deduce destination view type from source view traits and subview arguments
+
+template< class SrcTraits , class ... Args >
+struct ViewMapping
+  < typename std::enable_if<(
+      std::is_same< typename SrcTraits::specialize , void >::value
+      &&
+      (
+        std::is_same< typename SrcTraits::array_layout
+                    , Kokkos::LayoutLeft >::value ||
+        std::is_same< typename SrcTraits::array_layout
+                    , Kokkos::LayoutRight >::value ||
+        std::is_same< typename SrcTraits::array_layout
+                    , Kokkos::LayoutStride >::value
+      )
+    )>::type
+  , SrcTraits
+  , Args ... >
+{
+private:
+
+  static_assert( SrcTraits::rank == sizeof...(Args) ,
+    "Subview mapping requires one argument for each dimension of source View" );
+
+  enum
+    { RZ = false
+    , R0 = bool(is_integral_extent<0,Args...>::value)
+    , R1 = bool(is_integral_extent<1,Args...>::value)
+    , R2 = bool(is_integral_extent<2,Args...>::value)
+    , R3 = bool(is_integral_extent<3,Args...>::value)
+    , R4 = bool(is_integral_extent<4,Args...>::value)
+    , R5 = bool(is_integral_extent<5,Args...>::value)
+    , R6 = bool(is_integral_extent<6,Args...>::value)
+    , R7 = bool(is_integral_extent<7,Args...>::value)
+    };
+
+  enum { rank = unsigned(R0) + unsigned(R1) + unsigned(R2) + unsigned(R3)
+              + unsigned(R4) + unsigned(R5) + unsigned(R6) + unsigned(R7) };
+
+  // Whether right-most rank is a range.
+  enum { R0_rev = ( 0 == SrcTraits::rank ? RZ : (
+                    1 == SrcTraits::rank ? R0 : (
+                    2 == SrcTraits::rank ? R1 : (
+                    3 == SrcTraits::rank ? R2 : (
+                    4 == SrcTraits::rank ? R3 : (
+                    5 == SrcTraits::rank ? R4 : (
+                    6 == SrcTraits::rank ? R5 : (
+                    7 == SrcTraits::rank ? R6 : R7 )))))))) };
+
+  // Subview's layout
+  typedef typename std::conditional<
+      ( /* Same array layout IF */
+        ( rank == 0 ) /* output rank zero */
+        ||
+        // OutputRank 1 or 2, InputLayout Left, Interval 0
+        // because single stride one or second index has a stride.
+        ( rank <= 2 && R0 && std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutLeft >::value ) //replace with input rank
+        ||
+        // OutputRank 1 or 2, InputLayout Right, Interval [InputRank-1]
+        // because single stride one or second index has a stride.
+        ( rank <= 2 && R0_rev && std::is_same< typename SrcTraits::array_layout , Kokkos::LayoutRight >::value ) //replace input rank
+      ), typename SrcTraits::array_layout , Kokkos::LayoutStride
+      >::type array_layout ;
+
+  typedef typename SrcTraits::value_type  value_type ;
+
+  typedef typename std::conditional< rank == 0 , value_type ,
+          typename std::conditional< rank == 1 , value_type * ,
+          typename std::conditional< rank == 2 , value_type ** ,
+          typename std::conditional< rank == 3 , value_type *** ,
+          typename std::conditional< rank == 4 , value_type **** ,
+          typename std::conditional< rank == 5 , value_type ***** ,
+          typename std::conditional< rank == 6 , value_type ****** ,
+          typename std::conditional< rank == 7 , value_type ******* ,
+                                                 value_type ********
+          >::type >::type >::type >::type >::type >::type >::type >::type
+     data_type ;
+
+public:
+
+  typedef Kokkos::Experimental::ViewTraits
+    < data_type
+    , array_layout 
+    , typename SrcTraits::device_type
+    , typename SrcTraits::memory_traits > traits_type ;
+
+  typedef Kokkos::Experimental::View
+    < data_type
+    , array_layout 
+    , typename SrcTraits::device_type
+    , typename SrcTraits::memory_traits > type ;
+
+  template< class MemoryTraits >
+  struct apply {
+
+    static_assert( Kokkos::Impl::is_memory_traits< MemoryTraits >::value , "" );
+
+    typedef Kokkos::Experimental::ViewTraits
+      < data_type 
+      , array_layout
+      , typename SrcTraits::device_type
+      , MemoryTraits > traits_type ;
+
+    typedef Kokkos::Experimental::View
+      < data_type 
+      , array_layout
+      , typename SrcTraits::device_type
+      , MemoryTraits > type ;
+  };
+
+  // The presumed type is 'ViewMapping< traits_type , void >'
+  // However, a compatible ViewMapping is acceptable.
+  template< class DstTraits >
+  KOKKOS_INLINE_FUNCTION
+  static void assign( ViewMapping< DstTraits , void > & dst
+                    , ViewMapping< SrcTraits , void > const & src
+                    , Args ... args )
+    {
+      static_assert(
+        ViewMapping< DstTraits , traits_type , void >::is_assignable ,
+        "Subview destination type must be compatible with subview derived type" );
+
+      typedef ViewMapping< DstTraits , void >  DstType ;
+
+      typedef typename DstType::offset_type  dst_offset_type ;
+      typedef typename DstType::handle_type  dst_handle_type ;
+
+      const SubviewExtents< SrcTraits::rank , rank >
+        extents( src.m_offset.m_dim , args... );
+
+      dst.m_offset = dst_offset_type( src.m_offset , extents );
+      dst.m_handle = dst_handle_type( src.m_handle +
+                                      src.m_offset( extents.domain_offset(0)
+                                                  , extents.domain_offset(1)
+                                                  , extents.domain_offset(2)
+                                                  , extents.domain_offset(3)
+                                                  , extents.domain_offset(4)
+                                                  , extents.domain_offset(5)
+                                                  , extents.domain_offset(6)
+                                                  , extents.domain_offset(7)
+                                                  ) );
+    }
+};
+
+
+
+//----------------------------------------------------------------------------
+
+}}} // namespace Kokkos::Experimental::Impl
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template< unsigned , class MapType >
+KOKKOS_INLINE_FUNCTION
+bool view_verify_operator_bounds( const MapType & )
+{ return true ; }
+
+template< unsigned R , class MapType , class iType , class ... Args >
+KOKKOS_INLINE_FUNCTION
+bool view_verify_operator_bounds
+  ( const MapType & map
+  , const iType   & i
+  , Args ... args
+  )
+{
+  return ( size_t(i) < map.extent(R) )
+         && view_verify_operator_bounds<R+1>( map , args ... );
+}
+
+template< unsigned , class MapType >
+inline
+void view_error_operator_bounds( char * , int , const MapType & )
+{}
+
+template< unsigned R , class MapType , class iType , class ... Args >
+inline
+void view_error_operator_bounds
+  ( char * buf
+  , int len
+  , const MapType & map
+  , const iType   & i
+  , Args ... args
+  )
+{
+  const int n =
+    snprintf(buf,len," %ld < %ld %c"
+            , static_cast<unsigned long>(i)
+            , static_cast<unsigned long>( map.extent(R) )
+            , ( sizeof...(Args) ? ',' : ')' )
+            );
+  view_error_operator_bounds<R+1>(buf+n,len-n,map,args...);
+}
+
+template< class MapType , class ... Args >
+KOKKOS_INLINE_FUNCTION
+void view_verify_operator_bounds
+  ( const MapType & map , Args ... args )
+{
+  if ( ! view_verify_operator_bounds<0>( map , args ... ) ) {
+#if defined( KOKKOS_ACTIVE_EXECUTION_SPACE_HOST )
+    enum { LEN = 1024 };
+    char buffer[ LEN ];
+    int n = snprintf(buf,LEN,"View bounds error(" );
+    view_error_operator_bounds<0>( buffer + n , LEN - n , map , args ... );
+    Kokkos::Impl::throw_runtime_exception(std::string(buffer));
+#else
+    Kokkos::abort("View bounds error");
+#endif
+  }
+}
+
+
+class Error_view_scalar_reference_to_non_scalar_view ;
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_EXPERIMENTAL_VIEW_MAPPING_HPP */
+
diff --git a/lib/kokkos/core/src/impl/KokkosExp_ViewTile.hpp b/lib/kokkos/core/src/impl/KokkosExp_ViewTile.hpp
new file mode 100644
index 0000000000..8b3749e853
--- /dev/null
+++ b/lib/kokkos/core/src/impl/KokkosExp_ViewTile.hpp
@@ -0,0 +1,227 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXPERIMENTAL_VIEWTILE_HPP
+#define KOKKOS_EXPERIMENTAL_VIEWTILE_HPP
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+// View mapping for rank two tiled array
+
+template< class L >
+struct is_layout_tile : public std::false_type {};
+
+template< unsigned N0 , unsigned N1 >
+struct is_layout_tile< Kokkos::LayoutTileLeft<N0,N1,true> > : public std::true_type {};
+
+template< class Dimension , class Layout >
+struct ViewOffset< Dimension , Layout ,
+  typename std::enable_if<(
+    ( Dimension::rank == 2 )
+    &&
+    is_layout_tile< Layout >::value
+  )>::type >
+{
+public:
+
+  enum { SHIFT_0 = Kokkos::Impl::integral_power_of_two(Layout::N0) };
+  enum { SHIFT_1 = Kokkos::Impl::integral_power_of_two(Layout::N1) };
+  enum { SHIFT_T = SHIFT_0 + SHIFT_1 };
+  enum { MASK_0  = Layout::N0 - 1 };
+  enum { MASK_1  = Layout::N1 - 1 };
+
+  // Is an irregular layout that does not have uniform striding for each index.
+  using is_mapping_plugin = std::true_type ;
+  using is_regular        = std::false_type ;
+
+  typedef size_t     size_type ;
+  typedef Dimension  dimension_type ;
+  typedef Layout     array_layout ;
+
+  dimension_type m_dim ;
+  size_type      m_tile_N0 ;
+
+  //----------------------------------------
+
+  // Only instantiated for rank 2
+  template< typename I0 , typename I1 >
+  KOKKOS_INLINE_FUNCTION constexpr
+  size_type operator()( I0 const & i0 , I1 const & i1
+                      , int = 0 , int = 0
+                      , int = 0 , int = 0
+                      , int = 0 , int = 0
+                      ) const
+    {
+      return /* ( ( Tile offset                               ) * Tile size ) */
+                ( ( (i0>>SHIFT_0) + m_tile_N0 * (i1>>SHIFT_1) ) << SHIFT_T) +
+             /* ( Offset within tile                       ) */
+                ( (i0 & MASK_0) + ((i1 & MASK_1)<<SHIFT_0) ) ;
+    }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION constexpr
+  array_layout layout() const
+    { return array_layout( m_dim.N0 , m_dim.N1 ); }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_0() const { return m_dim.N0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_1() const { return m_dim.N1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_2() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_3() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_4() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_5() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_6() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type dimension_7() const { return 1 ; }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type size() const { return m_dim.N0 * m_dim.N1 ; }
+
+  // Strides are meaningless due to irregularity
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_0() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_1() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_2() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_3() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_4() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_5() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_6() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION constexpr size_type stride_7() const { return 0 ; }
+
+  KOKKOS_INLINE_FUNCTION constexpr size_type span() const
+    {
+      // ( TileDim0 * ( TileDim1 ) ) * TileSize
+      return ( m_tile_N0 * ( ( m_dim.N1 + MASK_1 ) >> SHIFT_1 ) ) << SHIFT_T ;
+    }
+
+  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const
+    {
+      // Only if dimensions align with tile size
+      return ( m_dim.N0 & MASK_0 ) == 0 && ( m_dim.N1 & MASK_1 ) == 0 ;
+    }
+
+  //----------------------------------------
+
+  ~ViewOffset() = default ;
+  ViewOffset() = default ;
+  ViewOffset( const ViewOffset & ) = default ;
+  ViewOffset & operator = ( const ViewOffset & ) = default ;
+
+  template< unsigned TrivialScalarSize >
+  KOKKOS_INLINE_FUNCTION
+  constexpr ViewOffset( std::integral_constant<unsigned,TrivialScalarSize> const & ,
+                        array_layout const arg_layout )
+    : m_dim( arg_layout.dimension[0], arg_layout.dimension[1], 0, 0, 0, 0, 0, 0 )
+    , m_tile_N0( ( arg_layout.dimension[0] + MASK_0 ) >> SHIFT_0 /* number of tiles in first dimension */ )
+    {}
+};
+
+template< typename T , unsigned N0 , unsigned N1 , class ... P
+        , typename iType0 , typename iType1
+        >
+struct ViewMapping
+  < void
+  , Kokkos::Experimental::ViewTraits<T**,Kokkos::LayoutTileLeft<N0,N1,true>,P...>
+  , Kokkos::LayoutTileLeft<N0,N1,true>
+  , iType0
+  , iType1 >
+{
+  typedef Kokkos::LayoutTileLeft<N0,N1,true>  src_layout ;
+  typedef Kokkos::Experimental::ViewTraits< T** , src_layout , P... > src_traits ;
+  typedef Kokkos::Experimental::ViewTraits< T[N0][N1] , LayoutLeft , P ... > traits ;
+  typedef Kokkos::Experimental::View< T[N0][N1] , LayoutLeft , P ... > type ;
+
+  KOKKOS_INLINE_FUNCTION static
+  void assign( ViewMapping< traits , void > & dst
+             , const ViewMapping< src_traits , void > & src
+             , const src_layout &
+             , const size_t i_tile0
+             , const size_t i_tile1
+             )
+    {
+      typedef ViewMapping< traits , void >        dst_map_type ;
+      typedef ViewMapping< src_traits , void >    src_map_type ;
+      typedef typename dst_map_type::handle_type  dst_handle_type ;
+      typedef typename dst_map_type::offset_type  dst_offset_type ;
+      typedef typename src_map_type::offset_type  src_offset_type ;
+
+      dst = dst_map_type(
+         dst_handle_type( src.m_handle +
+                        ( ( i_tile0 + src.m_offset.m_tile_N0 * i_tile1 ) << src_offset_type::SHIFT_T ) ) ,
+         dst_offset_type() );
+    }
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+namespace Kokkos {
+namespace Experimental {
+
+template< typename T , unsigned N0 , unsigned N1 , class ... P >
+KOKKOS_INLINE_FUNCTION
+Kokkos::Experimental::View< T[N0][N1] , LayoutLeft , P... >
+tile_subview( const Kokkos::Experimental::View<T**,Kokkos::LayoutTileLeft<N0,N1,true>,P...> & src
+            , const size_t i_tile0
+            , const size_t i_tile1
+            )
+{
+  // Force the specialized ViewMapping for extracting a tile
+  // by using the first subview argument as the layout.
+  typedef Kokkos::LayoutTileLeft<N0,N1,true> SrcLayout ;
+
+  return Kokkos::Experimental::View< T[N0][N1] , LayoutLeft , P... >
+    ( src , SrcLayout() , i_tile0 , i_tile1 );
+}
+
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_EXPERIENTAL_VIEWTILE_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_AnalyzePolicy.hpp b/lib/kokkos/core/src/impl/Kokkos_AnalyzePolicy.hpp
new file mode 100644
index 0000000000..0246a7b9af
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_AnalyzePolicy.hpp
@@ -0,0 +1,197 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_IMPL_ANALYZE_POLICY_HPP
+#define KOKKOS_IMPL_ANALYZE_POLICY_HPP
+
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_Concepts.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+namespace Kokkos { namespace Impl {
+
+template < typename ExecutionSpace   = void
+         , typename Schedule         = void
+         , typename WorkTag          = void
+         , typename IndexType        = void
+         , typename IterationPattern = void
+         >
+struct PolicyTraitsBase
+{
+  using type = PolicyTraitsBase< ExecutionSpace, Schedule, WorkTag, IndexType, IterationPattern>;
+
+  using execution_space   = ExecutionSpace;
+  using schedule_type     = Schedule;
+  using work_tag          = WorkTag;
+  using index_type        = IndexType;
+  using iteration_pattern = IterationPattern;
+};
+
+
+template <typename PolicyBase, typename ExecutionSpace>
+struct SetExecutionSpace
+{
+  static_assert( is_void<typename PolicyBase::execution_space>::value
+               , "Kokkos Error: More than one execution space given" );
+  using type = PolicyTraitsBase< ExecutionSpace
+                               , typename PolicyBase::schedule_type
+                               , typename PolicyBase::work_tag
+                               , typename PolicyBase::index_type
+                               , typename PolicyBase::iteration_pattern
+                               >;
+};
+
+template <typename PolicyBase, typename Schedule>
+struct SetSchedule
+{
+  static_assert( is_void<typename PolicyBase::schedule_type>::value
+               , "Kokkos Error: More than one schedule type given" );
+  using type = PolicyTraitsBase< typename PolicyBase::execution_space
+                               , Schedule
+                               , typename PolicyBase::work_tag
+                               , typename PolicyBase::index_type
+                               , typename PolicyBase::iteration_pattern
+                               >;
+};
+
+template <typename PolicyBase, typename WorkTag>
+struct SetWorkTag
+{
+  static_assert( is_void<typename PolicyBase::work_tag>::value
+               , "Kokkos Error: More than one work tag given" );
+  using type = PolicyTraitsBase< typename PolicyBase::execution_space
+                               , typename PolicyBase::schedule_type
+                               , WorkTag
+                               , typename PolicyBase::index_type
+                               , typename PolicyBase::iteration_pattern
+                               >;
+};
+
+template <typename PolicyBase, typename IndexType>
+struct SetIndexType
+{
+  static_assert( is_void<typename PolicyBase::index_type>::value
+               , "Kokkos Error: More than one index type given" );
+  using type = PolicyTraitsBase< typename PolicyBase::execution_space
+                               , typename PolicyBase::schedule_type
+                               , typename PolicyBase::work_tag
+                               , IndexType
+                               , typename PolicyBase::iteration_pattern
+                               >;
+};
+
+
+template <typename PolicyBase, typename IterationPattern>
+struct SetIterationPattern
+{
+  static_assert( is_void<typename PolicyBase::iteration_pattern>::value
+               , "Kokkos Error: More than one iteration_pattern given" );
+  using type = PolicyTraitsBase< typename PolicyBase::execution_space
+                               , typename PolicyBase::schedule_type
+                               , typename PolicyBase::work_tag
+                               , typename PolicyBase::index_type
+                               , IterationPattern
+                               >;
+};
+
+
+template <typename Base, typename... Traits>
+struct AnalyzePolicy;
+
+template <typename Base, typename T, typename... Traits>
+struct AnalyzePolicy<Base, T, Traits...> : public
+  AnalyzePolicy<
+      typename std::conditional< is_execution_space<T>::value  , SetExecutionSpace<Base,T>
+    , typename std::conditional< is_schedule_type<T>::value    , SetSchedule<Base,T>
+    , typename std::conditional< is_index_type<T>::value       , SetIndexType<Base,T>
+    , typename std::conditional< std::is_integral<T>::value    , SetIndexType<Base, IndexType<T> >
+    , typename std::conditional< is_iteration_pattern<T>::value, SetIterationPattern<Base,T>
+    , SetWorkTag<Base,T>
+    >::type >::type >::type >::type>::type::type
+  , Traits...
+  >
+{};
+
+template <typename Base>
+struct AnalyzePolicy<Base>
+{
+  using execution_space = typename std::conditional< is_void< typename Base::execution_space >::value
+                                                   , DefaultExecutionSpace
+                                                   , typename Base::execution_space
+                                                   >::type;
+
+  using schedule_type = typename std::conditional< is_void< typename Base::schedule_type >::value
+                                                 , Schedule< Static >
+                                                 , typename Base::schedule_type
+                                                 >::type;
+
+  using work_tag = typename Base::work_tag;
+
+  using index_type = typename std::conditional< is_void< typename Base::index_type >::value
+                                              , IndexType< typename execution_space::size_type >
+                                              , typename Base::index_type
+                                              >::type
+                                               ::type // nasty hack to make index_type into an integral_type
+                                              ;       // instead of the wrapped IndexType<T> for backwards compatibility
+
+  using iteration_pattern = typename std::conditional< is_void< typename Base::iteration_pattern >::value
+                                                     , void // TODO set default iteration pattern
+                                                     , typename Base::iteration_pattern
+                                                     >::type;
+  using type = PolicyTraitsBase< execution_space
+                               , schedule_type
+                               , work_tag
+                               , index_type
+                               , iteration_pattern
+                               >;
+};
+
+template <typename... Traits>
+struct PolicyTraits
+  : public AnalyzePolicy< PolicyTraitsBase<>, Traits... >::type
+{};
+
+}} // namespace Kokkos::Impl
+
+
+#endif //KOKKOS_IMPL_ANALYZE_POLICY_HPP
diff --git a/lib/kokkos/core/src/impl/Kokkos_AnalyzeShape.hpp b/lib/kokkos/core/src/impl/Kokkos_AnalyzeShape.hpp
new file mode 100644
index 0000000000..2de9df008e
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_AnalyzeShape.hpp
@@ -0,0 +1,260 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_ANALYZESHAPE_HPP
+#define KOKKOS_ANALYZESHAPE_HPP
+
+#include <impl/Kokkos_Shape.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+
+/** \brief  Analyze the array shape defined by a Kokkos::View data type.
+ *
+ *  It is presumed that the data type can be mapped down to a multidimensional
+ *  array of an intrinsic scalar numerical type (double, float, int, ... ).
+ *  The 'value_type' of an array may be an embedded aggregate type such
+ *  as a fixed length array 'Array<T,N>'.
+ *  In this case the 'array_intrinsic_type' represents the
+ *  underlying array of intrinsic scalar numerical type.
+ *
+ *  The embedded aggregate type must have an AnalyzeShape specialization
+ *  to map it down to a shape and intrinsic scalar numerical type.
+ */
+template< class T >
+struct AnalyzeShape : public Shape< sizeof(T) , 0 >
+{
+  typedef void specialize ;
+
+  typedef Shape< sizeof(T), 0 >  shape ;
+
+  typedef       T  array_intrinsic_type ;
+  typedef       T  value_type ;
+  typedef       T  type ;
+
+  typedef const T  const_array_intrinsic_type ;
+  typedef const T  const_value_type ;
+  typedef const T  const_type ;
+
+  typedef       T  non_const_array_intrinsic_type ;
+  typedef       T  non_const_value_type ;
+  typedef       T  non_const_type ;
+};
+
+template<>
+struct AnalyzeShape<void> : public Shape< 0 , 0 >
+{
+  typedef void specialize ;
+
+  typedef Shape< 0 , 0 >  shape ;
+
+  typedef       void  array_intrinsic_type ;
+  typedef       void  value_type ;
+  typedef       void  type ;
+  typedef const void  const_array_intrinsic_type ;
+  typedef const void  const_value_type ;
+  typedef const void  const_type ;
+  typedef       void  non_const_array_intrinsic_type ;
+  typedef       void  non_const_value_type ;
+  typedef       void  non_const_type ;
+};
+
+template< class T >
+struct AnalyzeShape< const T > : public AnalyzeShape<T>::shape
+{
+private:
+  typedef AnalyzeShape<T> nested ;
+public:
+
+  typedef typename nested::specialize specialize ;
+
+  typedef typename nested::shape shape ;
+
+  typedef typename nested::const_array_intrinsic_type  array_intrinsic_type ;
+  typedef typename nested::const_value_type            value_type ;
+  typedef typename nested::const_type                  type ;
+
+  typedef typename nested::const_array_intrinsic_type  const_array_intrinsic_type ;
+  typedef typename nested::const_value_type            const_value_type ;
+  typedef typename nested::const_type                  const_type ;
+
+  typedef typename nested::non_const_array_intrinsic_type  non_const_array_intrinsic_type ;
+  typedef typename nested::non_const_value_type            non_const_value_type ;
+  typedef typename nested::non_const_type                  non_const_type ;
+};
+
+template< class T >
+struct AnalyzeShape< T * >
+  : public ShapeInsert< typename AnalyzeShape<T>::shape , 0 >::type
+{
+private:
+  typedef AnalyzeShape<T> nested ;
+public:
+
+  typedef typename nested::specialize specialize ;
+
+  typedef typename ShapeInsert< typename nested::shape , 0 >::type shape ;
+
+  typedef typename nested::array_intrinsic_type * array_intrinsic_type ;
+  typedef typename nested::value_type             value_type ;
+  typedef typename nested::type                 * type ;
+
+  typedef typename nested::const_array_intrinsic_type * const_array_intrinsic_type ;
+  typedef typename nested::const_value_type             const_value_type ;
+  typedef typename nested::const_type                 * const_type ;
+
+  typedef typename nested::non_const_array_intrinsic_type * non_const_array_intrinsic_type ;
+  typedef typename nested::non_const_value_type             non_const_value_type ;
+  typedef typename nested::non_const_type                 * non_const_type ;
+};
+
+template< class T >
+struct AnalyzeShape< T[] >
+  : public ShapeInsert< typename AnalyzeShape<T>::shape , 0 >::type
+{
+private:
+  typedef AnalyzeShape<T> nested ;
+public:
+
+  typedef typename nested::specialize specialize ;
+
+  typedef typename ShapeInsert< typename nested::shape , 0 >::type shape ;
+
+  typedef typename nested::array_intrinsic_type  array_intrinsic_type [] ;
+  typedef typename nested::value_type            value_type ;
+  typedef typename nested::type                  type [] ;
+
+  typedef typename nested::const_array_intrinsic_type  const_array_intrinsic_type [] ;
+  typedef typename nested::const_value_type            const_value_type ;
+  typedef typename nested::const_type                  const_type [] ;
+
+  typedef typename nested::non_const_array_intrinsic_type  non_const_array_intrinsic_type [] ;
+  typedef typename nested::non_const_value_type            non_const_value_type ;
+  typedef typename nested::non_const_type                  non_const_type [] ;
+};
+
+template< class T >
+struct AnalyzeShape< const T[] >
+  : public ShapeInsert< typename AnalyzeShape< const T >::shape , 0 >::type
+{
+private:
+  typedef AnalyzeShape< const T > nested ;
+public:
+
+  typedef typename nested::specialize specialize ;
+
+  typedef typename ShapeInsert< typename nested::shape , 0 >::type shape ;
+
+  typedef typename nested::array_intrinsic_type  array_intrinsic_type [] ;
+  typedef typename nested::value_type            value_type ;
+  typedef typename nested::type                  type [] ;
+
+  typedef typename nested::const_array_intrinsic_type  const_array_intrinsic_type [] ;
+  typedef typename nested::const_value_type            const_value_type ;
+  typedef typename nested::const_type                  const_type [] ;
+
+  typedef typename nested::non_const_array_intrinsic_type  non_const_array_intrinsic_type [] ;
+  typedef typename nested::non_const_value_type            non_const_value_type ;
+  typedef typename nested::non_const_type                  non_const_type [] ;
+};
+
+template< class T , unsigned N >
+struct AnalyzeShape< T[N] >
+  : public ShapeInsert< typename AnalyzeShape<T>::shape , N >::type
+{
+private:
+  typedef AnalyzeShape<T> nested ;
+public:
+
+  typedef typename nested::specialize specialize ;
+
+  typedef typename ShapeInsert< typename nested::shape , N >::type shape ;
+
+  typedef typename nested::array_intrinsic_type  array_intrinsic_type [N] ;
+  typedef typename nested::value_type            value_type ;
+  typedef typename nested::type                  type [N] ;
+
+  typedef typename nested::const_array_intrinsic_type  const_array_intrinsic_type [N] ;
+  typedef typename nested::const_value_type            const_value_type ;
+  typedef typename nested::const_type                  const_type [N] ;
+
+  typedef typename nested::non_const_array_intrinsic_type  non_const_array_intrinsic_type [N] ;
+  typedef typename nested::non_const_value_type            non_const_value_type ;
+  typedef typename nested::non_const_type                  non_const_type [N] ;
+};
+
+template< class T , unsigned N >
+struct AnalyzeShape< const T[N] >
+  : public ShapeInsert< typename AnalyzeShape< const T >::shape , N >::type
+{
+private:
+  typedef AnalyzeShape< const T > nested ;
+public:
+
+  typedef typename nested::specialize specialize ;
+
+  typedef typename ShapeInsert< typename nested::shape , N >::type shape ;
+
+  typedef typename nested::array_intrinsic_type  array_intrinsic_type [N] ;
+  typedef typename nested::value_type            value_type ;
+  typedef typename nested::type                  type [N] ;
+
+  typedef typename nested::const_array_intrinsic_type  const_array_intrinsic_type [N] ;
+  typedef typename nested::const_value_type            const_value_type ;
+  typedef typename nested::const_type                  const_type [N] ;
+
+  typedef typename nested::non_const_array_intrinsic_type  non_const_array_intrinsic_type [N] ;
+  typedef typename nested::non_const_value_type            non_const_value_type ;
+  typedef typename nested::non_const_type                  non_const_type [N] ;
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+#endif /* #ifndef KOKKOS_ANALYZESHAPE_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Assembly.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Assembly.hpp
new file mode 100644
index 0000000000..500e2b5a21
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Assembly.hpp
@@ -0,0 +1,112 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_ASSEMBLY_HPP )
+#define KOKKOS_ATOMIC_ASSEMBLY_HPP
+namespace Kokkos {
+
+namespace Impl {
+  struct cas128_t
+  {
+    uint64_t lower;
+    uint64_t upper;
+
+    KOKKOS_INLINE_FUNCTION
+    cas128_t () {
+      lower = 0;
+      upper = 0;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    cas128_t (const cas128_t& a) {
+      lower = a.lower;
+      upper = a.upper;
+    }
+    KOKKOS_INLINE_FUNCTION
+    cas128_t (volatile cas128_t* a) {
+      lower = a->lower;
+      upper = a->upper;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    bool operator != (const cas128_t& a) const {
+      return (lower != a.lower) || upper!=a.upper;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator = (const cas128_t& a) {
+      lower = a.lower;
+      upper = a.upper;
+    }
+    KOKKOS_INLINE_FUNCTION
+    void operator = (const cas128_t& a) volatile {
+      lower = a.lower;
+      upper = a.upper;
+    }
+  }
+  __attribute__ (( __aligned__( 16 ) ));
+
+
+  #if defined( KOKKOS_ENABLE_ASM ) && defined ( KOKKOS_USE_ISA_X86_64 )
+  inline cas128_t cas128( volatile cas128_t * ptr, cas128_t cmp,  cas128_t swap )
+  {
+      bool swapped = false;
+      __asm__ __volatile__
+      (
+       "lock cmpxchg16b %1\n\t"
+       "setz %0"
+       : "=q" ( swapped )
+       , "+m" ( *ptr )
+       , "+d" ( cmp.upper )
+       , "+a" ( cmp.lower )
+       : "c" ( swap.upper )
+       , "b" ( swap.lower )
+       , "q" ( swapped )
+     );
+      return cmp;
+  }
+  #endif
+
+}
+}
+
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Compare_Exchange_Strong.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Compare_Exchange_Strong.hpp
new file mode 100644
index 0000000000..fd7ea845e7
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Compare_Exchange_Strong.hpp
@@ -0,0 +1,271 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_COMPARE_EXCHANGE_STRONG_HPP )
+#define KOKKOS_ATOMIC_COMPARE_EXCHANGE_STRONG_HPP
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+// Cuda native CAS supports int, unsigned int, and unsigned long long int (non-standard type).
+// Must cast-away 'volatile' for the CAS call.
+
+#if defined( KOKKOS_ATOMICS_USE_CUDA )
+
+__inline__ __device__
+int atomic_compare_exchange( volatile int * const dest, const int compare, const int val)
+{ return atomicCAS((int*)dest,compare,val); }
+
+__inline__ __device__
+unsigned int atomic_compare_exchange( volatile unsigned int * const dest, const unsigned int compare, const unsigned int val)
+{ return atomicCAS((unsigned int*)dest,compare,val); }
+
+__inline__ __device__
+unsigned long long int atomic_compare_exchange( volatile unsigned long long int * const dest ,
+                                                const unsigned long long int compare ,
+                                                const unsigned long long int val )
+{ return atomicCAS((unsigned long long int*)dest,compare,val); }
+
+template < typename T >
+__inline__ __device__
+T atomic_compare_exchange( volatile T * const dest , const T & compare ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T & >::type val )
+{
+  const int tmp = atomicCAS( (int*) dest , *((int*)&compare) , *((int*)&val) );
+  return *((T*)&tmp);
+}
+
+template < typename T >
+__inline__ __device__
+T atomic_compare_exchange( volatile T * const dest , const T & compare ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(unsigned long long int) , const T & >::type val )
+{
+  typedef unsigned long long int type ;
+  const type tmp = atomicCAS( (type*) dest , *((type*)&compare) , *((type*)&val) );
+  return *((T*)&tmp);
+}
+
+template < typename T >
+__inline__ __device__
+T atomic_compare_exchange( volatile T * const dest , const T & compare ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+             , const T >::type& val )
+{
+  T return_val;
+  // This is a way to (hopefully) avoid dead lock in a warp
+  int done = 1;
+  while ( done>0 ) {
+    done++;
+    if( Impl::lock_address_cuda_space( (void*) dest ) ) {
+      return_val = *dest;
+      if( return_val == compare )
+        *dest = val;
+      Impl::unlock_address_cuda_space( (void*) dest );
+      done = 0;
+    }
+  }
+  return return_val;
+}
+
+//----------------------------------------------------------------------------
+// GCC native CAS supports int, long, unsigned int, unsigned long.
+// Intel native CAS support int and long with the same interface as GCC.
+
+#elif defined(KOKKOS_ATOMICS_USE_GCC) || defined(KOKKOS_ATOMICS_USE_INTEL)
+
+KOKKOS_INLINE_FUNCTION
+int atomic_compare_exchange( volatile int * const dest, const int compare, const int val)
+{ return __sync_val_compare_and_swap(dest,compare,val); }
+
+KOKKOS_INLINE_FUNCTION
+long atomic_compare_exchange( volatile long * const dest, const long compare, const long val )
+{ return __sync_val_compare_and_swap(dest,compare,val); }
+
+#if defined( KOKKOS_ATOMICS_USE_GCC )
+
+// GCC supports unsigned
+
+KOKKOS_INLINE_FUNCTION
+unsigned int atomic_compare_exchange( volatile unsigned int * const dest, const unsigned int compare, const unsigned int val )
+{ return __sync_val_compare_and_swap(dest,compare,val); }
+
+KOKKOS_INLINE_FUNCTION
+unsigned long atomic_compare_exchange( volatile unsigned long * const dest ,
+                                       const unsigned long compare ,
+                                       const unsigned long val )
+{ return __sync_val_compare_and_swap(dest,compare,val); }
+
+#endif
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_compare_exchange( volatile T * const dest, const T & compare,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T & >::type val )
+{
+#ifdef KOKKOS_HAVE_CXX11
+  union U {
+    int i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } tmp ;
+#else
+  union U {
+    int i ;
+    T t ;
+  } tmp ;
+#endif
+
+  tmp.i = __sync_val_compare_and_swap( (int*) dest , *((int*)&compare) , *((int*)&val) );
+  return tmp.t ;
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_compare_exchange( volatile T * const dest, const T & compare,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(long) , const T & >::type val )
+{
+#ifdef KOKKOS_HAVE_CXX11
+  union U {
+    long i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } tmp ;
+#else
+  union U {
+    long i ;
+    T t ;
+  } tmp ;
+#endif
+
+  tmp.i = __sync_val_compare_and_swap( (long*) dest , *((long*)&compare) , *((long*)&val) );
+  return tmp.t ;
+}
+
+#if defined( KOKKOS_ENABLE_ASM) && defined ( KOKKOS_USE_ISA_X86_64 )
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_compare_exchange( volatile T * const dest, const T & compare,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) != sizeof(long) &&
+                                    sizeof(T) == sizeof(Impl::cas128_t), const T & >::type val )
+{
+  union U {
+    Impl::cas128_t i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } tmp ;
+
+  tmp.i = Impl::cas128( (Impl::cas128_t*) dest , *((Impl::cas128_t*)&compare) , *((Impl::cas128_t*)&val) );
+  return tmp.t ;
+}
+#endif
+
+template < typename T >
+inline
+T atomic_compare_exchange( volatile T * const dest , const T compare ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+            #if defined(KOKKOS_ENABLE_ASM) && defined ( KOKKOS_USE_ISA_X86_64 )
+               && ( sizeof(T) != 16 )
+            #endif
+             , const T >::type& val )
+{
+  while( !Impl::lock_address_host_space( (void*) dest ) );
+  T return_val = *dest;
+  if( return_val == compare ) {
+    // Don't use the following line of code here:
+    //
+    //const T tmp = *dest = val;
+    //
+    // Instead, put each assignment in its own statement.  This is
+    // because the overload of T::operator= for volatile *this should
+    // return void, not volatile T&.  See Kokkos #177:
+    //
+    // https://github.com/kokkos/kokkos/issues/177
+    *dest = val;
+    const T tmp = *dest;
+    #ifndef KOKKOS_COMPILER_CLANG
+    (void) tmp;
+    #endif
+  }
+  Impl::unlock_address_host_space( (void*) dest );
+  return return_val;
+}
+//----------------------------------------------------------------------------
+
+#elif defined( KOKKOS_ATOMICS_USE_OMP31 )
+
+template< typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_compare_exchange( volatile T * const dest, const T compare, const T val )
+{
+  T retval;
+#pragma omp critical
+  {
+    retval = dest[0];
+    if ( retval == compare )
+        dest[0] = val;
+  }
+  return retval;
+}
+
+#endif
+
+template <typename T>
+KOKKOS_INLINE_FUNCTION
+bool atomic_compare_exchange_strong(volatile T* const dest, const T compare, const T val)
+{
+  return compare == atomic_compare_exchange(dest, compare, val);
+}
+
+//----------------------------------------------------------------------------
+
+} // namespace Kokkos
+
+#endif
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Decrement.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Decrement.hpp
new file mode 100644
index 0000000000..1438a37e45
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Decrement.hpp
@@ -0,0 +1,117 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP) && ! defined( KOKKOS_ATOMIC_DECREMENT )
+#define KOKKOS_ATOMIC_DECREMENT
+
+namespace Kokkos {
+
+// Atomic increment
+template<>
+KOKKOS_INLINE_FUNCTION
+void atomic_decrement<char>(volatile char* a) {
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 ) && ! defined(_WIN32) && ! defined(__CUDA_ARCH__)
+  __asm__ __volatile__(
+      "lock decb %0"
+      : /* no output registers */
+      : "m" (a[0])
+      : "memory"
+    );
+#else
+  Kokkos::atomic_fetch_add(a,-1);
+#endif
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+void atomic_decrement<short>(volatile short* a) {
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 ) && ! defined(_WIN32) && ! defined(__CUDA_ARCH__)
+  __asm__ __volatile__(
+      "lock decw %0"
+      : /* no output registers */
+      : "m" (a[0])
+      : "memory"
+    );
+#else
+  Kokkos::atomic_fetch_add(a,-1);
+#endif
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+void atomic_decrement<int>(volatile int* a) {
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 ) && ! defined(_WIN32) && ! defined(__CUDA_ARCH__)
+  __asm__ __volatile__(
+      "lock decl %0"
+      : /* no output registers */
+      : "m" (a[0])
+      : "memory"
+    );
+#else
+  Kokkos::atomic_fetch_add(a,-1);
+#endif
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+void atomic_decrement<long long int>(volatile long long int* a) {
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 ) && ! defined(_WIN32) && ! defined(__CUDA_ARCH__)
+  __asm__ __volatile__(
+      "lock decq %0"
+      : /* no output registers */
+      : "m" (a[0])
+      : "memory"
+    );
+#else
+  Kokkos::atomic_fetch_add(a,-1);
+#endif
+}
+
+template<typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_decrement(volatile T* a) {
+  Kokkos::atomic_fetch_add(a,-1);
+}
+
+} // End of namespace Kokkos
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Exchange.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Exchange.hpp
new file mode 100644
index 0000000000..e8cac4ba3b
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Exchange.hpp
@@ -0,0 +1,359 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_EXCHANGE_HPP )
+#define KOKKOS_ATOMIC_EXCHANGE_HPP
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ATOMICS_USE_CUDA )
+
+__inline__ __device__
+int atomic_exchange( volatile int * const dest , const int val )
+{
+  // return __iAtomicExch( (int*) dest , val );
+  return atomicExch( (int*) dest , val );
+}
+
+__inline__ __device__
+unsigned int atomic_exchange( volatile unsigned int * const dest , const unsigned int val )
+{
+  // return __uAtomicExch( (unsigned int*) dest , val );
+  return atomicExch( (unsigned int*) dest , val );
+}
+
+__inline__ __device__
+unsigned long long int atomic_exchange( volatile unsigned long long int * const dest , const unsigned long long int val )
+{
+  // return __ullAtomicExch( (unsigned long long*) dest , val );
+  return atomicExch( (unsigned long long*) dest , val );
+}
+
+/** \brief  Atomic exchange for any type with compatible size */
+template< typename T >
+__inline__ __device__
+T atomic_exchange(
+  volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T & >::type val )
+{
+  // int tmp = __ullAtomicExch( (int*) dest , *((int*)&val) );
+  int tmp = atomicExch( ((int*)dest) , *((int*)&val) );
+  return *((T*)&tmp);
+}
+
+template< typename T >
+__inline__ __device__
+T atomic_exchange(
+  volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(unsigned long long int) , const T & >::type val )
+{
+  typedef unsigned long long int type ;
+  // type tmp = __ullAtomicExch( (type*) dest , *((type*)&val) );
+  type tmp = atomicExch( ((type*)dest) , *((type*)&val) );
+  return *((T*)&tmp);
+}
+
+template < typename T >
+__inline__ __device__
+T atomic_exchange( volatile T * const dest ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+             , const T >::type& val )
+{
+  T return_val;
+  // This is a way to (hopefully) avoid dead lock in a warp
+  int done = 1;
+  while ( done > 0 ) {
+    done++;
+    if( Impl::lock_address_cuda_space( (void*) dest ) ) {
+      return_val = *dest;
+      *dest = val;
+      Impl::unlock_address_cuda_space( (void*) dest );
+      done = 0;
+    }
+  }
+  return return_val;
+}
+/** \brief  Atomic exchange for any type with compatible size */
+template< typename T >
+__inline__ __device__
+void atomic_assign(
+  volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T & >::type val )
+{
+  // (void) __ullAtomicExch( (int*) dest , *((int*)&val) );
+  (void) atomicExch( ((int*)dest) , *((int*)&val) );
+}
+
+template< typename T >
+__inline__ __device__
+void atomic_assign(
+  volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(unsigned long long int) , const T & >::type val )
+{
+  typedef unsigned long long int type ;
+  // (void) __ullAtomicExch( (type*) dest , *((type*)&val) );
+  (void) atomicExch( ((type*)dest) , *((type*)&val) );
+}
+
+template< typename T >
+__inline__ __device__
+void atomic_assign(
+  volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) != sizeof(unsigned long long int)
+                                  , const T & >::type val )
+{
+  (void) atomic_exchange(dest,val);
+}
+
+//----------------------------------------------------------------------------
+
+#elif defined(KOKKOS_ATOMICS_USE_GCC) || defined(KOKKOS_ATOMICS_USE_INTEL)
+
+template< typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_exchange( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) || sizeof(T) == sizeof(long)
+                                  , const T & >::type val )
+{
+  typedef typename Kokkos::Impl::if_c< sizeof(T) == sizeof(int) , int , long >::type type ;
+
+  const type v = *((type*)&val); // Extract to be sure the value doesn't change
+
+  type assumed ;
+
+#ifdef KOKKOS_HAVE_CXX11
+  union U {
+    T val_T ;
+    type val_type ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } old ;
+#else
+  union { T val_T ; type val_type ; } old ;
+#endif
+
+  old.val_T = *dest ;
+
+  do {
+    assumed = old.val_type ;
+    old.val_type = __sync_val_compare_and_swap( (volatile type *) dest , assumed , v );
+  } while ( assumed != old.val_type );
+
+  return old.val_T ;
+}
+
+#if defined(KOKKOS_ENABLE_ASM) && defined ( KOKKOS_USE_ISA_X86_64 )
+template< typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_exchange( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(Impl::cas128_t)
+                                  , const T & >::type val )
+{
+  union U {
+    Impl::cas128_t i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } assume , oldval , newval ;
+
+  oldval.t = *dest ;
+  newval.t = val;
+
+  do {
+    assume.i = oldval.i ;
+    oldval.i = Impl::cas128( (volatile Impl::cas128_t*) dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+#endif
+
+//----------------------------------------------------------------------------
+
+template < typename T >
+inline
+T atomic_exchange( volatile T * const dest ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+              #if defined(KOKKOS_ENABLE_ASM) && defined ( KOKKOS_USE_ISA_X86_64 )
+               && ( sizeof(T) != 16 )
+              #endif
+                 , const T >::type& val )
+{
+  while( !Impl::lock_address_host_space( (void*) dest ) );
+  T return_val = *dest;
+  // Don't use the following line of code here:
+  //
+  //const T tmp = *dest = val;
+  //
+  // Instead, put each assignment in its own statement.  This is
+  // because the overload of T::operator= for volatile *this should
+  // return void, not volatile T&.  See Kokkos #177:
+  //
+  // https://github.com/kokkos/kokkos/issues/177
+  *dest = val;
+  const T tmp = *dest;
+  #ifndef KOKKOS_COMPILER_CLANG
+  (void) tmp;
+  #endif
+  Impl::unlock_address_host_space( (void*) dest );
+  return return_val;
+}
+
+template< typename T >
+KOKKOS_INLINE_FUNCTION
+void atomic_assign( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) || sizeof(T) == sizeof(long)
+                                  , const T & >::type val )
+{
+  typedef typename Kokkos::Impl::if_c< sizeof(T) == sizeof(int) , int , long >::type type ;
+
+  const type v = *((type*)&val); // Extract to be sure the value doesn't change
+
+  type assumed ;
+
+#ifdef KOKKOS_HAVE_CXX11
+  union U {
+    T val_T ;
+    type val_type ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } old ;
+#else
+  union { T val_T ; type val_type ; } old ;
+#endif
+
+  old.val_T = *dest ;
+
+  do {
+    assumed = old.val_type ;
+    old.val_type = __sync_val_compare_and_swap( (volatile type *) dest , assumed , v );
+  } while ( assumed != old.val_type );
+}
+
+#if defined( KOKKOS_ENABLE_ASM ) && defined ( KOKKOS_USE_ISA_X86_64 )
+template< typename T >
+KOKKOS_INLINE_FUNCTION
+void atomic_assign( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(Impl::cas128_t)
+                                  , const T & >::type val )
+{
+  union U {
+    Impl::cas128_t i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } assume , oldval , newval ;
+
+  oldval.t = *dest ;
+  newval.t = val;
+  do {
+    assume.i = oldval.i ;
+    oldval.i = Impl::cas128( (volatile Impl::cas128_t*) dest , assume.i , newval.i);
+  } while ( assume.i != oldval.i );
+}
+#endif
+
+template < typename T >
+inline
+void atomic_assign( volatile T * const dest ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+              #if defined(KOKKOS_ENABLE_ASM) && defined ( KOKKOS_USE_ISA_X86_64 )
+               && ( sizeof(T) != 16 )
+              #endif
+                 , const T >::type& val )
+{
+  while( !Impl::lock_address_host_space( (void*) dest ) );
+  // This is likely an aggregate type with a defined
+  // 'volatile T & operator = ( const T & ) volatile'
+  // member.  The volatile return value implicitly defines a
+  // dereference that some compilers (gcc 4.7.2) warn is being ignored.
+  // Suppress warning by casting return to void.
+  //(void)( *dest = val );
+  *dest = val;
+
+  Impl::unlock_address_host_space( (void*) dest );
+}
+//----------------------------------------------------------------------------
+
+#elif defined( KOKKOS_ATOMICS_USE_OMP31 )
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_exchange( volatile T * const dest , const T val )
+{
+  T retval;
+//#pragma omp atomic capture
+  #pragma omp critical
+  {
+    retval = dest[0];
+    dest[0] = val;
+  }
+  return retval;
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+void atomic_assign( volatile T * const dest , const T val )
+{
+//#pragma omp atomic
+  #pragma omp critical
+  {
+    dest[0] = val;
+  }
+}
+
+#endif
+
+} // namespace Kokkos
+
+#endif
+
+//----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Add.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Add.hpp
new file mode 100644
index 0000000000..62dfcdd2f8
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Add.hpp
@@ -0,0 +1,340 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_FETCH_ADD_HPP )
+#define KOKKOS_ATOMIC_FETCH_ADD_HPP
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ATOMICS_USE_CUDA )
+
+// Support for int, unsigned int, unsigned long long int, and float
+
+__inline__ __device__
+int atomic_fetch_add( volatile int * const dest , const int val )
+{ return atomicAdd((int*)dest,val); }
+
+__inline__ __device__
+unsigned int atomic_fetch_add( volatile unsigned int * const dest , const unsigned int val )
+{ return atomicAdd((unsigned int*)dest,val); }
+
+__inline__ __device__
+unsigned long long int atomic_fetch_add( volatile unsigned long long int * const dest ,
+                                         const unsigned long long int val )
+{ return atomicAdd((unsigned long long int*)dest,val); }
+
+__inline__ __device__
+float atomic_fetch_add( volatile float * const dest , const float val )
+{ return atomicAdd((float*)dest,val); }
+
+template < typename T >
+__inline__ __device__
+T atomic_fetch_add( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T >::type val )
+{
+#ifdef KOKKOS_HAVE_CXX11
+  union U {
+    int i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } assume , oldval , newval ;
+#else
+  union U {
+    int i ;
+    T t ;
+  } assume , oldval , newval ;
+#endif
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t + val ;
+    oldval.i = atomicCAS( (int*)dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+template < typename T >
+__inline__ __device__
+T atomic_fetch_add( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(unsigned long long int) , const T >::type val )
+{
+#ifdef KOKKOS_HAVE_CXX11
+  union U {
+    unsigned long long int i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } assume , oldval , newval ;
+#else
+  union U {
+    unsigned long long int i ;
+    T t ;
+  } assume , oldval , newval ;
+#endif
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t + val ;
+    oldval.i = atomicCAS( (unsigned long long int*)dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+//----------------------------------------------------------------------------
+
+template < typename T >
+__inline__ __device__
+T atomic_fetch_add( volatile T * const dest ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+             , const T >::type& val )
+{
+  T return_val;
+  // This is a way to (hopefully) avoid dead lock in a warp
+  int done = 1;
+  while ( done>0 ) {
+    done++;
+    if( Impl::lock_address_cuda_space( (void*) dest ) ) {
+      return_val = *dest;
+      *dest = return_val + val;
+      Impl::unlock_address_cuda_space( (void*) dest );
+      done = 0;
+    }
+  }
+  return return_val;
+}
+//----------------------------------------------------------------------------
+
+#elif defined(KOKKOS_ATOMICS_USE_GCC) || defined(KOKKOS_ATOMICS_USE_INTEL)
+
+#if defined( KOKKOS_ENABLE_ASM ) && defined ( KOKKOS_USE_ISA_X86_64 )
+KOKKOS_INLINE_FUNCTION
+int atomic_fetch_add( volatile int * dest , const int val )
+{
+        int original = val;
+
+        __asm__ __volatile__(
+                "lock xadd %1, %0"
+                : "+m" (*dest), "+r" (original)
+                : "m" (*dest), "r" (original)
+                : "memory"
+        );
+
+        return original;
+}
+#else
+KOKKOS_INLINE_FUNCTION
+int atomic_fetch_add( volatile int * const dest , const int val )
+{ return __sync_fetch_and_add(dest, val); }
+#endif
+
+KOKKOS_INLINE_FUNCTION
+long int atomic_fetch_add( volatile long int * const dest , const long int val )
+{ return __sync_fetch_and_add(dest,val); }
+
+#if defined( KOKKOS_ATOMICS_USE_GCC )
+
+KOKKOS_INLINE_FUNCTION
+unsigned int atomic_fetch_add( volatile unsigned int * const dest , const unsigned int val )
+{ return __sync_fetch_and_add(dest,val); }
+
+KOKKOS_INLINE_FUNCTION
+unsigned long int atomic_fetch_add( volatile unsigned long int * const dest , const unsigned long int val )
+{ return __sync_fetch_and_add(dest,val); }
+
+#endif
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_add( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T >::type val )
+{
+#ifdef KOKKOS_HAVE_CXX11
+  union U {
+    int i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } assume , oldval , newval ;
+#else
+  union U {
+    int i ;
+    T t ;
+  } assume , oldval , newval ;
+#endif
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t + val ;
+    oldval.i = __sync_val_compare_and_swap( (int*) dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_add( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(long) , const T >::type val )
+{
+#ifdef KOKKOS_HAVE_CXX11
+  union U {
+    long i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } assume , oldval , newval ;
+#else
+  union U {
+    long i ;
+    T t ;
+  } assume , oldval , newval ;
+#endif
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t + val ;
+    oldval.i = __sync_val_compare_and_swap( (long*) dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+#if defined( KOKKOS_ENABLE_ASM ) && defined ( KOKKOS_USE_ISA_X86_64 )
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_add( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) != sizeof(long) &&
+                                    sizeof(T) == sizeof(Impl::cas128_t) , const T >::type val )
+{
+  union U {
+    Impl::cas128_t i ;
+    T t ;
+    KOKKOS_INLINE_FUNCTION U() {};
+  } assume , oldval , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t + val ;
+    oldval.i = Impl::cas128( (volatile Impl::cas128_t*) dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+#endif
+
+//----------------------------------------------------------------------------
+
+template < typename T >
+inline
+T atomic_fetch_add( volatile T * const dest ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+              #if defined(KOKKOS_ENABLE_ASM) && defined ( KOKKOS_USE_ISA_X86_64 )
+               && ( sizeof(T) != 16 )
+              #endif
+                 , const T >::type& val )
+{
+  while( !Impl::lock_address_host_space( (void*) dest ) );
+  T return_val = *dest;
+  // Don't use the following line of code here:
+  //
+  //const T tmp = *dest = return_val + val;
+  //
+  // Instead, put each assignment in its own statement.  This is
+  // because the overload of T::operator= for volatile *this should
+  // return void, not volatile T&.  See Kokkos #177:
+  //
+  // https://github.com/kokkos/kokkos/issues/177
+  *dest = return_val + val;
+  const T tmp = *dest;
+  (void) tmp;
+  Impl::unlock_address_host_space( (void*) dest );
+  return return_val;
+}
+//----------------------------------------------------------------------------
+
+#elif defined( KOKKOS_ATOMICS_USE_OMP31 )
+
+template< typename T >
+T atomic_fetch_add( volatile T * const dest , const T val )
+{
+  T retval;
+#pragma omp atomic capture
+  {
+    retval = dest[0];
+    dest[0] += val;
+  }
+  return retval;
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+
+// Simpler version of atomic_fetch_add without the fetch
+template <typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_add(volatile T * const dest, const T src) {
+  atomic_fetch_add(dest,src);
+}
+
+}
+#endif
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_And.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_And.hpp
new file mode 100644
index 0000000000..9b7ebae4ac
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_And.hpp
@@ -0,0 +1,125 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_FETCH_AND_HPP )
+#define KOKKOS_ATOMIC_FETCH_AND_HPP
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ATOMICS_USE_CUDA )
+
+// Support for int, unsigned int, unsigned long long int, and float
+
+__inline__ __device__
+int atomic_fetch_and( volatile int * const dest , const int val )
+{ return atomicAnd((int*)dest,val); }
+
+__inline__ __device__
+unsigned int atomic_fetch_and( volatile unsigned int * const dest , const unsigned int val )
+{ return atomicAnd((unsigned int*)dest,val); }
+
+#if defined( __CUDA_ARCH__ ) && ( 350 <= __CUDA_ARCH__ )
+__inline__ __device__
+unsigned long long int atomic_fetch_and( volatile unsigned long long int * const dest ,
+                                         const unsigned long long int val )
+{ return atomicAnd((unsigned long long int*)dest,val); }
+#endif
+
+//----------------------------------------------------------------------------
+
+#elif defined(KOKKOS_ATOMICS_USE_GCC) || defined(KOKKOS_ATOMICS_USE_INTEL)
+
+KOKKOS_INLINE_FUNCTION
+int atomic_fetch_and( volatile int * const dest , const int val )
+{ return __sync_fetch_and_and(dest,val); }
+
+KOKKOS_INLINE_FUNCTION
+long int atomic_fetch_and( volatile long int * const dest , const long int val )
+{ return __sync_fetch_and_and(dest,val); }
+
+#if defined( KOKKOS_ATOMICS_USE_GCC )
+
+KOKKOS_INLINE_FUNCTION
+unsigned int atomic_fetch_and( volatile unsigned int * const dest , const unsigned int val )
+{ return __sync_fetch_and_and(dest,val); }
+
+KOKKOS_INLINE_FUNCTION
+unsigned long int atomic_fetch_and( volatile unsigned long int * const dest , const unsigned long int val )
+{ return __sync_fetch_and_and(dest,val); }
+
+#endif
+
+//----------------------------------------------------------------------------
+
+#elif defined( KOKKOS_ATOMICS_USE_OMP31 )
+
+template< typename T >
+T atomic_fetch_and( volatile T * const dest , const T val )
+{
+  T retval;
+#pragma omp atomic capture
+  {
+    retval = dest[0];
+    dest[0] &= val;
+  }
+  return retval;
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+
+// Simpler version of atomic_fetch_and without the fetch
+template <typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_and(volatile T * const dest, const T src) {
+  (void)atomic_fetch_and(dest,src);
+}
+
+}
+
+#endif
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Or.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Or.hpp
new file mode 100644
index 0000000000..f15e61a3ae
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Or.hpp
@@ -0,0 +1,125 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_FETCH_OR_HPP )
+#define KOKKOS_ATOMIC_FETCH_OR_HPP
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ATOMICS_USE_CUDA )
+
+// Support for int, unsigned int, unsigned long long int, and float
+
+__inline__ __device__
+int atomic_fetch_or( volatile int * const dest , const int val )
+{ return atomicOr((int*)dest,val); }
+
+__inline__ __device__
+unsigned int atomic_fetch_or( volatile unsigned int * const dest , const unsigned int val )
+{ return atomicOr((unsigned int*)dest,val); }
+
+#if defined( __CUDA_ARCH__ ) && ( 350 <= __CUDA_ARCH__ )
+__inline__ __device__
+unsigned long long int atomic_fetch_or( volatile unsigned long long int * const dest ,
+                                         const unsigned long long int val )
+{ return atomicOr((unsigned long long int*)dest,val); }
+#endif
+
+//----------------------------------------------------------------------------
+
+#elif defined(KOKKOS_ATOMICS_USE_GCC) || defined(KOKKOS_ATOMICS_USE_INTEL)
+
+KOKKOS_INLINE_FUNCTION
+int atomic_fetch_or( volatile int * const dest , const int val )
+{ return __sync_fetch_and_or(dest,val); }
+
+KOKKOS_INLINE_FUNCTION
+long int atomic_fetch_or( volatile long int * const dest , const long int val )
+{ return __sync_fetch_and_or(dest,val); }
+
+#if defined( KOKKOS_ATOMICS_USE_GCC )
+
+KOKKOS_INLINE_FUNCTION
+unsigned int atomic_fetch_or( volatile unsigned int * const dest , const unsigned int val )
+{ return __sync_fetch_and_or(dest,val); }
+
+KOKKOS_INLINE_FUNCTION
+unsigned long int atomic_fetch_or( volatile unsigned long int * const dest , const unsigned long int val )
+{ return __sync_fetch_and_or(dest,val); }
+
+#endif
+
+//----------------------------------------------------------------------------
+
+#elif defined( KOKKOS_ATOMICS_USE_OMP31 )
+
+template< typename T >
+T atomic_fetch_or( volatile T * const dest , const T val )
+{
+  T retval;
+#pragma omp atomic capture
+  {
+    retval = dest[0];
+    dest[0] |= val;
+  }
+  return retval;
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+
+// Simpler version of atomic_fetch_or without the fetch
+template <typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_or(volatile T * const dest, const T src) {
+  (void)atomic_fetch_or(dest,src);
+}
+
+}
+
+#endif
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Sub.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Sub.hpp
new file mode 100644
index 0000000000..a3a57aa81c
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Fetch_Sub.hpp
@@ -0,0 +1,235 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_FETCH_SUB_HPP )
+#define KOKKOS_ATOMIC_FETCH_SUB_HPP
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ATOMICS_USE_CUDA )
+
+// Support for int, unsigned int, unsigned long long int, and float
+
+__inline__ __device__
+int atomic_fetch_sub( volatile int * const dest , const int val )
+{ return atomicSub((int*)dest,val); }
+
+__inline__ __device__
+unsigned int atomic_fetch_sub( volatile unsigned int * const dest , const unsigned int val )
+{ return atomicSub((unsigned int*)dest,val); }
+
+template < typename T >
+__inline__ __device__
+T atomic_fetch_sub( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T >::type val )
+{
+  union { int i ; T t ; } oldval , assume , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t - val ;
+    oldval.i = atomicCAS( (int*)dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+template < typename T >
+__inline__ __device__
+T atomic_fetch_sub( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(unsigned long long int) , const T >::type val )
+{
+  union { unsigned long long int i ; T t ; } oldval , assume , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t - val ;
+    oldval.i = atomicCAS( (unsigned long long int*)dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+
+//----------------------------------------------------------------------------
+
+template < typename T >
+__inline__ __device__
+T atomic_fetch_sub( volatile T * const dest ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+             , const T >::type& val )
+{
+  T return_val;
+  // This is a way to (hopefully) avoid dead lock in a warp
+  int done = 0;
+  while ( done>0 ) {
+    done++;
+    if( Impl::lock_address_cuda_space( (void*) dest ) ) {
+      return_val = *dest;
+      *dest = return_val - val;
+      Impl::unlock_address_cuda_space( (void*) dest );
+      done = 0;
+    }
+  }
+  return return_val;
+}
+
+//----------------------------------------------------------------------------
+
+#elif defined(KOKKOS_ATOMICS_USE_GCC) || defined(KOKKOS_ATOMICS_USE_INTEL)
+
+KOKKOS_INLINE_FUNCTION
+int atomic_fetch_sub( volatile int * const dest , const int val )
+{ return __sync_fetch_and_sub(dest,val); }
+
+KOKKOS_INLINE_FUNCTION
+long int atomic_fetch_sub( volatile long int * const dest , const long int val )
+{ return __sync_fetch_and_sub(dest,val); }
+
+#if defined( KOKKOS_ATOMICS_USE_GCC )
+
+KOKKOS_INLINE_FUNCTION
+unsigned int atomic_fetch_sub( volatile unsigned int * const dest , const unsigned int val )
+{ return __sync_fetch_and_sub(dest,val); }
+
+KOKKOS_INLINE_FUNCTION
+unsigned long int atomic_fetch_sub( volatile unsigned long int * const dest , const unsigned long int val )
+{ return __sync_fetch_and_sub(dest,val); }
+
+#endif
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_sub( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T >::type val )
+{
+  union { int i ; T t ; } assume , oldval , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t - val ;
+    oldval.i = __sync_val_compare_and_swap( (int*) dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_sub( volatile T * const dest ,
+  typename Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(long) , const T >::type val )
+{
+  union { long i ; T t ; } assume , oldval , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = assume.t - val ;
+    oldval.i = __sync_val_compare_and_swap( (long*) dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+
+//----------------------------------------------------------------------------
+
+template < typename T >
+inline
+T atomic_fetch_sub( volatile T * const dest ,
+    typename ::Kokkos::Impl::enable_if<
+                  ( sizeof(T) != 4 )
+               && ( sizeof(T) != 8 )
+             , const T >::type& val )
+{
+  while( !Impl::lock_address_host_space( (void*) dest ) );
+  T return_val = *dest;
+  *dest = return_val - val;
+  Impl::unlock_address_host_space( (void*) dest );
+  return return_val;
+}
+
+//----------------------------------------------------------------------------
+
+#elif defined( KOKKOS_ATOMICS_USE_OMP31 )
+
+template< typename T >
+T atomic_fetch_sub( volatile T * const dest , const T val )
+{
+  T retval;
+#pragma omp atomic capture
+  {
+    retval = dest[0];
+    dest[0] -= val;
+  }
+  return retval;
+}
+
+#endif
+
+// Simpler version of atomic_fetch_sub without the fetch
+template <typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_sub(volatile T * const dest, const T src) {
+  atomic_fetch_sub(dest,src);
+}
+
+}
+
+#include<impl/Kokkos_Atomic_Assembly.hpp>
+#endif
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Generic.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Generic.hpp
new file mode 100644
index 0000000000..343e9bf4c4
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Generic.hpp
@@ -0,0 +1,419 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_ATOMIC_GENERIC_HPP )
+#define KOKKOS_ATOMIC_GENERIC_HPP
+#include <Kokkos_Macros.hpp>
+
+// Combination operands to be used in an Compare and Exchange based atomic operation
+namespace Kokkos {
+namespace Impl {
+
+template<class Scalar1, class Scalar2>
+struct MaxOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return (val1 > val2 ? val1 : val2);
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct MinOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return (val1 < val2 ? val1 : val2);
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct AddOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1+val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct SubOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1-val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct MulOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1*val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct DivOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1/val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct ModOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1%val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct AndOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1&val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct OrOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1|val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct XorOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1^val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct LShiftOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1<<val2;
+  }
+};
+
+template<class Scalar1, class Scalar2>
+struct RShiftOper {
+  KOKKOS_FORCEINLINE_FUNCTION
+  static Scalar1 apply(const Scalar1& val1, const Scalar2& val2) {
+    return val1>>val2;
+  }
+};
+
+template < class Oper, typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_oper( const Oper& op, volatile T * const dest ,
+  typename ::Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(unsigned long long int) , const T >::type val )
+{
+  union { unsigned long long int i ; T t ; } oldval , assume , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = Oper::apply(assume.t, val) ;
+    oldval.i = ::Kokkos::atomic_compare_exchange( (unsigned long long int*)dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+template < class Oper, typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_oper_fetch( const Oper& op, volatile T * const dest ,
+  typename ::Kokkos::Impl::enable_if< sizeof(T) != sizeof(int) &&
+                                    sizeof(T) == sizeof(unsigned long long int) , const T >::type val )
+{
+  union { unsigned long long int i ; T t ; } oldval , assume , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = Oper::apply(assume.t, val) ;
+    oldval.i = ::Kokkos::atomic_compare_exchange( (unsigned long long int*)dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return newval.t ;
+}
+
+template < class Oper, typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_oper( const Oper& op, volatile T * const dest ,
+  typename ::Kokkos::Impl::enable_if< sizeof(T) == sizeof(int) , const T >::type val )
+{
+  union { int i ; T t ; } oldval , assume , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = Oper::apply(assume.t, val) ;
+    oldval.i = ::Kokkos::atomic_compare_exchange( (int*)dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return oldval.t ;
+}
+
+template < class Oper, typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_oper_fetch( const Oper& op, volatile T * const dest ,
+  typename ::Kokkos::Impl::enable_if< sizeof(T) == sizeof(int), const T >::type val )
+{
+  union { int i ; T t ; } oldval , assume , newval ;
+
+  oldval.t = *dest ;
+
+  do {
+    assume.i = oldval.i ;
+    newval.t = Oper::apply(assume.t, val) ;
+    oldval.i = ::Kokkos::atomic_compare_exchange( (int*)dest , assume.i , newval.i );
+  } while ( assume.i != oldval.i );
+
+  return newval.t ;
+}
+
+template < class Oper, typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_oper( const Oper& op, volatile T * const dest ,
+  typename ::Kokkos::Impl::enable_if<
+                ( sizeof(T) != 4 )
+             && ( sizeof(T) != 8 )
+          #if defined(KOKKOS_ENABLE_ASM) && defined(KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST)
+             && ( sizeof(T) != 16 )
+          #endif
+           , const T >::type val )
+{
+
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+  while( !Impl::lock_address_host_space( (void*) dest ) );
+  T return_val = *dest;
+  *dest = Oper::apply(return_val, val);
+  Impl::unlock_address_host_space( (void*) dest );
+  return return_val;
+#else
+  // This is a way to (hopefully) avoid dead lock in a warp
+  int done = 1;
+  while ( done>0 ) {
+    done++;
+    if( Impl::lock_address_cuda_space( (void*) dest ) ) {
+      T return_val = *dest;
+      *dest = Oper::apply(return_val, val);;
+      Impl::unlock_address_cuda_space( (void*) dest );
+      done=0;
+    }
+  }
+  return return_val;
+#endif
+}
+
+template < class Oper, typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_oper_fetch( const Oper& op, volatile T * const dest ,
+  typename ::Kokkos::Impl::enable_if<
+                ( sizeof(T) != 4 )
+             && ( sizeof(T) != 8 )
+          #if defined(KOKKOS_ENABLE_ASM) && defined(KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST)
+             && ( sizeof(T) != 16 )
+          #endif
+           , const T >::type& val )
+{
+
+#ifdef KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST
+  while( !Impl::lock_address_host_space( (void*) dest ) );
+  T return_val = Oper::apply(*dest, val);
+  *dest = return_val;
+  Impl::unlock_address_host_space( (void*) dest );
+  return return_val;
+#else
+  // This is a way to (hopefully) avoid dead lock in a warp
+  int done = 1;
+  while ( done>0 ) {
+    done++;
+    if( Impl::lock_address_cuda_space( (void*) dest ) ) {
+      T return_val = Oper::apply(*dest, val);
+      *dest = return_val;
+      Impl::unlock_address_cuda_space( (void*) dest );
+      done=0;
+    }
+  }
+  return return_val;
+#endif
+}
+
+}
+}
+
+namespace Kokkos {
+
+// Fetch_Oper atomics: return value before operation
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_max(volatile T * const dest, const T val) {
+  return Impl::atomic_fetch_oper(Impl::MaxOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_min(volatile T * const dest, const T val) {
+  return Impl::atomic_fetch_oper(Impl::MinOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_mul(volatile T * const dest, const T val) {
+  return Impl::atomic_fetch_oper(Impl::MulOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_div(volatile T * const dest, const T val) {
+  return Impl::atomic_fetch_oper(Impl::DivOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_mod(volatile T * const dest, const T val) {
+  return Impl::atomic_fetch_oper(Impl::ModOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_and(volatile T * const dest, const T val) {
+  return Impl::atomic_fetch_oper(Impl::AndOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_or(volatile T * const dest, const T val) {
+  return Impl::atomic_fetch_oper(Impl::OrOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_xor(volatile T * const dest, const T val) {
+  return Impl::atomic_fetch_oper(Impl::XorOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_lshift(volatile T * const dest, const unsigned int val) {
+  return Impl::atomic_fetch_oper(Impl::LShiftOper<T,const unsigned int>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_fetch_rshift(volatile T * const dest, const unsigned int val) {
+  return Impl::atomic_fetch_oper(Impl::RShiftOper<T,const unsigned int>(),dest,val);
+}
+
+
+// Oper Fetch atomics: return value after operation
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_max_fetch(volatile T * const dest, const T val) {
+  return Impl::atomic_oper_fetch(Impl::MaxOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_min_fetch(volatile T * const dest, const T val) {
+  return Impl::atomic_oper_fetch(Impl::MinOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_mul_fetch(volatile T * const dest, const T val) {
+  return Impl::atomic_oper_fetch(Impl::MulOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_div_fetch(volatile T * const dest, const T val) {
+  return Impl::atomic_oper_fetch(Impl::DivOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_mod_fetch(volatile T * const dest, const T val) {
+  return Impl::atomic_oper_fetch(Impl::ModOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_and_fetch(volatile T * const dest, const T val) {
+  return Impl::atomic_oper_fetch(Impl::AndOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_or_fetch(volatile T * const dest, const T val) {
+  return Impl::atomic_oper_fetch(Impl::OrOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_xor_fetch(volatile T * const dest, const T val) {
+  return Impl::atomic_oper_fetch(Impl::XorOper<T,const T>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_lshift_fetch(volatile T * const dest, const unsigned int val) {
+  return Impl::atomic_oper_fetch(Impl::LShiftOper<T,const unsigned int>(),dest,val);
+}
+
+template < typename T >
+KOKKOS_INLINE_FUNCTION
+T atomic_rshift_fetch(volatile T * const dest, const unsigned int val) {
+  return Impl::atomic_oper_fetch(Impl::RShiftOper<T,const unsigned int>(),dest,val);
+}
+
+
+}
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Increment.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Increment.hpp
new file mode 100644
index 0000000000..eecda29f1c
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Increment.hpp
@@ -0,0 +1,117 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP) && ! defined( KOKKOS_ATOMIC_INCREMENT )
+#define KOKKOS_ATOMIC_INCREMENT
+
+namespace Kokkos {
+
+// Atomic increment
+template<>
+KOKKOS_INLINE_FUNCTION
+void atomic_increment<char>(volatile char* a) {
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 ) && ! defined(_WIN32) && ! defined(__CUDA_ARCH__)
+  __asm__ __volatile__(
+      "lock incb %0"
+      : /* no output registers */
+      : "m" (a[0])
+      : "memory"
+    );
+#else
+  Kokkos::atomic_fetch_add(a,1);
+#endif
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+void atomic_increment<short>(volatile short* a) {
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 ) && ! defined(_WIN32) && ! defined(__CUDA_ARCH__)
+  __asm__ __volatile__(
+      "lock incw %0"
+      : /* no output registers */
+      : "m" (a[0])
+      : "memory"
+    );
+#else
+  Kokkos::atomic_fetch_add(a,1);
+#endif
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+void atomic_increment<int>(volatile int* a) {
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 ) && ! defined(_WIN32) && ! defined(__CUDA_ARCH__)
+  __asm__ __volatile__(
+      "lock incl %0"
+      : /* no output registers */
+      : "m" (a[0])
+      : "memory"
+    );
+#else
+  Kokkos::atomic_fetch_add(a,1);
+#endif
+}
+
+template<>
+KOKKOS_INLINE_FUNCTION
+void atomic_increment<long long int>(volatile long long int* a) {
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 ) && ! defined(_WIN32) && ! defined(__CUDA_ARCH__)
+  __asm__ __volatile__(
+      "lock incq %0"
+      : /* no output registers */
+      : "m" (a[0])
+      : "memory"
+    );
+#else
+  Kokkos::atomic_fetch_add(a,1);
+#endif
+}
+
+template<typename T>
+KOKKOS_INLINE_FUNCTION
+void atomic_increment(volatile T* a) {
+  Kokkos::atomic_fetch_add(a,1);
+}
+
+} // End of namespace Kokkos
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_View.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_View.hpp
new file mode 100644
index 0000000000..6e48faa694
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_View.hpp
@@ -0,0 +1,430 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+#ifndef KOKKOS_ATOMIC_VIEW_HPP
+#define KOKKOS_ATOMIC_VIEW_HPP
+
+#include <Kokkos_Macros.hpp>
+#include <Kokkos_Atomic.hpp>
+
+namespace Kokkos { namespace Impl {
+
+//The following tag is used to prevent an implicit call of the constructor when trying
+//to assign a literal 0 int ( = 0 );
+struct AtomicViewConstTag {};
+
+template<class ViewTraits>
+class AtomicDataElement {
+public:
+  typedef typename ViewTraits::value_type value_type;
+  typedef typename ViewTraits::const_value_type const_value_type;
+  typedef typename ViewTraits::non_const_value_type non_const_value_type;
+  volatile value_type* const ptr;
+
+  KOKKOS_INLINE_FUNCTION
+  AtomicDataElement(value_type* ptr_, AtomicViewConstTag ):ptr(ptr_){}
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator = (const_value_type& val) const {
+    *ptr = val;
+    return val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator = (volatile const_value_type& val) const {
+    *ptr = val;
+    return val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void inc() const {
+    Kokkos::atomic_increment(ptr);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void dec() const {
+    Kokkos::atomic_decrement(ptr);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator ++ () const {
+    const_value_type tmp = Kokkos::atomic_fetch_add(ptr,1);
+    return tmp+1;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator -- () const {
+    const_value_type tmp = Kokkos::atomic_fetch_add(ptr,-1);
+    return tmp-1;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator ++ (int) const {
+    return Kokkos::atomic_fetch_add(ptr,1);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator -- (int) const {
+    return Kokkos::atomic_fetch_add(ptr,-1);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator += (const_value_type& val) const {
+    const_value_type tmp = Kokkos::atomic_fetch_add(ptr,val);
+    return tmp+val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator += (volatile const_value_type& val) const {
+    const_value_type tmp = Kokkos::atomic_fetch_add(ptr,val);
+    return tmp+val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator -= (const_value_type& val) const {
+    const_value_type tmp = Kokkos::atomic_fetch_add(ptr,-val);
+    return tmp-val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator -= (volatile const_value_type& val) const {
+    const_value_type tmp = Kokkos::atomic_fetch_add(ptr,-val);
+    return tmp-val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator *= (const_value_type& val) const {
+    return Kokkos::atomic_mul_fetch(ptr,val);
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator *= (volatile const_value_type& val) const {
+    return Kokkos::atomic_mul_fetch(ptr,val);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator /= (const_value_type& val) const {
+    return Kokkos::atomic_div_fetch(ptr,val);
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator /= (volatile const_value_type& val) const {
+    return Kokkos::atomic_div_fetch(ptr,val);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator %= (const_value_type& val) const {
+    return Kokkos::atomic_mod_fetch(ptr,val);
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator %= (volatile const_value_type& val) const {
+    return Kokkos::atomic_mod_fetch(ptr,val);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator &= (const_value_type& val) const {
+    return Kokkos::atomic_and_fetch(ptr,val);
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator &= (volatile const_value_type& val) const {
+    return Kokkos::atomic_and_fetch(ptr,val);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator ^= (const_value_type& val) const {
+    return Kokkos::atomic_xor_fetch(ptr,val);
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator ^= (volatile const_value_type& val) const {
+    return Kokkos::atomic_xor_fetch(ptr,val);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator |= (const_value_type& val) const {
+    return Kokkos::atomic_or_fetch(ptr,val);
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator |= (volatile const_value_type& val) const {
+    return Kokkos::atomic_or_fetch(ptr,val);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator <<= (const_value_type& val) const {
+    return Kokkos::atomic_lshift_fetch(ptr,val);
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator <<= (volatile const_value_type& val) const {
+    return Kokkos::atomic_lshift_fetch(ptr,val);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator >>= (const_value_type& val) const {
+    return Kokkos::atomic_rshift_fetch(ptr,val);
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator >>= (volatile const_value_type& val) const {
+    return Kokkos::atomic_rshift_fetch(ptr,val);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator + (const_value_type& val) const {
+    return *ptr+val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator + (volatile const_value_type& val) const {
+    return *ptr+val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator - (const_value_type& val) const {
+    return *ptr-val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator - (volatile const_value_type& val) const {
+    return *ptr-val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator * (const_value_type& val) const {
+    return *ptr*val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator * (volatile const_value_type& val) const {
+    return *ptr*val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator / (const_value_type& val) const {
+    return *ptr/val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator / (volatile const_value_type& val) const {
+    return *ptr/val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator % (const_value_type& val) const {
+    return *ptr^val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator % (volatile const_value_type& val) const {
+    return *ptr^val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator ! () const {
+    return !*ptr;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator && (const_value_type& val) const {
+    return *ptr&&val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator && (volatile const_value_type& val) const {
+    return *ptr&&val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator || (const_value_type& val) const {
+    return *ptr|val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator || (volatile const_value_type& val) const {
+    return *ptr|val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator & (const_value_type& val) const {
+    return *ptr&val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator & (volatile const_value_type& val) const {
+    return *ptr&val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator | (const_value_type& val) const {
+    return *ptr|val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator | (volatile const_value_type& val) const {
+    return *ptr|val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator ^ (const_value_type& val) const {
+    return *ptr^val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator ^ (volatile const_value_type& val) const {
+    return *ptr^val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator ~ () const {
+    return ~*ptr;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator << (const unsigned int& val) const {
+    return *ptr<<val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator << (volatile const unsigned int& val) const {
+    return *ptr<<val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator >> (const unsigned int& val) const {
+    return *ptr>>val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  const_value_type operator >> (volatile const unsigned int& val) const {
+    return *ptr>>val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool operator == (const_value_type& val) const {
+    return *ptr == val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator == (volatile const_value_type& val) const {
+    return *ptr == val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool operator != (const_value_type& val) const {
+    return *ptr != val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator != (volatile const_value_type& val) const {
+    return *ptr != val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool operator >= (const_value_type& val) const {
+    return *ptr >= val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator >= (volatile const_value_type& val) const {
+    return *ptr >= val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool operator <= (const_value_type& val) const {
+    return *ptr <= val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator <= (volatile const_value_type& val) const {
+    return *ptr <= val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool operator < (const_value_type& val) const {
+    return *ptr < val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator < (volatile const_value_type& val) const {
+    return *ptr < val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool operator > (const_value_type& val) const {
+    return *ptr > val;
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator > (volatile const_value_type& val) const {
+    return *ptr > val;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  operator const_value_type () const {
+    //return Kokkos::atomic_load(ptr);
+    return *ptr;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  operator volatile non_const_value_type () volatile const {
+    //return Kokkos::atomic_load(ptr);
+    return *ptr;
+  }
+};
+
+template<class ViewTraits>
+class AtomicViewDataHandle {
+public:
+  typename ViewTraits::value_type* ptr;
+
+  KOKKOS_INLINE_FUNCTION
+  AtomicViewDataHandle()
+    : ptr(NULL)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  AtomicViewDataHandle(typename ViewTraits::value_type* ptr_)
+    :ptr(ptr_)
+  {}
+
+  template<class iType>
+  KOKKOS_INLINE_FUNCTION
+  AtomicDataElement<ViewTraits> operator[] (const iType& i) const {
+    return AtomicDataElement<ViewTraits>(ptr+i,AtomicViewConstTag());
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  operator typename ViewTraits::value_type * () const { return ptr ; }
+
+};
+
+template<unsigned Size>
+struct Kokkos_Atomic_is_only_allowed_with_32bit_and_64bit_scalars;
+
+template<>
+struct Kokkos_Atomic_is_only_allowed_with_32bit_and_64bit_scalars<4> {
+  typedef int type;
+};
+
+template<>
+struct Kokkos_Atomic_is_only_allowed_with_32bit_and_64bit_scalars<8> {
+  typedef int64_t type;
+};
+
+}} // namespace Kokkos::Impl
+
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Atomic_Windows.hpp b/lib/kokkos/core/src/impl/Kokkos_Atomic_Windows.hpp
new file mode 100644
index 0000000000..14066e8be2
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Atomic_Windows.hpp
@@ -0,0 +1,232 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+#ifndef KOKKOS_ATOMIC_WINDOWS_HPP
+#define KOKKOS_ATOMIC_WINDOWS_HPP
+#ifdef _WIN32
+
+#define NOMINMAX
+#include <winsock2.h>
+#include <Windows.h>
+
+namespace Kokkos {
+  namespace Impl {
+    _declspec(align(16))
+    struct cas128_t
+    {
+      LONGLONG lower;
+      LONGLONG upper;
+      KOKKOS_INLINE_FUNCTION
+        bool operator != (const cas128_t& a) const {
+        return (lower != a.lower) || upper != a.upper;
+      }
+    };
+  }
+
+  template < typename T >
+  KOKKOS_INLINE_FUNCTION
+    T atomic_compare_exchange(volatile T * const dest, const T & compare,
+    typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(LONG), const T & >::type val)
+  {
+    union U {
+      LONG i;
+      T t;
+      KOKKOS_INLINE_FUNCTION U() {};
+    } tmp;
+
+    tmp.i = _InterlockedCompareExchange((LONG*)dest, *((LONG*)&val), *((LONG*)&compare));
+    return tmp.t;
+  }
+
+  template < typename T >
+  KOKKOS_INLINE_FUNCTION
+    T atomic_compare_exchange(volatile T * const dest, const T & compare,
+    typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(LONGLONG), const T & >::type val)
+  {
+    union U {
+      LONGLONG i;
+      T t;
+      KOKKOS_INLINE_FUNCTION U() {};
+    } tmp;
+
+    tmp.i = _InterlockedCompareExchange64((LONGLONG*)dest, *((LONGLONG*)&val), *((LONGLONG*)&compare));
+    return tmp.t;
+  }
+
+  template < typename T >
+  KOKKOS_INLINE_FUNCTION
+    T atomic_compare_exchange(volatile T * const dest, const T & compare,
+    typename Kokkos::Impl::enable_if< sizeof(T) == sizeof(Impl::cas128_t), const T & >::type val)
+  {
+    union U {
+      Impl::cas128_t i;
+      T t;
+      KOKKOS_INLINE_FUNCTION U() {};
+    } tmp, newval;
+    newval.t = val;
+    _InterlockedCompareExchange128((LONGLONG*)dest, newval.i.upper, newval.i.lower, ((LONGLONG*)&compare));
+    tmp.t = dest;
+    return tmp.t;
+  }
+
+  template < typename T >
+  KOKKOS_INLINE_FUNCTION
+    T atomic_compare_exchange_strong(volatile T * const dest, const T & compare, const T & val)
+  {
+    return atomic_compare_exchange(dest,compare,val);
+  }
+
+  template< typename T >
+  T atomic_fetch_or(volatile T * const dest, const T val) {
+    T oldval = *dest;
+    T assume;
+    do {
+      assume = oldval;
+      T newval = val | oldval;
+      oldval = atomic_compare_exchange(dest, assume, newval);
+    } while (assume != oldval);
+
+    return oldval;
+  }
+
+  template< typename T >
+  T atomic_fetch_and(volatile T * const dest, const T val) {
+    T oldval = *dest;
+    T assume;
+    do {
+      assume = oldval;
+      T newval = val & oldval;
+      oldval = atomic_compare_exchange(dest, assume, newval);
+    } while (assume != oldval);
+
+    return oldval;
+  }
+
+  template< typename T >
+  T atomic_fetch_add(volatile T * const dest, const T val) {
+    T oldval = *dest;
+    T assume;
+    do {
+      assume = oldval;
+      T newval = val + oldval;
+      oldval = atomic_compare_exchange(dest, assume, newval);
+    } while (assume != oldval);
+
+    return oldval;
+  }
+
+  template< typename T >
+  T atomic_fetch_sub(volatile T * const dest, const T val) {
+    T oldval = *dest;
+    T assume;
+    do {
+      assume = oldval;
+      T newval = val - oldval;
+      oldval = atomic_compare_exchange(dest, assume, newval);
+    } while (assume != oldval);
+
+    return oldval;
+  }
+
+  template< typename T >
+  T atomic_exchange(volatile T * const dest, const T val) {
+    T oldval = *dest;
+    T assume;
+    do {
+      assume = oldval;
+      oldval = atomic_compare_exchange(dest, assume, val);
+    } while (assume != oldval);
+
+    return oldval;
+  }
+
+  template< typename T >
+  void atomic_or(volatile T * const dest, const T val) {
+    atomic_fetch_or(dest, val);
+  }
+
+  template< typename T >
+  void atomic_and(volatile T * const dest, const T val) {
+    atomic_fetch_and(dest, val);
+  }
+
+  template< typename T >
+  void atomic_add(volatile T * const dest, const T val) {
+    atomic_fetch_add(dest, val);
+  }
+
+  template< typename T >
+  void atomic_sub(volatile T * const dest, const T val) {
+    atomic_fetch_sub(dest, val);
+  }
+
+  template< typename T >
+  void atomic_assign(volatile T * const dest, const T val) {
+    atomic_fetch_exchange(dest, val);
+  }
+
+  template< typename T >
+  T atomic_increment(volatile T * const dest) {
+    T oldval = *dest;
+    T assume;
+    do {
+      assume = oldval;
+      T newval = assume++;
+      oldval = atomic_compare_exchange(dest, assume, newval);
+    } while (assume != oldval);
+  }
+
+  template< typename T >
+  T atomic_decrement(volatile T * const dest) {
+    T oldval = *dest;
+    T assume;
+    do {
+      assume = oldval;
+      T newval = assume--;
+      oldval = atomic_compare_exchange(dest, assume, newval);
+    } while (assume != oldval);
+  }
+
+}
+#endif
+#endif
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_BitOps.hpp b/lib/kokkos/core/src/impl/Kokkos_BitOps.hpp
new file mode 100644
index 0000000000..0ffbc0548a
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_BitOps.hpp
@@ -0,0 +1,122 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_BITOPS_HPP
+#define KOKKOS_BITOPS_HPP
+
+#include <Kokkos_Macros.hpp>
+#include <stdint.h>
+#include <climits>
+
+namespace Kokkos {
+namespace Impl {
+
+KOKKOS_FORCEINLINE_FUNCTION
+int bit_scan_forward( unsigned i )
+{
+#if defined( __CUDA_ARCH__ )
+  return __ffs(i) - 1;
+#elif defined( __GNUC__ ) || defined( __GNUG__ )
+  return __builtin_ffs(i) - 1;
+#elif defined( __INTEL_COMPILER )
+  return _bit_scan_forward(i);
+#else
+
+  unsigned t = 1u;
+  int r = 0;
+  while ( i && ( i & t == 0 ) )
+  {
+    t = t << 1;
+    ++r;
+  }
+  return r;
+#endif
+}
+
+KOKKOS_FORCEINLINE_FUNCTION
+int bit_scan_reverse( unsigned i )
+{
+  enum { shift = static_cast<int>( sizeof(unsigned) * CHAR_BIT - 1 ) };
+#if defined( __CUDA_ARCH__ )
+  return shift - __clz(i);
+#elif defined( __GNUC__ ) || defined( __GNUG__ )
+  return shift - __builtin_clz(i);
+#elif defined( __INTEL_COMPILER )
+  return _bit_scan_reverse(i);
+#else
+  unsigned t = 1u << shift;
+  int r = 0;
+  while ( i && ( i & t == 0 ) )
+  {
+    t = t >> 1;
+    ++r;
+  }
+  return r;
+#endif
+}
+
+/// Count the number of bits set.
+KOKKOS_FORCEINLINE_FUNCTION
+int bit_count( unsigned i )
+{
+#if defined( __CUDA_ARCH__ )
+  return __popc(i);
+#elif defined( __GNUC__ ) || defined( __GNUG__ )
+  return __builtin_popcount(i);
+#elif defined ( __INTEL_COMPILER )
+  return _popcnt32(i);
+#else
+  // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetNaive
+  i = i - ( ( i >> 1 ) & ~0u / 3u );                             // temp
+  i = ( i & ~0u / 15u * 3u ) + ( ( i >> 2 ) & ~0u / 15u * 3u );  // temp
+  i = ( i + ( i >> 4 ) ) & ~0u / 255u * 15u;                     // temp
+
+  // count
+  return (int)( ( i * ( ~0u / 255u ) ) >> ( sizeof(unsigned) - 1 ) * CHAR_BIT );
+#endif
+}
+
+} // namespace Impl
+} // namespace Kokkos
+
+#endif // KOKKOS_BITOPS_HPP
diff --git a/lib/kokkos/core/src/impl/Kokkos_CPUDiscovery.cpp b/lib/kokkos/core/src/impl/Kokkos_CPUDiscovery.cpp
new file mode 100644
index 0000000000..b9d23bd815
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_CPUDiscovery.cpp
@@ -0,0 +1,124 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+
+namespace Kokkos {
+namespace Impl {
+
+//The following function (processors_per_node) is copied from here:
+// https://lists.gnu.org/archive/html/autoconf/2002-08/msg00126.html
+// Philip Willoughby
+
+int processors_per_node() {
+  int nprocs = -1;
+  int nprocs_max = -1;
+#ifdef _WIN32
+#ifndef _SC_NPROCESSORS_ONLN
+SYSTEM_INFO info;
+GetSystemInfo(&info);
+#define sysconf(a) info.dwNumberOfProcessors
+#define _SC_NPROCESSORS_ONLN
+#endif
+#endif
+#ifdef _SC_NPROCESSORS_ONLN
+  nprocs = sysconf(_SC_NPROCESSORS_ONLN);
+  if (nprocs < 1)
+  {
+    return -1;
+  }
+  nprocs_max = sysconf(_SC_NPROCESSORS_CONF);
+  if (nprocs_max < 1)
+  {
+    return -1;
+  }
+  return nprocs;
+#else
+  return -1;
+#endif
+}
+
+int mpi_ranks_per_node() {
+  char *str;
+  int ppn = 1;
+  if ((str = getenv("SLURM_TASKS_PER_NODE"))) {
+    ppn = atoi(str);
+    if(ppn<=0) ppn = 1;
+  }
+  if ((str = getenv("MV2_COMM_WORLD_LOCAL_SIZE"))) {
+    ppn = atoi(str);
+    if(ppn<=0) ppn = 1;
+  }
+  if ((str = getenv("OMPI_COMM_WORLD_LOCAL_SIZE"))) {
+    ppn = atoi(str);
+    if(ppn<=0) ppn = 1;
+  }
+  return ppn;
+}
+
+int mpi_local_rank_on_node() {
+  char *str;
+  int local_rank=0;
+  if ((str = getenv("SLURM_LOCALID"))) {
+    local_rank = atoi(str);
+  }
+  if ((str = getenv("MV2_COMM_WORLD_LOCAL_RANK"))) {
+    local_rank = atoi(str);
+  }
+  if ((str = getenv("OMPI_COMM_WORLD_LOCAL_RANK"))) {
+    local_rank = atoi(str);
+  }
+  return local_rank;
+}
+
+}
+}
diff --git a/lib/kokkos/core/src/impl/Kokkos_CPUDiscovery.hpp b/lib/kokkos/core/src/impl/Kokkos_CPUDiscovery.hpp
new file mode 100644
index 0000000000..af474bc406
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_CPUDiscovery.hpp
@@ -0,0 +1,51 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+namespace Kokkos {
+namespace Impl {
+
+int processors_per_node();
+int mpi_ranks_per_node();
+int mpi_local_rank_on_node();
+
+}
+}
diff --git a/lib/kokkos/core/src/impl/Kokkos_Core.cpp b/lib/kokkos/core/src/impl/Kokkos_Core.cpp
new file mode 100644
index 0000000000..567a214140
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Core.cpp
@@ -0,0 +1,454 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <cctype>
+#include <cstring>
+#include <iostream>
+#include <cstdlib>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+namespace {
+
+bool is_unsigned_int(const char* str)
+{
+  const size_t len = strlen (str);
+  for (size_t i = 0; i < len; ++i) {
+    if (! isdigit (str[i])) {
+      return false;
+    }
+  }
+  return true;
+}
+
+void initialize_internal(const InitArguments& args)
+{
+// This is an experimental setting
+// For KNL in Flat mode this variable should be set, so that
+// memkind allocates high bandwidth memory correctly.
+#ifdef KOKKOS_HAVE_HBWSPACE
+setenv("MEMKIND_HBW_NODES", "1", 0);
+#endif
+
+  // Protect declarations, to prevent "unused variable" warnings.
+#if defined( KOKKOS_HAVE_OPENMP ) || defined( KOKKOS_HAVE_PTHREAD )
+  const int num_threads = args.num_threads;
+  const int use_numa = args.num_numa;
+#endif // defined( KOKKOS_HAVE_OPENMP ) || defined( KOKKOS_HAVE_PTHREAD )
+#if defined( KOKKOS_HAVE_CUDA )
+  const int use_gpu = args.device_id;
+#endif // defined( KOKKOS_HAVE_CUDA )
+
+#if defined( KOKKOS_HAVE_OPENMP )
+  if( Impl::is_same< Kokkos::OpenMP , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::OpenMP , Kokkos::HostSpace::execution_space >::value ) {
+    if(num_threads>0) {
+      if(use_numa>0) {
+        Kokkos::OpenMP::initialize(num_threads,use_numa);
+      }
+      else {
+        Kokkos::OpenMP::initialize(num_threads);
+      }
+    } else {
+      Kokkos::OpenMP::initialize();
+    }
+    //std::cout << "Kokkos::initialize() fyi: OpenMP enabled and initialized" << std::endl ;
+  }
+  else {
+    //std::cout << "Kokkos::initialize() fyi: OpenMP enabled but not initialized" << std::endl ;
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+  if( Impl::is_same< Kokkos::Threads , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::Threads , Kokkos::HostSpace::execution_space >::value ) {
+    if(num_threads>0) {
+      if(use_numa>0) {
+        Kokkos::Threads::initialize(num_threads,use_numa);
+      }
+      else {
+        Kokkos::Threads::initialize(num_threads);
+      }
+    } else {
+      Kokkos::Threads::initialize();
+    }
+    //std::cout << "Kokkos::initialize() fyi: Pthread enabled and initialized" << std::endl ;
+  }
+  else {
+    //std::cout << "Kokkos::initialize() fyi: Pthread enabled but not initialized" << std::endl ;
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_SERIAL )
+  // Prevent "unused variable" warning for 'args' input struct.  If
+  // Serial::initialize() ever needs to take arguments from the input
+  // struct, you may remove this line of code.
+  (void) args;
+
+  if( Impl::is_same< Kokkos::Serial , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::Serial , Kokkos::HostSpace::execution_space >::value ) {
+    Kokkos::Serial::initialize();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_CUDA )
+  if( Impl::is_same< Kokkos::Cuda , Kokkos::DefaultExecutionSpace >::value || 0 < use_gpu ) {
+    if (use_gpu > -1) {
+      Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice( use_gpu ) );
+    }
+    else {
+      Kokkos::Cuda::initialize();
+    }
+    //std::cout << "Kokkos::initialize() fyi: Cuda enabled and initialized" << std::endl ;
+  }
+#endif
+
+#if (KOKKOS_ENABLE_PROFILING)
+    Kokkos::Profiling::initialize();
+#endif
+}
+
+void finalize_internal( const bool all_spaces = false )
+{
+
+#if defined( KOKKOS_HAVE_CUDA )
+  if( Impl::is_same< Kokkos::Cuda , Kokkos::DefaultExecutionSpace >::value || all_spaces ) {
+    if(Kokkos::Cuda::is_initialized())
+      Kokkos::Cuda::finalize();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_OPENMP )
+  if( Impl::is_same< Kokkos::OpenMP , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::OpenMP , Kokkos::HostSpace::execution_space >::value ||
+      all_spaces ) {
+    if(Kokkos::OpenMP::is_initialized())
+      Kokkos::OpenMP::finalize();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+  if( Impl::is_same< Kokkos::Threads , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::Threads , Kokkos::HostSpace::execution_space >::value ||
+      all_spaces ) {
+    if(Kokkos::Threads::is_initialized())
+      Kokkos::Threads::finalize();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_SERIAL )
+  if( Impl::is_same< Kokkos::Serial , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::Serial , Kokkos::HostSpace::execution_space >::value ||
+      all_spaces ) {
+    if(Kokkos::Serial::is_initialized())
+      Kokkos::Serial::finalize();
+  }
+#endif
+
+#if (KOKKOS_ENABLE_PROFILING)
+    Kokkos::Profiling::finalize();
+#endif
+
+}
+
+void fence_internal()
+{
+
+#if defined( KOKKOS_HAVE_CUDA )
+  if( Impl::is_same< Kokkos::Cuda , Kokkos::DefaultExecutionSpace >::value ) {
+    Kokkos::Cuda::fence();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_OPENMP )
+  if( Impl::is_same< Kokkos::OpenMP , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::OpenMP , Kokkos::HostSpace::execution_space >::value ) {
+    Kokkos::OpenMP::fence();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+  if( Impl::is_same< Kokkos::Threads , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::Threads , Kokkos::HostSpace::execution_space >::value ) {
+    Kokkos::Threads::fence();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_SERIAL )
+  if( Impl::is_same< Kokkos::Serial , Kokkos::DefaultExecutionSpace >::value ||
+      Impl::is_same< Kokkos::Serial , Kokkos::HostSpace::execution_space >::value ) {
+    Kokkos::Serial::fence();
+  }
+#endif
+
+}
+
+} // namespace
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+void initialize(int& narg, char* arg[])
+{
+    int num_threads = -1;
+    int numa = -1;
+    int device = -1;
+
+    int kokkos_threads_found = 0;
+    int kokkos_numa_found = 0;
+    int kokkos_device_found = 0;
+    int kokkos_ndevices_found = 0;
+
+    int iarg = 0;
+
+    while (iarg < narg) {
+      if ((strncmp(arg[iarg],"--kokkos-threads",16) == 0) || (strncmp(arg[iarg],"--threads",9) == 0)) {
+        //Find the number of threads (expecting --threads=XX)
+        if (!((strncmp(arg[iarg],"--kokkos-threads=",17) == 0) || (strncmp(arg[iarg],"--threads=",10) == 0)))
+          Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--threads/--kokkos-threads'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+
+        char* number =  strchr(arg[iarg],'=')+1;
+
+        if(!Impl::is_unsigned_int(number) || (strlen(number)==0))
+          Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--threads/--kokkos-threads'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+
+        if((strncmp(arg[iarg],"--kokkos-threads",16) == 0) || !kokkos_threads_found)
+          num_threads = atoi(number);
+
+        //Remove the --kokkos-threads argument from the list but leave --threads
+        if(strncmp(arg[iarg],"--kokkos-threads",16) == 0) {
+          for(int k=iarg;k<narg-1;k++) {
+            arg[k] = arg[k+1];
+          }
+          kokkos_threads_found=1;
+          narg--;
+        } else {
+          iarg++;
+        }
+      } else if ((strncmp(arg[iarg],"--kokkos-numa",13) == 0) || (strncmp(arg[iarg],"--numa",6) == 0)) {
+        //Find the number of numa (expecting --numa=XX)
+        if (!((strncmp(arg[iarg],"--kokkos-numa=",14) == 0) || (strncmp(arg[iarg],"--numa=",7) == 0)))
+          Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--numa/--kokkos-numa'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+
+        char* number =  strchr(arg[iarg],'=')+1;
+
+        if(!Impl::is_unsigned_int(number) || (strlen(number)==0))
+          Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--numa/--kokkos-numa'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+
+        if((strncmp(arg[iarg],"--kokkos-numa",13) == 0) || !kokkos_numa_found)
+          numa = atoi(number);
+
+        //Remove the --kokkos-numa argument from the list but leave --numa
+        if(strncmp(arg[iarg],"--kokkos-numa",13) == 0) {
+          for(int k=iarg;k<narg-1;k++) {
+            arg[k] = arg[k+1];
+          }
+          kokkos_numa_found=1;
+          narg--;
+        } else {
+          iarg++;
+        }
+      } else if ((strncmp(arg[iarg],"--kokkos-device",15) == 0) || (strncmp(arg[iarg],"--device",8) == 0)) {
+        //Find the number of device (expecting --device=XX)
+        if (!((strncmp(arg[iarg],"--kokkos-device=",16) == 0) || (strncmp(arg[iarg],"--device=",9) == 0)))
+          Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--device/--kokkos-device'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+
+        char* number =  strchr(arg[iarg],'=')+1;
+
+        if(!Impl::is_unsigned_int(number) || (strlen(number)==0))
+          Impl::throw_runtime_exception("Error: expecting an '=INT' after command line argument '--device/--kokkos-device'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+
+        if((strncmp(arg[iarg],"--kokkos-device",15) == 0) || !kokkos_device_found)
+          device = atoi(number);
+
+        //Remove the --kokkos-device argument from the list but leave --device
+        if(strncmp(arg[iarg],"--kokkos-device",15) == 0) {
+          for(int k=iarg;k<narg-1;k++) {
+            arg[k] = arg[k+1];
+          }
+          kokkos_device_found=1;
+          narg--;
+        } else {
+          iarg++;
+        }
+      } else if ((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || (strncmp(arg[iarg],"--ndevices",10) == 0)) {
+
+        //Find the number of device (expecting --device=XX)
+        if (!((strncmp(arg[iarg],"--kokkos-ndevices=",18) == 0) || (strncmp(arg[iarg],"--ndevices=",11) == 0)))
+          Impl::throw_runtime_exception("Error: expecting an '=INT[,INT]' after command line argument '--ndevices/--kokkos-ndevices'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+
+        int ndevices=-1;
+        int skip_device = 9999;
+
+        char* num1 = strchr(arg[iarg],'=')+1;
+        char* num2 = strpbrk(num1,",");
+        int num1_len = num2==NULL?strlen(num1):num2-num1;
+        char* num1_only = new char[num1_len+1];
+        strncpy(num1_only,num1,num1_len);
+        num1_only[num1_len]=0;
+
+        if(!Impl::is_unsigned_int(num1_only) || (strlen(num1_only)==0)) {
+          Impl::throw_runtime_exception("Error: expecting an integer number after command line argument '--kokkos-ndevices'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+        }
+        if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found)
+          ndevices = atoi(num1_only);
+
+        if( num2 != NULL ) {
+          if(( !Impl::is_unsigned_int(num2+1) ) || (strlen(num2)==1) )
+            Impl::throw_runtime_exception("Error: expecting an integer number after command line argument '--kokkos-ndevices=XX,'. Raised by Kokkos::initialize(int narg, char* argc[]).");
+
+          if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found)
+            skip_device = atoi(num2+1);
+        }
+
+        if((strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) || !kokkos_ndevices_found) {
+          char *str;
+          if ((str = getenv("SLURM_LOCALID"))) {
+            int local_rank = atoi(str);
+            device = local_rank % ndevices;
+            if (device >= skip_device) device++;
+          }
+          if ((str = getenv("MV2_COMM_WORLD_LOCAL_RANK"))) {
+            int local_rank = atoi(str);
+            device = local_rank % ndevices;
+            if (device >= skip_device) device++;
+          }
+          if ((str = getenv("OMPI_COMM_WORLD_LOCAL_RANK"))) {
+            int local_rank = atoi(str);
+            device = local_rank % ndevices;
+            if (device >= skip_device) device++;
+          }
+          if(device==-1) {
+            device = 0;
+            if (device >= skip_device) device++;
+          }
+        }
+
+        //Remove the --kokkos-ndevices argument from the list but leave --ndevices
+        if(strncmp(arg[iarg],"--kokkos-ndevices",17) == 0) {
+          for(int k=iarg;k<narg-1;k++) {
+            arg[k] = arg[k+1];
+          }
+          kokkos_ndevices_found=1;
+          narg--;
+        } else {
+          iarg++;
+        }
+      } else if ((strcmp(arg[iarg],"--kokkos-help") == 0) || (strcmp(arg[iarg],"--help") == 0)) {
+         std::cout << std::endl;
+         std::cout << "--------------------------------------------------------------------------------" << std::endl;
+         std::cout << "-------------Kokkos command line arguments--------------------------------------" << std::endl;
+         std::cout << "--------------------------------------------------------------------------------" << std::endl;
+         std::cout << "The following arguments exist also without prefix 'kokkos' (e.g. --help)." << std::endl;
+         std::cout << "The prefixed arguments will be removed from the list by Kokkos::initialize()," << std::endl;
+         std::cout << "the non-prefixed ones are not removed. Prefixed versions take precedence over " << std::endl;
+         std::cout << "non prefixed ones, and the last occurence of an argument overwrites prior" << std::endl;
+         std::cout << "settings." << std::endl;
+         std::cout << std::endl;
+         std::cout << "--kokkos-help               : print this message" << std::endl;
+         std::cout << "--kokkos-threads=INT        : specify total number of threads or" << std::endl;
+         std::cout << "                              number of threads per NUMA region if " << std::endl;
+         std::cout << "                              used in conjunction with '--numa' option. " << std::endl;
+         std::cout << "--kokkos-numa=INT           : specify number of NUMA regions used by process." << std::endl;
+         std::cout << "--kokkos-device=INT         : specify device id to be used by Kokkos. " << std::endl;
+         std::cout << "--kokkos-ndevices=INT[,INT] : used when running MPI jobs. Specify number of" << std::endl;
+         std::cout << "                              devices per node to be used. Process to device" << std::endl;
+         std::cout << "                              mapping happens by obtaining the local MPI rank" << std::endl;
+         std::cout << "                              and assigning devices round-robin. The optional" << std::endl;
+         std::cout << "                              second argument allows for an existing device" << std::endl;
+         std::cout << "                              to be ignored. This is most useful on workstations" << std::endl;
+         std::cout << "                              with multiple GPUs of which one is used to drive" << std::endl;
+         std::cout << "                              screen output." << std::endl;
+         std::cout << std::endl;
+         std::cout << "--------------------------------------------------------------------------------" << std::endl;
+         std::cout << std::endl;
+
+         //Remove the --kokkos-help argument from the list but leave --ndevices
+         if(strcmp(arg[iarg],"--kokkos-help") == 0) {
+           for(int k=iarg;k<narg-1;k++) {
+             arg[k] = arg[k+1];
+           }
+           narg--;
+         } else {
+           iarg++;
+         }
+      } else
+      iarg++;
+    }
+
+    InitArguments arguments;
+    arguments.num_threads = num_threads;
+    arguments.num_numa = numa;
+    arguments.device_id = device;
+    Impl::initialize_internal(arguments);
+}
+
+void initialize(const InitArguments& arguments) {
+  Impl::initialize_internal(arguments);
+}
+
+void finalize()
+{
+  Impl::finalize_internal();
+}
+
+void finalize_all()
+{
+  enum { all_spaces = true };
+  Impl::finalize_internal( all_spaces );
+}
+
+void fence()
+{
+  Impl::fence_internal();
+}
+
+} // namespace Kokkos
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Error.cpp b/lib/kokkos/core/src/impl/Kokkos_Error.cpp
new file mode 100644
index 0000000000..36224990d0
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Error.cpp
@@ -0,0 +1,193 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <ostream>
+#include <sstream>
+#include <iomanip>
+#include <stdexcept>
+#include <impl/Kokkos_Error.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+void host_abort( const char * const message )
+{
+  fwrite(message,1,strlen(message),stderr);
+  fflush(stderr);
+  ::abort();
+}
+
+void throw_runtime_exception( const std::string & msg )
+{
+  std::ostringstream o ;
+  o << msg ;
+  traceback_callstack( o );
+  throw std::runtime_error( o.str() );
+}
+
+
+std::string human_memory_size(size_t arg_bytes)
+{
+  double bytes = arg_bytes;
+  const double K = 1024;
+  const double M = K*1024;
+  const double G = M*1024;
+
+  std::ostringstream out;
+  if (bytes < K) {
+    out << std::setprecision(4) << bytes << " B";
+  } else if (bytes < M) {
+    bytes /= K;
+    out << std::setprecision(4) << bytes << " K";
+  } else if (bytes < G) {
+    bytes /= M;
+    out << std::setprecision(4) << bytes << " M";
+  } else {
+    bytes /= G;
+    out << std::setprecision(4) << bytes << " G";
+  }
+  return out.str();
+}
+
+}
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if defined( __GNUC__ ) && defined( ENABLE_TRACEBACK )
+
+/*  This is only known to work with GNU C++
+ *  Must be compiled with '-rdynamic'
+ *  Must be linked with   '-ldl'
+ */
+
+/* Print call stack into an error stream,
+ * so one knows in which function the error occured.
+ *
+ * Code copied from:
+ *   http://stupefydeveloper.blogspot.com/2008/10/cc-call-stack.html
+ *
+ * License on this site:
+ *   This blog is licensed under a
+ *   Creative Commons Attribution-Share Alike 3.0 Unported License.
+ *
+ *   http://creativecommons.org/licenses/by-sa/3.0/
+ *
+ * Modified to output to std::ostream.
+ */
+#include <signal.h>
+#include <execinfo.h>
+#include <cxxabi.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+namespace Kokkos {
+namespace Impl {
+
+void traceback_callstack( std::ostream & msg )
+{
+  using namespace abi;
+
+  enum { MAX_DEPTH = 32 };
+
+  void *trace[MAX_DEPTH];
+  Dl_info dlinfo;
+
+  int status;
+
+  int trace_size = backtrace(trace, MAX_DEPTH);
+
+  msg << std::endl << "Call stack {" << std::endl ;
+
+  for (int i=1; i<trace_size; ++i)
+  {
+    if(!dladdr(trace[i], &dlinfo))
+        continue;
+
+    const char * symname = dlinfo.dli_sname;
+
+    char * demangled = __cxa_demangle(symname, NULL, 0, &status);
+
+    if ( status == 0 && demangled ) {
+      symname = demangled;
+    }
+
+    if ( symname && *symname != 0 ) {
+      msg << "  object: " << dlinfo.dli_fname
+          << " function: " << symname
+          << std::endl ;
+    }
+
+    if ( demangled ) {
+        free(demangled);
+    }
+  }
+  msg << "}" ;
+}
+
+}
+}
+
+#else
+
+namespace Kokkos {
+namespace Impl {
+
+void traceback_callstack( std::ostream & msg )
+{
+  msg << std::endl << "Traceback functionality not available" << std::endl ;
+}
+
+}
+}
+
+#endif
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Error.hpp b/lib/kokkos/core/src/impl/Kokkos_Error.hpp
new file mode 100644
index 0000000000..5f88d66206
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Error.hpp
@@ -0,0 +1,82 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_IMPL_ERROR_HPP
+#define KOKKOS_IMPL_ERROR_HPP
+
+#include <string>
+#include <iosfwd>
+#include <KokkosCore_config.h>
+#ifdef KOKKOS_HAVE_CUDA
+#include <Cuda/Kokkos_Cuda_abort.hpp>
+#endif
+
+namespace Kokkos {
+namespace Impl {
+
+void host_abort( const char * const );
+
+void throw_runtime_exception( const std::string & );
+
+void traceback_callstack( std::ostream & );
+
+std::string human_memory_size(size_t arg_bytes);
+
+}
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+namespace Kokkos {
+inline
+void abort( const char * const message ) { Kokkos::Impl::host_abort(message); }
+}
+#endif /* defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_CUDA ) */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_IMPL_ERROR_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_ExecPolicy.cpp b/lib/kokkos/core/src/impl/Kokkos_ExecPolicy.cpp
new file mode 100644
index 0000000000..cabf5a3cac
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_ExecPolicy.cpp
@@ -0,0 +1,19 @@
+#include <Kokkos_Core.hpp>
+namespace Kokkos {
+namespace Impl {
+    PerTeamValue::PerTeamValue(int arg):value(arg) {}
+
+    PerThreadValue::PerThreadValue(int arg):value(arg) {}
+}
+
+Impl::PerTeamValue PerTeam(const int& arg)
+{
+  return Impl::PerTeamValue(arg);
+}
+
+Impl::PerThreadValue PerThread(const int& arg)
+{
+  return Impl::PerThreadValue(arg);
+}
+
+}
diff --git a/lib/kokkos/core/src/impl/Kokkos_FunctorAdapter.hpp b/lib/kokkos/core/src/impl/Kokkos_FunctorAdapter.hpp
new file mode 100644
index 0000000000..78b6794491
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_FunctorAdapter.hpp
@@ -0,0 +1,1131 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_FUNCTORADAPTER_HPP
+#define KOKKOS_FUNCTORADAPTER_HPP
+
+#include <cstddef>
+#include <Kokkos_Core_fwd.hpp>
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_Tags.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ArgTag , class Enable = void >
+struct FunctorDeclaresValueType : public Impl::false_type {};
+
+template< class FunctorType , class ArgTag >
+struct FunctorDeclaresValueType< FunctorType , ArgTag
+                               , typename Impl::enable_if_type< typename FunctorType::value_type >::type >
+  : public Impl::true_type {};
+
+
+/** \brief  Query Functor and execution policy argument tag for value type.
+ *
+ *  If C++11 enabled and 'value_type' is not explicitly declared then attempt
+ *  to deduce the type from FunctorType::operator().
+ */
+template< class FunctorType , class ArgTag , bool Dec = FunctorDeclaresValueType<FunctorType,ArgTag>::value >
+struct FunctorValueTraits
+{
+  typedef void value_type ;
+  typedef void pointer_type ;
+  typedef void reference_type ;
+  typedef void functor_type ;
+
+  enum { StaticValueSize = 0 };
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  unsigned value_count( const FunctorType & ) { return 0 ; }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  unsigned value_size( const FunctorType & ) { return 0 ; }
+};
+
+template<class ArgTag>
+struct FunctorValueTraits<void, ArgTag,false>
+{
+  typedef void value_type ;
+  typedef void pointer_type ;
+  typedef void reference_type ;
+  typedef void functor_type ;
+};
+
+/** \brief  FunctorType::value_type is explicitly declared so use it.
+ *
+ * Two options for declaration
+ *
+ *   1) A plain-old-data (POD) type
+ *        typedef {pod_type} value_type ;
+ *
+ *   2) An array of POD of a runtime specified count.
+ *        typedef {pod_type} value_type[] ;
+ *        const unsigned     value_count ;
+ */
+template< class FunctorType , class ArgTag >
+struct FunctorValueTraits< FunctorType , ArgTag , true /* == exists FunctorType::value_type */ >
+{
+  typedef typename Impl::remove_extent< typename FunctorType::value_type >::type  value_type ;
+  typedef FunctorType functor_type;
+
+  static_assert( 0 == ( sizeof(value_type) % sizeof(int) ) ,
+    "Reduction functor's declared value_type requires: 0 == sizeof(value_type) % sizeof(int)" );
+
+  // If not an array then what is the sizeof(value_type)
+  enum { StaticValueSize = Impl::is_array< typename FunctorType::value_type >::value ? 0 : sizeof(value_type) };
+
+  typedef value_type                 * pointer_type ;
+
+  // The reference_type for an array is 'value_type *'
+  // The reference_type for a single value is 'value_type &'
+
+  typedef typename Impl::if_c< ! StaticValueSize , value_type *
+                                                 , value_type & >::type  reference_type ;
+
+  // Number of values if single value
+  template< class F >
+  KOKKOS_FORCEINLINE_FUNCTION static
+  typename Impl::enable_if< Impl::is_same<F,FunctorType>::value && StaticValueSize , unsigned >::type
+    value_count( const F & ) { return 1 ; }
+
+  // Number of values if an array, protect via templating because 'f.value_count'
+  // will only exist when the functor declares the value_type to be an array.
+  template< class F >
+  KOKKOS_FORCEINLINE_FUNCTION static
+  typename Impl::enable_if< Impl::is_same<F,FunctorType>::value && ! StaticValueSize , unsigned >::type
+    value_count( const F & f ) { return f.value_count ; }
+
+  // Total size of the value
+  KOKKOS_INLINE_FUNCTION static
+  unsigned value_size( const FunctorType & f ) { return value_count( f ) * sizeof(value_type) ; }
+};
+
+
+template< class FunctorType , class ArgTag >
+struct FunctorValueTraits< FunctorType
+                         , ArgTag
+                         , false  /* == exists FunctorType::value_type */
+                         >
+{
+private:
+
+  struct VOIDTAG {};   // Allow declaration of non-matching operator() with void argument tag.
+  struct REJECTTAG {}; // Reject tagged operator() when using non-tagged execution policy.
+
+  typedef typename
+    Impl::if_c< Impl::is_same< ArgTag , void >::value , VOIDTAG , ArgTag >::type tag_type ;
+
+  //----------------------------------------
+  // parallel_for operator without a tag:
+
+  template< class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static VOIDTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( ArgMember ) const ) {}
+
+  template< class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static VOIDTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const ArgMember & ) const ) {}
+
+  template< class TagType , class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( TagType , ArgMember ) const ) {}
+
+  template< class TagType , class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( TagType , const ArgMember & ) const ) {}
+
+  template< class TagType , class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const TagType & , ArgMember ) const ) {}
+
+  template< class TagType , class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const TagType & , const ArgMember & ) const ) {}
+
+  //----------------------------------------
+  // parallel_for operator with a tag:
+
+  template< class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static VOIDTAG deduce_reduce_type( tag_type , void (FunctorType::*)( tag_type , ArgMember ) const ) {}
+
+  template< class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static VOIDTAG deduce_reduce_type( tag_type , void (FunctorType::*)( const tag_type & , ArgMember ) const ) {}
+
+  template< class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static VOIDTAG deduce_reduce_type( tag_type , void (FunctorType::*)( tag_type , const ArgMember & ) const ) {}
+
+  template< class ArgMember >
+  KOKKOS_INLINE_FUNCTION
+  static VOIDTAG deduce_reduce_type( tag_type , void (FunctorType::*)( const tag_type & , const ArgMember & ) const ) {}
+
+  //----------------------------------------
+  // parallel_reduce operator without a tag:
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( VOIDTAG , void (FunctorType::*)( ArgMember , T & ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const ArgMember & , T & ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( TagType , ArgMember , T & ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( TagType , const ArgMember & , T & ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const TagType & , ArgMember , T & ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const TagType & , const ArgMember & , T & ) const ) {}
+
+  //----------------------------------------
+  // parallel_reduce operator with a tag:
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( tag_type , ArgMember , T & ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( const tag_type & , ArgMember , T & ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( tag_type , const ArgMember & , T & ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( const tag_type & , const ArgMember & , T & ) const ) {}
+
+  //----------------------------------------
+  // parallel_scan operator without a tag:
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( VOIDTAG , void (FunctorType::*)( ArgMember , T & , bool ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const ArgMember & , T & , bool ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( TagType , ArgMember , T & , bool ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( TagType , const ArgMember & , T & , bool ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const TagType & , ArgMember , T & , bool ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const TagType & , const ArgMember & , T & , bool ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( VOIDTAG , void (FunctorType::*)( ArgMember , T & , const bool& ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const ArgMember & , T & , const bool& ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( TagType , ArgMember , T & , const bool& ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( TagType , const ArgMember & , T & , const bool& ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const TagType & , ArgMember , T & , const bool& ) const ) {}
+
+  template< class TagType , class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static REJECTTAG deduce_reduce_type( VOIDTAG , void (FunctorType::*)( const TagType & , const ArgMember & , T & , const bool& ) const ) {}
+  //----------------------------------------
+  // parallel_scan operator with a tag:
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( tag_type , ArgMember , T & , bool ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( const tag_type & , ArgMember , T & , bool ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( tag_type , const ArgMember& , T & , bool ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( const tag_type & , const ArgMember& , T & , bool ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( tag_type , ArgMember , T & , const bool& ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( const tag_type & , ArgMember , T & , const bool& ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( tag_type , const ArgMember& , T & , const bool& ) const ) {}
+
+  template< class ArgMember , class T >
+  KOKKOS_INLINE_FUNCTION
+  static T deduce_reduce_type( tag_type , void (FunctorType::*)( const tag_type & , const ArgMember& , T & , const bool& ) const ) {}
+  //----------------------------------------
+
+  typedef decltype( deduce_reduce_type( tag_type() , & FunctorType::operator() ) ) ValueType ;
+
+  enum { IS_VOID   = Impl::is_same<VOIDTAG  ,ValueType>::value };
+  enum { IS_REJECT = Impl::is_same<REJECTTAG,ValueType>::value };
+
+public:
+
+  typedef typename Impl::if_c< IS_VOID || IS_REJECT , void , ValueType   >::type  value_type ;
+  typedef typename Impl::if_c< IS_VOID || IS_REJECT , void , ValueType * >::type  pointer_type ;
+  typedef typename Impl::if_c< IS_VOID || IS_REJECT , void , ValueType & >::type  reference_type ;
+  typedef FunctorType functor_type;
+
+  static_assert( IS_VOID || IS_REJECT || 0 == ( sizeof(ValueType) % sizeof(int) ) ,
+    "Reduction functor's value_type deduced from functor::operator() requires: 0 == sizeof(value_type) % sizeof(int)" );
+
+  enum { StaticValueSize = IS_VOID || IS_REJECT ? 0 : sizeof(ValueType) };
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  unsigned value_size( const FunctorType & ) { return StaticValueSize ; }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  unsigned value_count( const FunctorType & ) { return IS_VOID || IS_REJECT ? 0 : 1 ; }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+/** Function signatures for FunctorType::init function with a tag.
+ *  reference_type is 'value_type &' for scalar and 'value_type *' for array.
+ */
+template< class FunctorType , class ArgTag >
+struct FunctorValueInitFunction {
+
+  typedef typename FunctorValueTraits<FunctorType,ArgTag>::reference_type
+    reference_type ;
+
+  KOKKOS_INLINE_FUNCTION static void
+    enable_if( void (FunctorType::*)( ArgTag         , reference_type ) const );
+  KOKKOS_INLINE_FUNCTION static void
+    enable_if( void (FunctorType::*)( ArgTag const & , reference_type ) const );
+  KOKKOS_INLINE_FUNCTION static void
+    enable_if( void (             *)( ArgTag         , reference_type ) );
+  KOKKOS_INLINE_FUNCTION static void
+    enable_if( void (             *)( ArgTag const & , reference_type ) );
+
+};
+
+/** Function signatures for FunctorType::init function without a tag.
+ *  reference_type is 'value_type &' for scalar and 'value_type *' for array.
+ */
+template< class FunctorType >
+struct FunctorValueInitFunction< FunctorType , void > {
+
+  typedef typename FunctorValueTraits<FunctorType,void>::reference_type
+    reference_type ;
+
+  KOKKOS_INLINE_FUNCTION static void
+    enable_if( void (FunctorType::*)( reference_type ) const );
+  KOKKOS_INLINE_FUNCTION static void
+    enable_if( void (             *)( reference_type ) );
+};
+
+// Adapter for value initialization function.
+// If a proper FunctorType::init is declared then use it,
+// otherwise use default constructor.
+template< class FunctorType , class ArgTag
+        , class T = typename FunctorValueTraits<FunctorType,ArgTag>::reference_type
+        , class Enable = void >
+struct FunctorValueInit ;
+
+/* No 'init' function provided for single value */
+template< class FunctorType , class ArgTag , class T , class Enable >
+struct FunctorValueInit< FunctorType , ArgTag , T & , Enable >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T & init( const FunctorType & f , void * p )
+    { return *( new(p) T() ); };
+};
+
+/* No 'init' function provided for array value */
+template< class FunctorType , class ArgTag , class T , class Enable >
+struct FunctorValueInit< FunctorType , ArgTag , T * , Enable >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T * init( const FunctorType & f , void * p )
+    {
+      const int n = FunctorValueTraits< FunctorType , ArgTag >::value_count(f);
+      for ( int i = 0 ; i < n ; ++i ) { new( ((T*)p) + i ) T(); }
+      return (T*)p ;
+    }
+};
+
+/* 'init' function provided for single value */
+template< class FunctorType , class T >
+struct FunctorValueInit
+  < FunctorType
+  , void
+  , T &
+    // First  substitution failure when FunctorType::init does not exist.
+    // Second substitution failure when FunctorType::init is not compatible.
+  , decltype( FunctorValueInitFunction< FunctorType , void >::enable_if( & FunctorType::init ) )
+  >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T & init( const FunctorType & f , void * p )
+    { f.init( *((T*)p) ); return *((T*)p) ; }
+};
+
+/* 'init' function provided for array value */
+template< class FunctorType , class T >
+struct FunctorValueInit
+  < FunctorType
+  , void
+  , T *
+    // First  substitution failure when FunctorType::init does not exist.
+    // Second substitution failure when FunctorType::init is not compatible
+  , decltype( FunctorValueInitFunction< FunctorType , void >::enable_if( & FunctorType::init ) )
+  >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T * init( const FunctorType & f , void * p )
+    { f.init( (T*)p ); return (T*)p ; }
+};
+
+/* 'init' function provided for single value */
+template< class FunctorType , class ArgTag , class T >
+struct FunctorValueInit
+  < FunctorType
+  , ArgTag
+  , T &
+    // First  substitution failure when FunctorType::init does not exist.
+    // Second substitution failure when FunctorType::init is not compatible.
+  , decltype( FunctorValueInitFunction< FunctorType , ArgTag >::enable_if( & FunctorType::init ) )
+  >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T & init( const FunctorType & f , void * p )
+    { f.init( ArgTag() , *((T*)p) ); return *((T*)p) ; }
+};
+
+/* 'init' function provided for array value */
+template< class FunctorType , class ArgTag , class T >
+struct FunctorValueInit
+  < FunctorType
+  , ArgTag
+  , T *
+    // First  substitution failure when FunctorType::init does not exist.
+    // Second substitution failure when FunctorType::init is not compatible
+  , decltype( FunctorValueInitFunction< FunctorType , ArgTag >::enable_if( & FunctorType::init ) )
+  >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T * init( const FunctorType & f , void * p )
+    { f.init( ArgTag() , (T*)p ); return (T*)p ; }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+// Signatures for compatible FunctorType::join with tag and not an array
+template< class FunctorType , class ArgTag , bool IsArray = 0 == FunctorValueTraits<FunctorType,ArgTag>::StaticValueSize >
+struct FunctorValueJoinFunction {
+
+  typedef typename FunctorValueTraits<FunctorType,ArgTag>::value_type value_type ;
+
+  typedef       volatile value_type & vref_type ;
+  typedef const volatile value_type & cvref_type ;
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , vref_type , cvref_type ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , vref_type , cvref_type ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , vref_type , cvref_type ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , vref_type , cvref_type ) );
+};
+
+// Signatures for compatible FunctorType::join with tag and is an array
+template< class FunctorType , class ArgTag >
+struct FunctorValueJoinFunction< FunctorType , ArgTag , true > {
+
+  typedef typename FunctorValueTraits<FunctorType,ArgTag>::value_type value_type ;
+
+  typedef       volatile value_type * vptr_type ;
+  typedef const volatile value_type * cvptr_type ;
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , vptr_type , cvptr_type ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , vptr_type , cvptr_type ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , vptr_type , cvptr_type ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , vptr_type , cvptr_type ) );
+};
+
+// Signatures for compatible FunctorType::join without tag and not an array
+template< class FunctorType >
+struct FunctorValueJoinFunction< FunctorType , void , false > {
+
+  typedef typename FunctorValueTraits<FunctorType,void>::value_type value_type ;
+
+  typedef       volatile value_type & vref_type ;
+  typedef const volatile value_type & cvref_type ;
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( vref_type , cvref_type ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( vref_type , cvref_type ) );
+};
+
+// Signatures for compatible FunctorType::join without tag and is an array
+template< class FunctorType >
+struct FunctorValueJoinFunction< FunctorType , void , true > {
+
+  typedef typename FunctorValueTraits<FunctorType,void>::value_type value_type ;
+
+  typedef       volatile value_type * vptr_type ;
+  typedef const volatile value_type * cvptr_type ;
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( vptr_type , cvptr_type ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( vptr_type , cvptr_type ) );
+};
+
+
+template< class FunctorType , class ArgTag
+        , class T = typename FunctorValueTraits<FunctorType,ArgTag>::reference_type
+        , class Enable = void >
+struct FunctorValueJoin ;
+
+/* No 'join' function provided, single value */
+template< class FunctorType , class ArgTag , class T , class Enable >
+struct FunctorValueJoin< FunctorType , ArgTag , T & , Enable >
+{
+  KOKKOS_FORCEINLINE_FUNCTION
+  FunctorValueJoin(const FunctorType& ){}
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void join( const FunctorType & f , volatile void * const lhs , const volatile void * const rhs )
+    {
+      *((volatile T*)lhs) += *((const volatile T*)rhs);
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator()( volatile T& lhs , const volatile T& rhs ) const
+    {
+      lhs += rhs;
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator() ( T& lhs , const T& rhs ) const
+    {
+      lhs += rhs;
+    }
+};
+
+/* No 'join' function provided, array of values */
+template< class FunctorType , class ArgTag , class T , class Enable >
+struct FunctorValueJoin< FunctorType , ArgTag , T * , Enable >
+{
+  const FunctorType& f;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  FunctorValueJoin(const FunctorType& f_):f(f_){}
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void join( const FunctorType & f_ , volatile void * const lhs , const volatile void * const rhs )
+    {
+      const int n = FunctorValueTraits<FunctorType,ArgTag>::value_count(f_);
+
+      for ( int i = 0 ; i < n ; ++i ) { ((volatile T*)lhs)[i] += ((const volatile T*)rhs)[i]; }
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator()( volatile T* const lhs , const volatile T* const rhs ) const
+    {
+      const int n = FunctorValueTraits<FunctorType,ArgTag>::value_count(f);
+
+      for ( int i = 0 ; i < n ; ++i ) { lhs[i] += rhs[i]; }
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator() ( T* lhs , const T* rhs ) const
+    {
+      const int n = FunctorValueTraits<FunctorType,ArgTag>::value_count(f);
+
+      for ( int i = 0 ; i < n ; ++i ) { lhs[i] += rhs[i]; }
+    }
+};
+
+/* 'join' function provided, single value */
+template< class FunctorType , class ArgTag , class T >
+struct FunctorValueJoin
+  < FunctorType
+  , ArgTag
+  , T &
+    // First  substitution failure when FunctorType::join does not exist.
+    // Second substitution failure when enable_if( & Functor::join ) does not exist
+  , decltype( FunctorValueJoinFunction< FunctorType , ArgTag >::enable_if( & FunctorType::join ) )
+  >
+{
+  const FunctorType& f;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  FunctorValueJoin(const FunctorType& f_):f(f_){}
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void join( const FunctorType & f_ , volatile void * const lhs , const volatile void * const rhs )
+    {
+      f_.join( ArgTag() , *((volatile T *)lhs) , *((const volatile T *)rhs) );
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator()( volatile T& lhs , const volatile T& rhs ) const
+    {
+      f.join( ArgTag() , lhs , rhs );
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator() ( T& lhs , const T& rhs ) const
+    {
+      f.join( ArgTag(), lhs , rhs );
+    }
+};
+
+/* 'join' function provided, no tag, single value */
+template< class FunctorType , class T >
+struct FunctorValueJoin
+  < FunctorType
+  , void
+  , T &
+    // First  substitution failure when FunctorType::join does not exist.
+    // Second substitution failure when enable_if( & Functor::join ) does not exist
+  , decltype( FunctorValueJoinFunction< FunctorType , void >::enable_if( & FunctorType::join ) )
+  >
+{
+  const FunctorType& f;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  FunctorValueJoin(const FunctorType& f_):f(f_){}
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void join( const FunctorType & f_ , volatile void * const lhs , const volatile void * const rhs )
+    {
+      f_.join( *((volatile T *)lhs) , *((const volatile T *)rhs) );
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator()( volatile T& lhs , const volatile T& rhs ) const
+    {
+      f.join( lhs , rhs );
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator() ( T& lhs , const T& rhs ) const
+    {
+      f.join( lhs , rhs );
+    }
+};
+
+/* 'join' function provided for array value */
+template< class FunctorType , class ArgTag , class T >
+struct FunctorValueJoin
+  < FunctorType
+  , ArgTag
+  , T *
+    // First  substitution failure when FunctorType::join does not exist.
+    // Second substitution failure when enable_if( & Functor::join ) does not exist
+  , decltype( FunctorValueJoinFunction< FunctorType , ArgTag >::enable_if( & FunctorType::join ) )
+  >
+{
+  const FunctorType& f;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  FunctorValueJoin(const FunctorType& f_):f(f_){}
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void join( const FunctorType & f_ , volatile void * const lhs , const volatile void * const rhs )
+    {
+      f_.join( ArgTag() , (volatile T *)lhs , (const volatile T *)rhs );
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator()( volatile T* const lhs , const volatile T* const rhs ) const
+    {
+      f.join( ArgTag() , lhs , rhs );
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator() ( T* lhs , const T* rhs ) const
+    {
+      f.join( ArgTag(), lhs , rhs );
+    }
+};
+
+/* 'join' function provided, no tag, array value */
+template< class FunctorType , class T >
+struct FunctorValueJoin
+  < FunctorType
+  , void
+  , T *
+    // First  substitution failure when FunctorType::join does not exist.
+    // Second substitution failure when enable_if( & Functor::join ) does not exist
+  , decltype( FunctorValueJoinFunction< FunctorType , void >::enable_if( & FunctorType::join ) )
+  >
+{
+  const FunctorType& f;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  FunctorValueJoin(const FunctorType& f_):f(f_){}
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void join( const FunctorType & f_ , volatile void * const lhs , const volatile void * const rhs )
+    {
+      f_.join( (volatile T *)lhs , (const volatile T *)rhs );
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator() ( volatile T* const lhs , const volatile T* const rhs ) const
+    {
+      f.join( lhs , rhs );
+    }
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator() ( T* lhs , const T* rhs ) const
+    {
+      f.join( lhs , rhs );
+    }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+namespace Kokkos {
+
+namespace Impl {
+
+  template<typename ValueType, class JoinOp, class Enable = void>
+  struct JoinLambdaAdapter {
+    typedef ValueType value_type;
+    const JoinOp& lambda;
+    KOKKOS_INLINE_FUNCTION
+    JoinLambdaAdapter(const JoinOp& lambda_):lambda(lambda_) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void join(volatile value_type& dst, const volatile value_type& src) const {
+      lambda(dst,src);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void join(value_type& dst, const value_type& src) const {
+      lambda(dst,src);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (volatile value_type& dst, const volatile value_type& src) const {
+      lambda(dst,src);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (value_type& dst, const value_type& src) const {
+      lambda(dst,src);
+    }
+  };
+
+  template<typename ValueType, class JoinOp>
+  struct JoinLambdaAdapter<ValueType, JoinOp, decltype( FunctorValueJoinFunction< JoinOp , void >::enable_if( & JoinOp::join ) )> {
+    typedef ValueType value_type;
+    typedef StaticAssertSame<ValueType,typename JoinOp::value_type> assert_value_types_match;
+    const JoinOp& lambda;
+    KOKKOS_INLINE_FUNCTION
+    JoinLambdaAdapter(const JoinOp& lambda_):lambda(lambda_) {}
+
+    KOKKOS_INLINE_FUNCTION
+    void join(volatile value_type& dst, const volatile value_type& src) const {
+      lambda.join(dst,src);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void join(value_type& dst, const value_type& src) const {
+      lambda.join(dst,src);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (volatile value_type& dst, const volatile value_type& src) const {
+      lambda.join(dst,src);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator() (value_type& dst, const value_type& src) const {
+      lambda.join(dst,src);
+    }
+  };
+
+  template<typename ValueType>
+  struct JoinAdd {
+    typedef ValueType value_type;
+
+    KOKKOS_INLINE_FUNCTION
+    JoinAdd() {}
+
+    KOKKOS_INLINE_FUNCTION
+    void join(volatile value_type& dst, const volatile value_type& src) const {
+      dst+=src;
+    }
+    KOKKOS_INLINE_FUNCTION
+    void operator() (value_type& dst, const value_type& src) const {
+      dst+=src;
+    }
+    KOKKOS_INLINE_FUNCTION
+    void operator() (volatile value_type& dst, const volatile value_type& src) const {
+      dst+=src;
+    }
+  };
+
+}
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ArgTag
+        , class T = typename FunctorValueTraits<FunctorType,ArgTag>::reference_type >
+struct FunctorValueOps ;
+
+template< class FunctorType , class ArgTag , class T >
+struct FunctorValueOps< FunctorType , ArgTag , T & >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T * pointer( T & r ) { return & r ; }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T & reference( void * p ) { return *((T*)p); }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void copy( const FunctorType & , void * const lhs , const void * const rhs )
+    { *((T*)lhs) = *((const T*)rhs); }
+};
+
+/* No 'join' function provided, array of values */
+template< class FunctorType , class ArgTag , class T >
+struct FunctorValueOps< FunctorType , ArgTag , T * >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T * pointer( T * p ) { return p ; }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  T * reference( void * p ) { return ((T*)p); }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void copy( const FunctorType & f , void * const lhs , const void * const rhs )
+    {
+      const int n = FunctorValueTraits<FunctorType,ArgTag>::value_count(f);
+      for ( int i = 0 ; i < n ; ++i ) { ((T*)lhs)[i] = ((const T*)rhs)[i]; }
+    }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+// Compatible functions for 'final' function and value_type not an array
+template< class FunctorType , class ArgTag , bool IsArray = 0 == FunctorValueTraits<FunctorType,ArgTag>::StaticValueSize >
+struct FunctorFinalFunction {
+
+  typedef typename FunctorValueTraits<FunctorType,ArgTag>::value_type value_type ;
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type & ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type & ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type & ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type & ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , value_type & ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , value_type & ) );
+
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type volatile & ) const );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type volatile & ) const );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type volatile & ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type volatile & ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , value_type volatile & ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , value_type volatile & ) );
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type const & ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type const & ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type const & ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type const & ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , value_type const & ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , value_type const & ) );
+
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type const volatile & ) const );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type const volatile & ) const );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type const volatile & ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type const volatile & ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , value_type const volatile & ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , value_type const volatile & ) );
+};
+
+// Compatible functions for 'final' function and value_type is an array
+template< class FunctorType , class ArgTag >
+struct FunctorFinalFunction< FunctorType , ArgTag , true > {
+
+  typedef typename FunctorValueTraits<FunctorType,ArgTag>::value_type value_type ;
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type * ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type * ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type * ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type * ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , value_type * ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , value_type * ) );
+
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type volatile * ) const );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type volatile * ) const );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type volatile * ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type volatile * ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , value_type volatile * ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , value_type volatile * ) );
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type const * ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type const * ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type const * ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type const * ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , value_type const * ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , value_type const * ) );
+
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type const volatile * ) const );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type const volatile * ) const );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , value_type const volatile * ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , value_type const volatile * ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , value_type const volatile * ) );
+  // KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , value_type const volatile * ) );
+};
+
+template< class FunctorType >
+struct FunctorFinalFunction< FunctorType , void , false > {
+
+  typedef typename FunctorValueTraits<FunctorType,void>::value_type value_type ;
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( value_type & ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( value_type & ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( value_type & ) );
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( const value_type & ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( const value_type & ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( const value_type & ) );
+};
+
+template< class FunctorType >
+struct FunctorFinalFunction< FunctorType , void , true > {
+
+  typedef typename FunctorValueTraits<FunctorType,void>::value_type value_type ;
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( value_type * ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( value_type * ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( value_type * ) );
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( const value_type * ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( const value_type * ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( const value_type * ) );
+};
+
+/* No 'final' function provided */
+template< class FunctorType , class ArgTag
+        , class ResultType = typename FunctorValueTraits<FunctorType,ArgTag>::reference_type
+        , class Enable = void >
+struct FunctorFinal
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void final( const FunctorType & , void * ) {}
+};
+
+/* 'final' function provided */
+template< class FunctorType , class ArgTag , class T >
+struct FunctorFinal
+  < FunctorType
+  , ArgTag
+  , T &
+    // First  substitution failure when FunctorType::final does not exist.
+    // Second substitution failure when enable_if( & Functor::final ) does not exist
+  , decltype( FunctorFinalFunction< FunctorType , ArgTag >::enable_if( & FunctorType::final ) )
+  >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void final( const FunctorType & f , void * p ) { f.final( *((T*)p) ); }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void final( FunctorType & f , void * p ) { f.final( *((T*)p) ); }
+};
+
+/* 'final' function provided for array value */
+template< class FunctorType , class ArgTag , class T >
+struct FunctorFinal
+  < FunctorType
+  , ArgTag
+  , T *
+    // First  substitution failure when FunctorType::final does not exist.
+    // Second substitution failure when enable_if( & Functor::final ) does not exist
+  , decltype( FunctorFinalFunction< FunctorType , ArgTag >::enable_if( & FunctorType::final ) )
+  >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void final( const FunctorType & f , void * p ) { f.final( (T*)p ); }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void final( FunctorType & f , void * p ) { f.final( (T*)p ); }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class FunctorType , class ArgTag
+        , class ReferenceType = typename FunctorValueTraits<FunctorType,ArgTag>::reference_type >
+struct FunctorApplyFunction {
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , ReferenceType ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , ReferenceType ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag         , ReferenceType ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ArgTag const & , ReferenceType ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag         , ReferenceType ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ArgTag const & , ReferenceType ) );
+};
+
+template< class FunctorType , class ReferenceType >
+struct FunctorApplyFunction< FunctorType , void , ReferenceType > {
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ReferenceType ) const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)( ReferenceType ) );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (             *)( ReferenceType ) );
+};
+
+template< class FunctorType >
+struct FunctorApplyFunction< FunctorType , void , void > {
+
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)() const );
+  KOKKOS_INLINE_FUNCTION static void enable_if( void (FunctorType::*)() );
+};
+
+template< class FunctorType , class ArgTag , class ReferenceType
+        , class Enable = void >
+struct FunctorApply
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void apply( const FunctorType & , void * ) {}
+};
+
+/* 'apply' function provided for void value */
+template< class FunctorType , class ArgTag >
+struct FunctorApply
+  < FunctorType
+  , ArgTag
+  , void
+    // First  substitution failure when FunctorType::apply does not exist.
+    // Second substitution failure when enable_if( & Functor::apply ) does not exist
+  , decltype( FunctorApplyFunction< FunctorType , ArgTag , void >::enable_if( & FunctorType::apply ) )
+  >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void apply( FunctorType & f ) { f.apply(); }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void apply( const FunctorType & f ) { f.apply(); }
+};
+
+/* 'apply' function provided for single value */
+template< class FunctorType , class ArgTag , class T >
+struct FunctorApply
+  < FunctorType
+  , ArgTag
+  , T &
+    // First  substitution failure when FunctorType::apply does not exist.
+    // Second substitution failure when enable_if( & Functor::apply ) does not exist
+  , decltype( FunctorApplyFunction< FunctorType , ArgTag >::enable_if( & FunctorType::apply ) )
+  >
+{
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void apply( const FunctorType & f , void * p ) { f.apply( *((T*)p) ); }
+
+  KOKKOS_FORCEINLINE_FUNCTION static
+  void apply( FunctorType & f , void * p ) { f.apply( *((T*)p) ); }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* KOKKOS_FUNCTORADAPTER_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_HBWAllocators.cpp b/lib/kokkos/core/src/impl/Kokkos_HBWAllocators.cpp
new file mode 100644
index 0000000000..4eb80d03f1
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_HBWAllocators.cpp
@@ -0,0 +1,108 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_HostSpace.hpp>
+
+#include <impl/Kokkos_HBWAllocators.hpp>
+#include <impl/Kokkos_Error.hpp>
+
+
+#include <stdint.h>    // uintptr_t
+#include <cstdlib>     // for malloc, realloc, and free
+#include <cstring>     // for memcpy
+
+#if defined(KOKKOS_POSIX_MEMALIGN_AVAILABLE)
+#include <sys/mman.h>  // for mmap, munmap, MAP_ANON, etc
+#include <unistd.h>    // for sysconf, _SC_PAGE_SIZE, _SC_PHYS_PAGES
+#endif
+
+#include <sstream>
+#include <iostream>
+
+#ifdef KOKKOS_HAVE_HBWSPACE
+#include <memkind.h>
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+#define MEMKIND_TYPE MEMKIND_HBW //hbw_get_kind(HBW_PAGESIZE_4KB)
+/*--------------------------------------------------------------------------*/
+
+void* HBWMallocAllocator::allocate( size_t size )
+{
+  std::cout<< "Allocate HBW: " << 1.0e-6*size << "MB" << std::endl;
+  void * ptr = NULL;
+  if (size) {
+    ptr = memkind_malloc(MEMKIND_TYPE,size);
+
+    if (!ptr)
+    {
+      std::ostringstream msg ;
+      msg << name() << ": allocate(" << size << ") FAILED";
+      Kokkos::Impl::throw_runtime_exception( msg.str() );
+    }
+  }
+  return ptr;
+}
+
+void HBWMallocAllocator::deallocate( void * ptr, size_t /*size*/ )
+{
+  if (ptr) {
+    memkind_free(MEMKIND_TYPE,ptr);
+  }
+}
+
+void * HBWMallocAllocator::reallocate(void * old_ptr, size_t /*old_size*/, size_t new_size)
+{
+  void * ptr = memkind_realloc(MEMKIND_TYPE, old_ptr, new_size);
+
+  if (new_size > 0u && ptr == NULL) {
+    Kokkos::Impl::throw_runtime_exception("Error: Malloc Allocator could not reallocate memory");
+  }
+  return ptr;
+}
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_HBWAllocators.hpp b/lib/kokkos/core/src/impl/Kokkos_HBWAllocators.hpp
new file mode 100644
index 0000000000..be0134460b
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_HBWAllocators.hpp
@@ -0,0 +1,75 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_HBW_ALLOCATORS_HPP
+#define KOKKOS_HBW_ALLOCATORS_HPP
+
+#ifdef KOKKOS_HAVE_HBWSPACE
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+/// class MallocAllocator
+class HBWMallocAllocator
+{
+public:
+  static const char * name()
+  {
+    return "HBW Malloc Allocator";
+  }
+
+  static void* allocate(size_t size);
+
+  static void deallocate(void * ptr, size_t size);
+
+  static void * reallocate(void * old_ptr, size_t old_size, size_t new_size);
+};
+
+}
+}
+} // namespace Kokkos::Impl
+#endif //KOKKOS_HAVE_HBWSPACE
+#endif //KOKKOS_HBW_ALLOCATORS_HPP
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_HBWSpace.cpp b/lib/kokkos/core/src/impl/Kokkos_HBWSpace.cpp
new file mode 100644
index 0000000000..11cc120212
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_HBWSpace.cpp
@@ -0,0 +1,379 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+
+#include <Kokkos_Macros.hpp>
+
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <memory.h>
+
+#include <iostream>
+#include <sstream>
+#include <cstring>
+#include <algorithm>
+
+#include <Kokkos_HBWSpace.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <Kokkos_Atomic.hpp>
+#ifdef KOKKOS_HAVE_HBWSPACE
+#include <memkind.h>
+#endif
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+#ifdef KOKKOS_HAVE_HBWSPACE
+#define MEMKIND_TYPE MEMKIND_HBW //hbw_get_kind(HBW_PAGESIZE_4KB)
+
+namespace Kokkos {
+namespace Experimental {
+namespace {
+
+static const int QUERY_SPACE_IN_PARALLEL_MAX = 16 ;
+
+typedef int (* QuerySpaceInParallelPtr )();
+
+QuerySpaceInParallelPtr s_in_parallel_query[ QUERY_SPACE_IN_PARALLEL_MAX ] ;
+int s_in_parallel_query_count = 0 ;
+
+} // namespace <empty>
+
+void HBWSpace::register_in_parallel( int (*device_in_parallel)() )
+{
+  if ( 0 == device_in_parallel ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::HBWSpace::register_in_parallel ERROR : given NULL" ) );
+  }
+
+  int i = -1 ;
+
+  if ( ! (device_in_parallel)() ) {
+    for ( i = 0 ; i < s_in_parallel_query_count && ! (*(s_in_parallel_query[i]))() ; ++i );
+  }
+
+  if ( i < s_in_parallel_query_count ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::HBWSpace::register_in_parallel_query ERROR : called in_parallel" ) );
+
+  }
+
+  if ( QUERY_SPACE_IN_PARALLEL_MAX <= i ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::HBWSpace::register_in_parallel_query ERROR : exceeded maximum" ) );
+
+  }
+
+  for ( i = 0 ; i < s_in_parallel_query_count && s_in_parallel_query[i] != device_in_parallel ; ++i );
+
+  if ( i == s_in_parallel_query_count ) {
+    s_in_parallel_query[s_in_parallel_query_count++] = device_in_parallel ;
+  }
+}
+
+int HBWSpace::in_parallel()
+{
+  const int n = s_in_parallel_query_count ;
+
+  int i = 0 ;
+
+  while ( i < n && ! (*(s_in_parallel_query[i]))() ) { ++i ; }
+
+  return i < n ;
+}
+
+} // namespace Experiemtal
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Experimental {
+
+/* Default allocation mechanism */
+HBWSpace::HBWSpace()
+  : m_alloc_mech(
+     HBWSpace::STD_MALLOC
+    )
+{
+printf("Init\n");
+setenv("MEMKIND_HBW_NODES", "1", 0);
+}
+
+/* Default allocation mechanism */
+HBWSpace::HBWSpace( const HBWSpace::AllocationMechanism & arg_alloc_mech )
+  : m_alloc_mech( HBWSpace::STD_MALLOC )
+{
+printf("Init2\n");
+setenv("MEMKIND_HBW_NODES", "1", 0);
+  if ( arg_alloc_mech == STD_MALLOC ) {
+    m_alloc_mech = HBWSpace::STD_MALLOC ;
+  }
+}
+
+void * HBWSpace::allocate( const size_t arg_alloc_size ) const
+{
+  static_assert( sizeof(void*) == sizeof(uintptr_t)
+               , "Error sizeof(void*) != sizeof(uintptr_t)" );
+
+  static_assert( Kokkos::Impl::power_of_two< Kokkos::Impl::MEMORY_ALIGNMENT >::value
+               , "Memory alignment must be power of two" );
+
+  constexpr uintptr_t alignment = Kokkos::Impl::MEMORY_ALIGNMENT ;
+  constexpr uintptr_t alignment_mask = alignment - 1 ;
+
+  void * ptr = 0 ;
+
+  if ( arg_alloc_size ) {
+
+    if ( m_alloc_mech == STD_MALLOC ) {
+      // Over-allocate to and round up to guarantee proper alignment.
+      size_t size_padded = arg_alloc_size + sizeof(void*) + alignment ;
+
+      void * alloc_ptr = memkind_malloc(MEMKIND_TYPE, size_padded );
+
+      if (alloc_ptr) {
+        uintptr_t address = reinterpret_cast<uintptr_t>(alloc_ptr);
+
+        // offset enough to record the alloc_ptr
+        address += sizeof(void *);
+        uintptr_t rem = address % alignment;
+        uintptr_t offset = rem ? (alignment - rem) : 0u;
+        address += offset;
+        ptr = reinterpret_cast<void *>(address);
+        // record the alloc'd pointer
+        address -= sizeof(void *);
+        *reinterpret_cast<void **>(address) = alloc_ptr;
+      }
+    }
+  }
+
+  if ( ( ptr == 0 ) || ( reinterpret_cast<uintptr_t>(ptr) == ~uintptr_t(0) )
+       || ( reinterpret_cast<uintptr_t>(ptr) & alignment_mask ) ) {
+    std::ostringstream msg ;
+    msg << "Kokkos::Experimental::HBWSpace::allocate[ " ;
+    switch( m_alloc_mech ) {
+    case STD_MALLOC: msg << "STD_MALLOC" ; break ;
+    }
+    msg << " ]( " << arg_alloc_size << " ) FAILED" ;
+    if ( ptr == NULL ) { msg << " NULL" ; } 
+    else { msg << " NOT ALIGNED " << ptr ; }
+
+    std::cerr << msg.str() << std::endl ;
+    std::cerr.flush();
+
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  return ptr;
+}
+
+
+void HBWSpace::deallocate( void * const arg_alloc_ptr , const size_t arg_alloc_size ) const
+{
+  if ( arg_alloc_ptr ) {
+
+    if ( m_alloc_mech == STD_MALLOC ) {
+      void * alloc_ptr = *(reinterpret_cast<void **>(arg_alloc_ptr) -1);
+      memkind_free(MEMKIND_TYPE, alloc_ptr );
+    }    
+
+  }
+}
+
+} // namespace Experimental
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+SharedAllocationRecord< void , void >
+SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::s_root_record ;
+
+void
+SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::
+deallocate( SharedAllocationRecord< void , void > * arg_rec )
+{
+  delete static_cast<SharedAllocationRecord*>(arg_rec);
+}
+
+SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::
+~SharedAllocationRecord()
+{
+  m_space.deallocate( SharedAllocationRecord< void , void >::m_alloc_ptr
+                    , SharedAllocationRecord< void , void >::m_alloc_size
+                    );
+}
+
+SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::
+SharedAllocationRecord( const Kokkos::Experimental::HBWSpace & arg_space
+                      , const std::string       & arg_label
+                      , const size_t              arg_alloc_size
+                      , const SharedAllocationRecord< void , void >::function_type arg_dealloc
+                      )
+  // Pass through allocated [ SharedAllocationHeader , user_memory ]
+  // Pass through deallocation function
+  : SharedAllocationRecord< void , void >
+      ( & SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::s_root_record
+      , reinterpret_cast<SharedAllocationHeader*>( arg_space.allocate( sizeof(SharedAllocationHeader) + arg_alloc_size ) )
+      , sizeof(SharedAllocationHeader) + arg_alloc_size
+      , arg_dealloc
+      )
+  , m_space( arg_space )
+{
+  // Fill in the Header information
+  RecordBase::m_alloc_ptr->m_record = static_cast< SharedAllocationRecord< void , void > * >( this );
+
+  strncpy( RecordBase::m_alloc_ptr->m_label
+          , arg_label.c_str()
+          , SharedAllocationHeader::maximum_label_length
+          );
+}
+
+//----------------------------------------------------------------------------
+
+void * SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::
+allocate_tracked( const Kokkos::Experimental::HBWSpace & arg_space
+                , const std::string & arg_alloc_label 
+                , const size_t arg_alloc_size )
+{
+  if ( ! arg_alloc_size ) return (void *) 0 ;
+
+  SharedAllocationRecord * const r =
+    allocate( arg_space , arg_alloc_label , arg_alloc_size );
+
+  RecordBase::increment( r );
+
+  return r->data();
+}
+
+void SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::
+deallocate_tracked( void * const arg_alloc_ptr )
+{
+  if ( arg_alloc_ptr != 0 ) {
+    SharedAllocationRecord * const r = get_record( arg_alloc_ptr );
+
+    RecordBase::decrement( r );
+  }
+}
+
+void * SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::
+reallocate_tracked( void * const arg_alloc_ptr
+                  , const size_t arg_alloc_size )
+{
+  SharedAllocationRecord * const r_old = get_record( arg_alloc_ptr );
+  SharedAllocationRecord * const r_new = allocate( r_old->m_space , r_old->get_label() , arg_alloc_size );
+
+  Kokkos::Impl::DeepCopy<HBWSpace,HBWSpace>( r_new->data() , r_old->data()
+                                             , std::min( r_old->size() , r_new->size() ) );
+
+  RecordBase::increment( r_new );
+  RecordBase::decrement( r_old );
+
+  return r_new->data();
+}
+
+SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void > *
+SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::get_record( void * alloc_ptr )
+{
+  typedef SharedAllocationHeader  Header ;
+  typedef SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >  RecordHost ;
+
+  SharedAllocationHeader const * const head   = alloc_ptr ? Header::get_header( alloc_ptr ) : (SharedAllocationHeader *)0 ;
+  RecordHost                   * const record = head ? static_cast< RecordHost * >( head->m_record ) : (RecordHost *) 0 ;
+
+  if ( ! alloc_ptr || record->m_alloc_ptr != head ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::get_record ERROR" ) );
+  }
+
+  return record ;
+}
+
+// Iterate records to print orphaned memory ...
+void SharedAllocationRecord< Kokkos::Experimental::HBWSpace , void >::
+print_records( std::ostream & s , const Kokkos::Experimental::HBWSpace & space , bool detail )
+{
+  SharedAllocationRecord< void , void >::print_host_accessible_records( s , "HBWSpace" , & s_root_record , detail );
+}
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Experimental {
+namespace {
+  const unsigned HBW_SPACE_ATOMIC_MASK = 0xFFFF;
+  const unsigned HBW_SPACE_ATOMIC_XOR_MASK = 0x5A39;
+  static int HBW_SPACE_ATOMIC_LOCKS[HBW_SPACE_ATOMIC_MASK+1];
+}
+
+namespace Impl {
+void init_lock_array_hbw_space() {
+  static int is_initialized = 0;
+  if(! is_initialized)
+    for(int i = 0; i < static_cast<int> (HBW_SPACE_ATOMIC_MASK+1); i++)
+      HBW_SPACE_ATOMIC_LOCKS[i] = 0;
+}
+
+bool lock_address_hbw_space(void* ptr) {
+  return 0 == atomic_compare_exchange( &HBW_SPACE_ATOMIC_LOCKS[
+      (( size_t(ptr) >> 2 ) & HBW_SPACE_ATOMIC_MASK) ^ HBW_SPACE_ATOMIC_XOR_MASK] ,
+                                  0 , 1);
+}
+
+void unlock_address_hbw_space(void* ptr) {
+   atomic_exchange( &HBW_SPACE_ATOMIC_LOCKS[
+      (( size_t(ptr) >> 2 ) & HBW_SPACE_ATOMIC_MASK) ^ HBW_SPACE_ATOMIC_XOR_MASK] ,
+                    0);
+}
+
+}
+}
+}
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_HostSpace.cpp b/lib/kokkos/core/src/impl/Kokkos_HostSpace.cpp
new file mode 100644
index 0000000000..b52f4591ef
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_HostSpace.cpp
@@ -0,0 +1,537 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <algorithm>
+#include <Kokkos_Macros.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+#if defined( __INTEL_COMPILER ) && ! defined ( KOKKOS_HAVE_CUDA )
+
+// Intel specialized allocator does not interoperate with CUDA memory allocation
+
+#define KOKKOS_INTEL_MM_ALLOC_AVAILABLE
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#if defined(KOKKOS_POSIX_MEMALIGN_AVAILABLE)
+
+#include <unistd.h>
+#include <sys/mman.h>
+
+/* mmap flags for private anonymous memory allocation */
+
+#if defined( MAP_ANONYMOUS ) && defined( MAP_PRIVATE )
+  #define KOKKOS_POSIX_MMAP_FLAGS (MAP_PRIVATE | MAP_ANONYMOUS)
+#elif defined( MAP_ANON ) && defined( MAP_PRIVATE )
+  #define KOKKOS_POSIX_MMAP_FLAGS (MAP_PRIVATE | MAP_ANON)
+#endif
+
+// mmap flags for huge page tables
+// the Cuda driver does not interoperate with MAP_HUGETLB
+#if defined( KOKKOS_POSIX_MMAP_FLAGS )
+  #if defined( MAP_HUGETLB ) && ! defined( KOKKOS_HAVE_CUDA )
+    #define KOKKOS_POSIX_MMAP_FLAGS_HUGE (KOKKOS_POSIX_MMAP_FLAGS | MAP_HUGETLB )
+  #else
+    #define KOKKOS_POSIX_MMAP_FLAGS_HUGE KOKKOS_POSIX_MMAP_FLAGS
+  #endif
+#endif
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <memory.h>
+
+#include <iostream>
+#include <sstream>
+#include <cstring>
+
+#include <Kokkos_HostSpace.hpp>
+#include <impl/Kokkos_Error.hpp>
+#include <Kokkos_Atomic.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace {
+
+static const int QUERY_SPACE_IN_PARALLEL_MAX = 16 ;
+
+typedef int (* QuerySpaceInParallelPtr )();
+
+QuerySpaceInParallelPtr s_in_parallel_query[ QUERY_SPACE_IN_PARALLEL_MAX ] ;
+int s_in_parallel_query_count = 0 ;
+
+} // namespace <empty>
+
+void HostSpace::register_in_parallel( int (*device_in_parallel)() )
+{
+  if ( 0 == device_in_parallel ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::HostSpace::register_in_parallel ERROR : given NULL" ) );
+  }
+
+  int i = -1 ;
+
+  if ( ! (device_in_parallel)() ) {
+    for ( i = 0 ; i < s_in_parallel_query_count && ! (*(s_in_parallel_query[i]))() ; ++i );
+  }
+
+  if ( i < s_in_parallel_query_count ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::HostSpace::register_in_parallel_query ERROR : called in_parallel" ) );
+
+  }
+
+  if ( QUERY_SPACE_IN_PARALLEL_MAX <= i ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::HostSpace::register_in_parallel_query ERROR : exceeded maximum" ) );
+
+  }
+
+  for ( i = 0 ; i < s_in_parallel_query_count && s_in_parallel_query[i] != device_in_parallel ; ++i );
+
+  if ( i == s_in_parallel_query_count ) {
+    s_in_parallel_query[s_in_parallel_query_count++] = device_in_parallel ;
+  }
+}
+
+int HostSpace::in_parallel()
+{
+  const int n = s_in_parallel_query_count ;
+
+  int i = 0 ;
+
+  while ( i < n && ! (*(s_in_parallel_query[i]))() ) { ++i ; }
+
+  return i < n ;
+}
+
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+
+/* Default allocation mechanism */
+HostSpace::HostSpace()
+  : m_alloc_mech(
+#if defined( KOKKOS_INTEL_MM_ALLOC_AVAILABLE )
+      HostSpace::INTEL_MM_ALLOC
+#elif defined( KOKKOS_POSIX_MMAP_FLAGS )
+      HostSpace::POSIX_MMAP
+#elif defined( KOKKOS_POSIX_MEMALIGN_AVAILABLE )
+      HostSpace::POSIX_MEMALIGN
+#else
+      HostSpace::STD_MALLOC
+#endif
+    )
+{}
+
+/* Default allocation mechanism */
+HostSpace::HostSpace( const HostSpace::AllocationMechanism & arg_alloc_mech )
+  : m_alloc_mech( HostSpace::STD_MALLOC )
+{
+  if ( arg_alloc_mech == STD_MALLOC ) {
+    m_alloc_mech = HostSpace::STD_MALLOC ;
+  }
+#if defined( KOKKOS_INTEL_MM_ALLOC_AVAILABLE )
+  else if ( arg_alloc_mech == HostSpace::INTEL_MM_ALLOC ) {
+    m_alloc_mech = HostSpace::INTEL_MM_ALLOC ;
+  }
+#elif defined( KOKKOS_POSIX_MEMALIGN_AVAILABLE )
+  else if ( arg_alloc_mech == HostSpace::POSIX_MEMALIGN ) {
+    m_alloc_mech = HostSpace::POSIX_MEMALIGN ;
+  }
+#elif defined( KOKKOS_POSIX_MMAP_FLAGS )
+  else if ( arg_alloc_mech == HostSpace::POSIX_MMAP ) {
+    m_alloc_mech = HostSpace::POSIX_MMAP ;
+  }
+#endif
+  else {
+    const char * const mech =
+      ( arg_alloc_mech == HostSpace::INTEL_MM_ALLOC ) ? "INTEL_MM_ALLOC" : (
+      ( arg_alloc_mech == HostSpace::POSIX_MEMALIGN ) ? "POSIX_MEMALIGN" : (
+      ( arg_alloc_mech == HostSpace::POSIX_MMAP     ) ? "POSIX_MMAP" : "" ));
+
+    std::string msg ;
+    msg.append("Kokkos::HostSpace ");
+    msg.append(mech);
+    msg.append(" is not available" );
+    Kokkos::Impl::throw_runtime_exception( msg );
+  }
+}
+
+void * HostSpace::allocate( const size_t arg_alloc_size ) const
+{
+  static_assert( sizeof(void*) == sizeof(uintptr_t)
+               , "Error sizeof(void*) != sizeof(uintptr_t)" );
+
+  static_assert( Kokkos::Impl::is_integral_power_of_two( Kokkos::Impl::MEMORY_ALIGNMENT )
+               , "Memory alignment must be power of two" );
+
+  constexpr uintptr_t alignment = Kokkos::Impl::MEMORY_ALIGNMENT ;
+  constexpr uintptr_t alignment_mask = alignment - 1 ;
+
+  void * ptr = 0 ;
+
+  if ( arg_alloc_size ) {
+
+    if ( m_alloc_mech == STD_MALLOC ) {
+      // Over-allocate to and round up to guarantee proper alignment.
+      size_t size_padded = arg_alloc_size + sizeof(void*) + alignment ;
+
+      void * alloc_ptr = malloc( size_padded );
+
+      if (alloc_ptr) {
+        uintptr_t address = reinterpret_cast<uintptr_t>(alloc_ptr);
+
+        // offset enough to record the alloc_ptr
+        address += sizeof(void *);
+        uintptr_t rem = address % alignment;
+        uintptr_t offset = rem ? (alignment - rem) : 0u;
+        address += offset;
+        ptr = reinterpret_cast<void *>(address);
+        // record the alloc'd pointer
+        address -= sizeof(void *);
+        *reinterpret_cast<void **>(address) = alloc_ptr;
+      }
+    }
+
+#if defined( KOKKOS_INTEL_MM_ALLOC_AVAILABLE )
+    else if ( m_alloc_mech == INTEL_MM_ALLOC ) {
+      ptr = _mm_malloc( arg_alloc_size , alignment );
+    }
+#endif
+
+#if defined( KOKKOS_POSIX_MEMALIGN_AVAILABLE )
+    else if ( m_alloc_mech == POSIX_MEMALIGN ) {
+      posix_memalign( & ptr, alignment , arg_alloc_size );
+    }
+#endif
+
+#if defined( KOKKOS_POSIX_MMAP_FLAGS )
+    else if ( m_alloc_mech == POSIX_MMAP ) {
+      constexpr size_t use_huge_pages = (1u << 27);
+      constexpr int    prot  = PROT_READ | PROT_WRITE ;
+      const int flags = arg_alloc_size < use_huge_pages
+                      ? KOKKOS_POSIX_MMAP_FLAGS
+                      : KOKKOS_POSIX_MMAP_FLAGS_HUGE ;
+
+      // read write access to private memory
+
+      ptr = mmap( NULL /* address hint, if NULL OS kernel chooses address */
+                , arg_alloc_size /* size in bytes */
+                , prot           /* memory protection */
+                , flags          /* visibility of updates */
+                , -1             /* file descriptor */
+                ,  0             /* offset */
+                );
+
+/* Associated reallocation:
+       ptr = mremap( old_ptr , old_size , new_size , MREMAP_MAYMOVE );
+*/
+    }
+#endif
+  }
+
+  if ( ( ptr == 0 ) || ( reinterpret_cast<uintptr_t>(ptr) == ~uintptr_t(0) )
+       || ( reinterpret_cast<uintptr_t>(ptr) & alignment_mask ) ) {
+    std::ostringstream msg ;
+    msg << "Kokkos::HostSpace::allocate[ " ;
+    switch( m_alloc_mech ) {
+    case STD_MALLOC: msg << "STD_MALLOC" ; break ;
+    case POSIX_MEMALIGN: msg << "POSIX_MEMALIGN" ; break ;
+    case POSIX_MMAP: msg << "POSIX_MMAP" ; break ;
+    case INTEL_MM_ALLOC: msg << "INTEL_MM_ALLOC" ; break ;
+    }
+    msg << " ]( " << arg_alloc_size << " ) FAILED" ;
+    if ( ptr == NULL ) { msg << " NULL" ; } 
+    else { msg << " NOT ALIGNED " << ptr ; }
+
+    std::cerr << msg.str() << std::endl ;
+    std::cerr.flush();
+
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  return ptr;
+}
+
+
+void HostSpace::deallocate( void * const arg_alloc_ptr , const size_t arg_alloc_size ) const
+{
+  if ( arg_alloc_ptr ) {
+
+    if ( m_alloc_mech == STD_MALLOC ) {
+      void * alloc_ptr = *(reinterpret_cast<void **>(arg_alloc_ptr) -1);
+      free( alloc_ptr );
+    }    
+
+#if defined( KOKKOS_INTEL_MM_ALLOC_AVAILABLE )
+    else if ( m_alloc_mech == INTEL_MM_ALLOC ) {
+      _mm_free( arg_alloc_ptr );
+    }
+#endif
+
+#if defined( KOKKOS_POSIX_MEMALIGN_AVAILABLE )
+    else if ( m_alloc_mech == POSIX_MEMALIGN ) {
+      free( arg_alloc_ptr );
+    }
+#endif
+
+#if defined( KOKKOS_POSIX_MMAP_FLAGS )
+    else if ( m_alloc_mech == POSIX_MMAP ) {
+      munmap( arg_alloc_ptr , arg_alloc_size );
+    }
+#endif
+
+  }
+}
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+SharedAllocationRecord< void , void >
+SharedAllocationRecord< Kokkos::HostSpace , void >::s_root_record ;
+
+void
+SharedAllocationRecord< Kokkos::HostSpace , void >::
+deallocate( SharedAllocationRecord< void , void > * arg_rec )
+{
+  delete static_cast<SharedAllocationRecord*>(arg_rec);
+}
+
+SharedAllocationRecord< Kokkos::HostSpace , void >::
+~SharedAllocationRecord()
+{
+  m_space.deallocate( SharedAllocationRecord< void , void >::m_alloc_ptr
+                    , SharedAllocationRecord< void , void >::m_alloc_size
+                    );
+}
+
+SharedAllocationRecord< Kokkos::HostSpace , void >::
+SharedAllocationRecord( const Kokkos::HostSpace & arg_space
+                      , const std::string       & arg_label
+                      , const size_t              arg_alloc_size
+                      , const SharedAllocationRecord< void , void >::function_type arg_dealloc
+                      )
+  // Pass through allocated [ SharedAllocationHeader , user_memory ]
+  // Pass through deallocation function
+  : SharedAllocationRecord< void , void >
+      ( & SharedAllocationRecord< Kokkos::HostSpace , void >::s_root_record
+      , reinterpret_cast<SharedAllocationHeader*>( arg_space.allocate( sizeof(SharedAllocationHeader) + arg_alloc_size ) )
+      , sizeof(SharedAllocationHeader) + arg_alloc_size
+      , arg_dealloc
+      )
+  , m_space( arg_space )
+{
+  // Fill in the Header information
+  RecordBase::m_alloc_ptr->m_record = static_cast< SharedAllocationRecord< void , void > * >( this );
+
+  strncpy( RecordBase::m_alloc_ptr->m_label
+          , arg_label.c_str()
+          , SharedAllocationHeader::maximum_label_length
+          );
+}
+
+//----------------------------------------------------------------------------
+
+void * SharedAllocationRecord< Kokkos::HostSpace , void >::
+allocate_tracked( const Kokkos::HostSpace & arg_space
+                , const std::string & arg_alloc_label 
+                , const size_t arg_alloc_size )
+{
+  if ( ! arg_alloc_size ) return (void *) 0 ;
+
+  SharedAllocationRecord * const r =
+    allocate( arg_space , arg_alloc_label , arg_alloc_size );
+
+  RecordBase::increment( r );
+
+  return r->data();
+}
+
+void SharedAllocationRecord< Kokkos::HostSpace , void >::
+deallocate_tracked( void * const arg_alloc_ptr )
+{
+  if ( arg_alloc_ptr != 0 ) {
+    SharedAllocationRecord * const r = get_record( arg_alloc_ptr );
+
+    RecordBase::decrement( r );
+  }
+}
+
+void * SharedAllocationRecord< Kokkos::HostSpace , void >::
+reallocate_tracked( void * const arg_alloc_ptr
+                  , const size_t arg_alloc_size )
+{
+  SharedAllocationRecord * const r_old = get_record( arg_alloc_ptr );
+  SharedAllocationRecord * const r_new = allocate( r_old->m_space , r_old->get_label() , arg_alloc_size );
+
+  Kokkos::Impl::DeepCopy<HostSpace,HostSpace>( r_new->data() , r_old->data()
+                                             , std::min( r_old->size() , r_new->size() ) );
+
+  RecordBase::increment( r_new );
+  RecordBase::decrement( r_old );
+
+  return r_new->data();
+}
+
+SharedAllocationRecord< Kokkos::HostSpace , void > *
+SharedAllocationRecord< Kokkos::HostSpace , void >::get_record( void * alloc_ptr )
+{
+  typedef SharedAllocationHeader  Header ;
+  typedef SharedAllocationRecord< Kokkos::HostSpace , void >  RecordHost ;
+
+  SharedAllocationHeader const * const head   = alloc_ptr ? Header::get_header( alloc_ptr ) : (SharedAllocationHeader *)0 ;
+  RecordHost                   * const record = head ? static_cast< RecordHost * >( head->m_record ) : (RecordHost *) 0 ;
+
+  if ( ! alloc_ptr || record->m_alloc_ptr != head ) {
+    Kokkos::Impl::throw_runtime_exception( std::string("Kokkos::Experimental::Impl::SharedAllocationRecord< Kokkos::HostSpace , void >::get_record ERROR" ) );
+  }
+
+  return record ;
+}
+
+// Iterate records to print orphaned memory ...
+void SharedAllocationRecord< Kokkos::HostSpace , void >::
+print_records( std::ostream & s , const Kokkos::HostSpace & space , bool detail )
+{
+  SharedAllocationRecord< void , void >::print_host_accessible_records( s , "HostSpace" , & s_root_record , detail );
+}
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+template< class >
+struct ViewOperatorBoundsErrorAbort ;
+
+template<>
+struct ViewOperatorBoundsErrorAbort< Kokkos::HostSpace > {
+ static void apply( const size_t rank
+                  , const size_t n0 , const size_t n1
+                  , const size_t n2 , const size_t n3
+                  , const size_t n4 , const size_t n5
+                  , const size_t n6 , const size_t n7
+                  , const size_t i0 , const size_t i1
+                  , const size_t i2 , const size_t i3
+                  , const size_t i4 , const size_t i5
+                  , const size_t i6 , const size_t i7 );
+};
+
+void ViewOperatorBoundsErrorAbort< Kokkos::HostSpace >::
+apply( const size_t rank
+     , const size_t n0 , const size_t n1
+     , const size_t n2 , const size_t n3
+     , const size_t n4 , const size_t n5
+     , const size_t n6 , const size_t n7
+     , const size_t i0 , const size_t i1
+     , const size_t i2 , const size_t i3
+     , const size_t i4 , const size_t i5
+     , const size_t i6 , const size_t i7 )
+{
+  char buffer[512];
+
+  snprintf( buffer , sizeof(buffer)
+          , "View operator bounds error : rank(%lu) dim(%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu) index(%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu)"
+          , rank , n0 , n1 , n2 , n3 , n4 , n5 , n6 , n7
+                 , i0 , i1 , i2 , i3 , i4 , i5 , i6 , i7 );
+
+  Kokkos::Impl::throw_runtime_exception( buffer );
+}
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace {
+  const unsigned HOST_SPACE_ATOMIC_MASK = 0xFFFF;
+  const unsigned HOST_SPACE_ATOMIC_XOR_MASK = 0x5A39;
+  static int HOST_SPACE_ATOMIC_LOCKS[HOST_SPACE_ATOMIC_MASK+1];
+}
+
+namespace Impl {
+void init_lock_array_host_space() {
+  static int is_initialized = 0;
+  if(! is_initialized)
+    for(int i = 0; i < static_cast<int> (HOST_SPACE_ATOMIC_MASK+1); i++)
+      HOST_SPACE_ATOMIC_LOCKS[i] = 0;
+}
+
+bool lock_address_host_space(void* ptr) {
+  return 0 == atomic_compare_exchange( &HOST_SPACE_ATOMIC_LOCKS[
+      (( size_t(ptr) >> 2 ) & HOST_SPACE_ATOMIC_MASK) ^ HOST_SPACE_ATOMIC_XOR_MASK] ,
+                                  0 , 1);
+}
+
+void unlock_address_host_space(void* ptr) {
+   atomic_exchange( &HOST_SPACE_ATOMIC_LOCKS[
+      (( size_t(ptr) >> 2 ) & HOST_SPACE_ATOMIC_MASK) ^ HOST_SPACE_ATOMIC_XOR_MASK] ,
+                    0);
+}
+
+}
+}
diff --git a/lib/kokkos/core/src/impl/Kokkos_Memory_Fence.hpp b/lib/kokkos/core/src/impl/Kokkos_Memory_Fence.hpp
new file mode 100644
index 0000000000..eb3da7501e
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Memory_Fence.hpp
@@ -0,0 +1,107 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_MEMORY_FENCE )
+#define KOKKOS_MEMORY_FENCE
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+KOKKOS_FORCEINLINE_FUNCTION
+void memory_fence()
+{
+#if defined( KOKKOS_ATOMICS_USE_CUDA )
+  __threadfence();
+#elif defined( KOKKOS_ATOMICS_USE_GCC ) || \
+      ( defined( KOKKOS_COMPILER_NVCC ) && defined( KOKKOS_ATOMICS_USE_INTEL ) )
+  __sync_synchronize();
+#elif defined( KOKKOS_ATOMICS_USE_INTEL )
+  _mm_mfence();
+#elif defined( KOKKOS_ATOMICS_USE_OMP31 )
+  #pragma omp flush
+#elif defined( KOKKOS_ATOMICS_USE_WINDOWS )
+  MemoryBarrier();
+#else
+ #error "Error: memory_fence() not defined"
+#endif
+}
+
+//////////////////////////////////////////////////////
+// store_fence()
+//
+// If possible use a store fence on the architecture, if not run a full memory fence
+
+KOKKOS_FORCEINLINE_FUNCTION
+void store_fence()
+{
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 )
+  asm volatile (
+	"sfence" ::: "memory"
+  	);
+#else
+  memory_fence();
+#endif
+}
+
+//////////////////////////////////////////////////////
+// load_fence()
+//
+// If possible use a load fence on the architecture, if not run a full memory fence
+
+KOKKOS_FORCEINLINE_FUNCTION
+void load_fence()
+{
+#if defined( KOKKOS_ENABLE_ASM ) && defined( KOKKOS_USE_ISA_X86_64 )
+  asm volatile (
+	"lfence" ::: "memory"
+  	);
+#else
+  memory_fence();
+#endif
+}
+
+} // namespace kokkos
+
+#endif
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_PhysicalLayout.hpp b/lib/kokkos/core/src/impl/Kokkos_PhysicalLayout.hpp
new file mode 100644
index 0000000000..556c96d863
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_PhysicalLayout.hpp
@@ -0,0 +1,73 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_PHYSICAL_LAYOUT_HPP
+#define KOKKOS_PHYSICAL_LAYOUT_HPP
+
+
+#include <Kokkos_View.hpp>
+namespace Kokkos {
+namespace Impl {
+
+
+
+struct PhysicalLayout {
+  enum LayoutType {Left,Right,Scalar,Error};
+  LayoutType layout_type;
+  int rank;
+  long long int stride[8]; //distance between two neighboring elements in a given dimension
+
+  template< class T , class L , class D , class M >
+  PhysicalLayout( const View<T,L,D,M> & view )
+    : layout_type( is_same< typename View<T,L,D,M>::array_layout , LayoutLeft  >::value ? Left : (
+                   is_same< typename View<T,L,D,M>::array_layout , LayoutRight >::value ? Right : Error ))
+    , rank( view.Rank )
+    {
+      for(int i=0;i<8;i++) stride[i] = 0;
+      view.stride( stride );
+    }
+};
+
+}
+}
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Profiling_DeviceInfo.hpp b/lib/kokkos/core/src/impl/Kokkos_Profiling_DeviceInfo.hpp
new file mode 100644
index 0000000000..8ea1e816cd
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Profiling_DeviceInfo.hpp
@@ -0,0 +1,57 @@
+/*
+ //@HEADER
+ // ************************************************************************
+ //
+ //                        Kokkos v. 2.0
+ //              Copyright (2014) Sandia Corporation
+ //
+ // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ // the U.S. Government retains certain rights in this software.
+ //
+ // 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.
+ //
+ // 3. Neither the name of the Corporation nor the names of the
+ // contributors may be used to endorse or promote products derived from
+ // this software without specific prior written permission.
+ //
+ // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+ // 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.
+ //
+ // Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+ //
+ // ************************************************************************
+ //@HEADER
+*/
+
+#ifndef KOKKOSP_DEVICE_INFO_HPP
+#define KOKKOSP_DEVICE_INFO_HPP
+
+namespace Kokkos {
+namespace Profiling {
+
+    struct KokkosPDeviceInfo {
+        uint32_t deviceID;
+    };
+
+}
+}
+
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Profiling_Interface.cpp b/lib/kokkos/core/src/impl/Kokkos_Profiling_Interface.cpp
new file mode 100644
index 0000000000..91faed170a
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Profiling_Interface.cpp
@@ -0,0 +1,186 @@
+/*
+ //@HEADER
+ // ************************************************************************
+ //
+ //                        Kokkos v. 2.0
+ //              Copyright (2014) Sandia Corporation
+ //
+ // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ // the U.S. Government retains certain rights in this software.
+ //
+ // 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.
+ //
+ // 3. Neither the name of the Corporation nor the names of the
+ // contributors may be used to endorse or promote products derived from
+ // this software without specific prior written permission.
+ //
+ // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+ // 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.
+ //
+ // Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+ //
+ // ************************************************************************
+ //@HEADER
+ */
+
+#include <impl/Kokkos_Profiling_Interface.hpp>
+
+#if (KOKKOS_ENABLE_PROFILING)
+#include <string.h>
+
+namespace Kokkos {
+  namespace Profiling {
+    bool profileLibraryLoaded() {
+       	return (NULL != initProfileLibrary);
+    }
+
+    void beginParallelFor(const std::string& kernelPrefix, const uint32_t devID, uint64_t* kernelID) {
+        if(NULL != beginForCallee) {
+            Kokkos::fence();
+            (*beginForCallee)(kernelPrefix.c_str(), devID, kernelID);
+        }
+    }
+
+    void endParallelFor(const uint64_t kernelID) {
+        if(NULL != endForCallee) {
+            Kokkos::fence();
+            (*endForCallee)(kernelID);
+        }
+    }
+
+    void beginParallelScan(const std::string& kernelPrefix, const uint32_t devID, uint64_t* kernelID) {
+        if(NULL != beginScanCallee) {
+            Kokkos::fence();
+            (*beginScanCallee)(kernelPrefix.c_str(), devID, kernelID);
+        }
+    }
+
+    void endParallelScan(const uint64_t kernelID) {
+        if(NULL != endScanCallee) {
+            Kokkos::fence();
+            (*endScanCallee)(kernelID);
+        }
+    }
+    
+    void beginParallelReduce(const std::string& kernelPrefix, const uint32_t devID, uint64_t* kernelID) {
+        if(NULL != beginReduceCallee) {
+            Kokkos::fence();
+            (*beginReduceCallee)(kernelPrefix.c_str(), devID, kernelID);
+        }
+    }
+    
+    void endParallelReduce(const uint64_t kernelID) {
+        if(NULL != endReduceCallee) {
+            Kokkos::fence();
+            (*endReduceCallee)(kernelID);
+        }
+    }
+    
+    void initialize() {
+
+        // Make sure initialize calls happens only once
+        static int is_initialized = 0;
+        if(is_initialized) return;
+        is_initialized = 1;
+
+        void* firstProfileLibrary;
+
+        char* envProfileLibrary  = getenv("KOKKOS_PROFILE_LIBRARY");
+
+	// If we do not find a profiling library in the environment then exit
+	// early.
+	if( NULL == envProfileLibrary ) {
+		return ;
+	}
+
+		char* envProfileCopy = (char*) malloc(sizeof(char) * (strlen(envProfileLibrary) + 1));
+		sprintf(envProfileCopy, "%s", envProfileLibrary);
+
+		char* profileLibraryName = strtok(envProfileCopy, ";");
+
+        if( (NULL != profileLibraryName) && (strcmp(profileLibraryName, "") != 0) ) {
+            firstProfileLibrary = dlopen(profileLibraryName, RTLD_NOW | RTLD_GLOBAL);
+
+            if(NULL == firstProfileLibrary) {
+                std::cerr << "Error: Unable to load KokkosP library: " <<
+                profileLibraryName << std::endl;
+            } else {
+                std::cout << "KokkosP: Library Loaded: " << profileLibraryName << std::endl;
+
+                // dlsym returns a pointer to an object, while we want to assign to pointer to function
+                // A direct cast will give warnings hence, we have to workaround the issue by casting pointer to pointers.
+                auto p1 = dlsym(firstProfileLibrary, "kokkosp_begin_parallel_for");
+                beginForCallee = *((beginFunction*) &p1);
+                auto p2 = dlsym(firstProfileLibrary, "kokkosp_begin_parallel_scan");
+                beginScanCallee = *((beginFunction*) &p2);
+                auto p3 = dlsym(firstProfileLibrary, "kokkosp_begin_parallel_reduce");
+                beginReduceCallee = *((beginFunction*) &p3);
+
+                auto p4 = dlsym(firstProfileLibrary, "kokkosp_end_parallel_scan");
+                endScanCallee = *((endFunction*) &p4);
+                auto p5 = dlsym(firstProfileLibrary, "kokkosp_end_parallel_for");
+                endForCallee = *((endFunction*) &p5);
+                auto p6 = dlsym(firstProfileLibrary, "kokkosp_end_parallel_reduce");
+                endReduceCallee = *((endFunction*) &p6);
+
+                auto p7 = dlsym(firstProfileLibrary, "kokkosp_init_library");
+                initProfileLibrary = *((initFunction*) &p7);
+                auto p8 = dlsym(firstProfileLibrary, "kokkosp_finalize_library");
+                finalizeProfileLibrary = *((finalizeFunction*) &p8);
+            }
+        }
+
+        if(NULL != initProfileLibrary) {
+            (*initProfileLibrary)(0,
+			(uint64_t) KOKKOSP_INTERFACE_VERSION,
+			(uint32_t) 0,
+			NULL);
+        }
+
+		free(envProfileCopy);
+    }
+
+    void finalize() {
+      // Make sure finalize calls happens only once
+      static int is_finalized = 0;
+      if(is_finalized) return;
+      is_finalized = 1;
+
+      if(NULL != finalizeProfileLibrary) {
+        (*finalizeProfileLibrary)();
+
+        // Set all profile hooks to NULL to prevent
+        // any additional calls. Once we are told to
+        // finalize, we mean it
+        beginForCallee = NULL;
+        beginScanCallee = NULL;
+        beginReduceCallee = NULL;
+        endScanCallee = NULL;
+        endForCallee = NULL;
+        endReduceCallee = NULL;
+        initProfileLibrary = NULL;
+        finalizeProfileLibrary = NULL;
+      }
+    }
+  }
+}
+
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Profiling_Interface.hpp b/lib/kokkos/core/src/impl/Kokkos_Profiling_Interface.hpp
new file mode 100644
index 0000000000..4f01256335
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Profiling_Interface.hpp
@@ -0,0 +1,118 @@
+/*
+ //@HEADER
+ // ************************************************************************
+ //
+ //                        Kokkos v. 2.0
+ //              Copyright (2014) Sandia Corporation
+ //
+ // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+ // the U.S. Government retains certain rights in this software.
+ //
+ // 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.
+ //
+ // 3. Neither the name of the Corporation nor the names of the
+ // contributors may be used to endorse or promote products derived from
+ // this software without specific prior written permission.
+ //
+ // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+ // 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.
+ //
+ // Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+ //
+ // ************************************************************************
+ //@HEADER
+ */
+
+#ifndef KOKKOSP_INTERFACE_HPP
+#define KOKKOSP_INTERFACE_HPP
+
+#include <cstddef>
+#include <Kokkos_Core_fwd.hpp>
+#include <Kokkos_Macros.hpp>
+#include <string>
+
+#if (KOKKOS_ENABLE_PROFILING)
+#include <impl/Kokkos_Profiling_DeviceInfo.hpp>
+#include <dlfcn.h>
+#include <iostream>
+#include <stdlib.h>
+#endif
+
+#define KOKKOSP_INTERFACE_VERSION 20150628
+
+#if (KOKKOS_ENABLE_PROFILING)
+namespace Kokkos {
+  namespace Profiling {
+
+    typedef void (*initFunction)(const int,
+	const uint64_t,
+	const uint32_t,
+	KokkosPDeviceInfo*);
+    typedef void (*finalizeFunction)();
+    typedef void (*beginFunction)(const char*, const uint32_t, uint64_t*);
+    typedef void (*endFunction)(uint64_t);
+
+    static initFunction initProfileLibrary = NULL;
+    static finalizeFunction finalizeProfileLibrary = NULL;
+    static beginFunction beginForCallee = NULL;
+    static beginFunction beginScanCallee = NULL;
+    static beginFunction beginReduceCallee = NULL;
+    static endFunction endForCallee = NULL;
+    static endFunction endScanCallee = NULL;
+    static endFunction endReduceCallee = NULL;
+
+    bool profileLibraryLoaded();
+
+    void beginParallelFor(const std::string& kernelPrefix, const uint32_t devID, uint64_t* kernelID);
+    void endParallelFor(const uint64_t kernelID);
+    void beginParallelScan(const std::string& kernelPrefix, const uint32_t devID, uint64_t* kernelID);
+    void endParallelScan(const uint64_t kernelID);
+    void beginParallelReduce(const std::string& kernelPrefix, const uint32_t devID, uint64_t* kernelID);
+    void endParallelReduce(const uint64_t kernelID);
+
+    void initialize();
+    void finalize();
+
+    //Define finalize_fake inline to get rid of warnings for unused static variables
+    inline void finalize_fake() {
+      if(NULL != finalizeProfileLibrary) {
+        (*finalizeProfileLibrary)();
+
+        // Set all profile hooks to NULL to prevent
+        // any additional calls. Once we are told to
+        // finalize, we mean it
+        beginForCallee = NULL;
+        beginScanCallee = NULL;
+        beginReduceCallee = NULL;
+        endScanCallee = NULL;
+        endForCallee = NULL;
+        endReduceCallee = NULL;
+        initProfileLibrary = NULL;
+        finalizeProfileLibrary = NULL;
+      }
+    }
+
+
+  }
+}
+
+#endif
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_Serial.cpp b/lib/kokkos/core/src/impl/Kokkos_Serial.cpp
new file mode 100644
index 0000000000..562c7afc6d
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Serial.cpp
@@ -0,0 +1,119 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdlib.h>
+#include <sstream>
+#include <Kokkos_Serial.hpp>
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_Error.hpp>
+
+#if defined( KOKKOS_HAVE_SERIAL )
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+namespace SerialImpl {
+
+Sentinel::Sentinel() : m_scratch(0), m_reduce_end(0), m_shared_end(0) {}
+
+Sentinel::~Sentinel()
+{
+  if ( m_scratch ) { free( m_scratch ); }
+  m_scratch = 0 ;
+  m_reduce_end = 0 ;
+  m_shared_end = 0 ;
+}
+
+Sentinel & Sentinel::singleton()
+{
+  static Sentinel s ; return s ;
+}
+
+inline
+unsigned align( unsigned n )
+{
+  enum { ALIGN = 0x0100 /* 256 */ , MASK = ALIGN - 1 };
+  return ( n + MASK ) & ~MASK ;
+}
+
+} // namespace
+
+SerialTeamMember::SerialTeamMember( int arg_league_rank
+                                  , int arg_league_size
+                                  , int arg_shared_size
+                                  )
+  : m_space( ((char *) SerialImpl::Sentinel::singleton().m_scratch) + SerialImpl::Sentinel::singleton().m_reduce_end
+           , arg_shared_size )
+  , m_league_rank( arg_league_rank )
+  , m_league_size( arg_league_size )
+{}
+
+} // namespace Impl
+
+void * Serial::scratch_memory_resize( unsigned reduce_size , unsigned shared_size )
+{
+  static Impl::SerialImpl::Sentinel & s = Impl::SerialImpl::Sentinel::singleton();
+
+  reduce_size = Impl::SerialImpl::align( reduce_size );
+  shared_size = Impl::SerialImpl::align( shared_size );
+
+  if ( ( s.m_reduce_end < reduce_size ) ||
+       ( s.m_shared_end < s.m_reduce_end + shared_size ) ) {
+
+    if ( s.m_scratch ) { free( s.m_scratch ); }
+
+    if ( s.m_reduce_end < reduce_size ) s.m_reduce_end = reduce_size ;
+    if ( s.m_shared_end < s.m_reduce_end + shared_size ) s.m_shared_end = s.m_reduce_end + shared_size ;
+
+    s.m_scratch = malloc( s.m_shared_end );
+  }
+
+  return s.m_scratch ;
+}
+
+} // namespace Kokkos
+
+#endif // defined( KOKKOS_HAVE_SERIAL )
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Serial_Task.cpp b/lib/kokkos/core/src/impl/Kokkos_Serial_Task.cpp
new file mode 100644
index 0000000000..e8bdbde6c6
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Serial_Task.cpp
@@ -0,0 +1,147 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_SERIAL ) && defined( KOKKOS_ENABLE_TASKPOLICY )
+
+#include <impl/Kokkos_TaskQueue_impl.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template class TaskQueue< Kokkos::Serial > ;
+
+void TaskQueueSpecialization< Kokkos::Serial >::execute
+  ( TaskQueue< Kokkos::Serial > * const queue )
+{
+  using execution_space = Kokkos::Serial ;
+  using queue_type      = TaskQueue< execution_space > ;
+  using task_root_type  = TaskBase< execution_space , void , void > ;
+  using Member          = TaskExec< execution_space > ;
+
+  task_root_type * const end = (task_root_type *) task_root_type::EndTag ;
+
+  Member exec ;
+
+  // Loop until all queues are empty
+  while ( 0 < queue->m_ready_count ) {
+
+    task_root_type * task = end ;
+
+    for ( int i = 0 ; i < queue_type::NumQueue && end == task ; ++i ) {
+      for ( int j = 0 ; j < 2 && end == task ; ++j ) {
+        task = queue_type::pop_task( & queue->m_ready[i][j] );
+      }
+    }
+
+    if ( end != task ) {
+
+      // pop_task resulted in lock == task->m_next
+      // In the executing state
+
+      (*task->m_apply)( task , & exec );
+
+#if 0
+  printf( "TaskQueue<Serial>::executed: 0x%lx { 0x%lx 0x%lx %d %d %d }\n"
+        , uintptr_t(task)
+        , uintptr_t(task->m_wait)
+        , uintptr_t(task->m_next)
+        , task->m_task_type
+        , task->m_priority
+        , task->m_ref_count );
+#endif
+
+      // If a respawn then re-enqueue otherwise the task is complete
+      // and all tasks waiting on this task are updated.
+      queue->complete( task );
+    }
+    else if ( 0 != queue->m_ready_count ) {
+      Kokkos::abort("TaskQueue<Serial>::execute ERROR: ready_count");
+    }
+  }
+}
+
+void TaskQueueSpecialization< Kokkos::Serial > ::
+  iff_single_thread_recursive_execute(
+    TaskQueue< Kokkos::Serial > * const queue )
+{
+  using execution_space = Kokkos::Serial ;
+  using queue_type      = TaskQueue< execution_space > ;
+  using task_root_type  = TaskBase< execution_space , void , void > ;
+  using Member          = TaskExec< execution_space > ;
+
+  task_root_type * const end = (task_root_type *) task_root_type::EndTag ;
+
+  Member exec ;
+
+  // Loop until no runnable task
+
+  task_root_type * task = end ;
+  
+  do {
+
+    task = end ;
+
+    for ( int i = 0 ; i < queue_type::NumQueue && end == task ; ++i ) {
+      for ( int j = 0 ; j < 2 && end == task ; ++j ) {
+        task = queue_type::pop_task( & queue->m_ready[i][j] );
+      }
+    }
+
+    if ( end == task ) break ;
+
+    (*task->m_apply)( task , & exec );
+
+    queue->complete( task );
+
+  } while(1);
+}
+
+}} /* namespace Kokkos::Impl */
+
+#endif /* #if defined( KOKKOS_HAVE_SERIAL ) && defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Serial_Task.hpp b/lib/kokkos/core/src/impl/Kokkos_Serial_Task.hpp
new file mode 100644
index 0000000000..48a110c5f1
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Serial_Task.hpp
@@ -0,0 +1,271 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_IMPL_SERIAL_TASK_HPP
+#define KOKKOS_IMPL_SERIAL_TASK_HPP
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+
+template<>
+class TaskQueueSpecialization< Kokkos::Serial >
+{
+public:
+
+  using execution_space = Kokkos::Serial ;
+  using memory_space    = Kokkos::HostSpace ;
+  using queue_type      = Kokkos::Impl::TaskQueue< execution_space > ;
+  using task_base_type  = Kokkos::Impl::TaskBase< execution_space , void , void > ;
+
+  static
+  void iff_single_thread_recursive_execute( queue_type * const );
+
+  static
+  void execute( queue_type * const );
+
+  template< typename FunctorType >
+  static
+  void proc_set_apply( task_base_type::function_type * ptr )
+    {
+      using TaskType = TaskBase< Kokkos::Serial
+                               , typename FunctorType::value_type
+                               , FunctorType
+                               > ;
+       *ptr = TaskType::apply ;
+    }
+};
+
+extern template class TaskQueue< Kokkos::Serial > ;
+
+//----------------------------------------------------------------------------
+
+template<>
+class TaskExec< Kokkos::Serial >
+{
+public:
+
+  KOKKOS_INLINE_FUNCTION void team_barrier() const {}
+  KOKKOS_INLINE_FUNCTION int team_rank() const { return 0 ; }
+  KOKKOS_INLINE_FUNCTION int team_size() const { return 1 ; }
+};
+
+template<typename iType>
+struct TeamThreadRangeBoundariesStruct<iType, TaskExec< Kokkos::Serial > >
+{
+  typedef iType index_type;
+  const iType start ;
+  const iType end ;
+  enum {increment = 1};
+  //const  TaskExec< Kokkos::Serial > & thread;
+  TaskExec< Kokkos::Serial > & thread;
+
+  KOKKOS_INLINE_FUNCTION
+  TeamThreadRangeBoundariesStruct
+    //( const TaskExec< Kokkos::Serial > & arg_thread, const iType& arg_count)
+    ( TaskExec< Kokkos::Serial > & arg_thread, const iType& arg_count)
+    : start(0)
+    , end(arg_count)
+    , thread(arg_thread)
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  TeamThreadRangeBoundariesStruct
+    //( const TaskExec< Kokkos::Serial > & arg_thread
+    ( TaskExec< Kokkos::Serial > & arg_thread
+    , const iType& arg_start
+    , const iType & arg_end
+    )
+    : start( arg_start )
+    , end(   arg_end)
+    , thread( arg_thread )
+    {}
+};
+
+}} /* namespace Kokkos::Impl */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+/*
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >
+TeamThreadRange( const Impl::TaskExec< Kokkos::Serial > & thread
+               , const iType & count )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >(thread,count);
+}
+*/
+//TODO const issue omp
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >
+TeamThreadRange( Impl::TaskExec< Kokkos::Serial > & thread
+               , const iType & count )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >(thread,count);
+}
+/*
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::Serial > >
+TeamThreadRange( const Impl:: TaskExec< Kokkos::Serial > & thread, const iType & start , const iType & end )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::Serial > >(thread,start,end);
+}
+*/
+//TODO const issue omp
+template<typename iType>
+KOKKOS_INLINE_FUNCTION
+Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::Serial > >
+TeamThreadRange( Impl:: TaskExec< Kokkos::Serial > & thread, const iType & start , const iType & end )
+{
+  return Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::Serial > >(thread,start,end);
+}
+
+  /** \brief  Inter-thread parallel_for. Executes lambda(iType i) for each i=0..N-1.
+   *
+   * The range i=0..N-1 is mapped to all threads of the the calling thread team.
+   * This functionality requires C++11 support.*/
+template<typename iType, class Lambda>
+KOKKOS_INLINE_FUNCTION
+void parallel_for(const Impl::TeamThreadRangeBoundariesStruct<iType,Impl:: TaskExec< Kokkos::Serial > >& loop_boundaries, const Lambda& lambda) {
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i);
+}
+
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >& loop_boundaries,
+   const Lambda & lambda,
+   ValueType& initialized_result)
+{
+
+  ValueType result = initialized_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i, result);
+
+  initialized_result = result;
+}
+
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >& loop_boundaries,
+   const Lambda & lambda,
+   const JoinType & join,
+   ValueType& initialized_result)
+{
+  ValueType result = initialized_result;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment)
+    lambda(i, result);
+
+  initialized_result = result;
+}
+// placeholder for future function
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >& loop_boundaries,
+   const Lambda & lambda,
+   ValueType& initialized_result)
+{
+}
+// placeholder for future function
+template< typename iType, class Lambda, typename ValueType, class JoinType >
+KOKKOS_INLINE_FUNCTION
+void parallel_reduce
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >& loop_boundaries,
+   const Lambda & lambda,
+   const JoinType & join,
+   ValueType& initialized_result)
+{
+}
+
+template< typename ValueType, typename iType, class Lambda >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan
+  (const Impl::TeamThreadRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >& loop_boundaries,
+   const Lambda & lambda)
+{
+  ValueType accum = 0 ;
+  ValueType val, local_total;
+
+  for( iType i = loop_boundaries.start; i < loop_boundaries.end; i+=loop_boundaries.increment) {
+    local_total = 0;
+    lambda(i,local_total,false);
+    val = accum;
+    lambda(i,val,true);
+    accum += local_total;
+  }
+
+}
+
+// placeholder for future function
+template< typename iType, class Lambda, typename ValueType >
+KOKKOS_INLINE_FUNCTION
+void parallel_scan
+  (const Impl::ThreadVectorRangeBoundariesStruct<iType,Impl::TaskExec< Kokkos::Serial > >& loop_boundaries,
+   const Lambda & lambda)
+{
+}
+
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #ifndef KOKKOS_IMPL_SERIAL_TASK_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.cpp b/lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.cpp
new file mode 100644
index 0000000000..1577df07cd
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.cpp
@@ -0,0 +1,348 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#include <impl/Kokkos_Serial_TaskPolicy.hpp>
+
+#if defined( KOKKOS_HAVE_SERIAL ) && defined( KOKKOS_ENABLE_TASKPOLICY )
+
+#include <stdlib.h>
+#include <stdexcept>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+TaskPolicy< Kokkos::Serial >::member_type &
+TaskPolicy< Kokkos::Serial >::member_single()
+{
+  static member_type s(0,1,0); 
+  return s ;
+}
+
+} // namespace Experimental
+} // namespace Kokkos
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+typedef TaskMember<  Kokkos::Serial , void , void > Task ;
+
+//----------------------------------------------------------------------------
+
+namespace {
+
+inline
+unsigned padded_sizeof_derived( unsigned sizeof_derived )
+{
+  return sizeof_derived +
+    ( sizeof_derived % sizeof(Task*) ? sizeof(Task*) - sizeof_derived % sizeof(Task*) : 0 );
+}
+
+} // namespace
+
+void Task::deallocate( void * ptr )
+{
+  free( ptr );
+}
+
+void * Task::allocate( const unsigned arg_sizeof_derived
+                     , const unsigned arg_dependence_capacity )
+{
+  return malloc( padded_sizeof_derived( arg_sizeof_derived ) + arg_dependence_capacity * sizeof(Task*) );
+}
+
+Task::~TaskMember()
+{
+
+}
+
+Task::TaskMember( const Task::function_verify_type   arg_verify
+                , const Task::function_dealloc_type  arg_dealloc
+                , const Task::function_apply_type    arg_apply
+                , const unsigned                     arg_sizeof_derived
+                , const unsigned                     arg_dependence_capacity
+                )
+  : m_dealloc( arg_dealloc )
+  , m_verify(  arg_verify )
+  , m_apply(   arg_apply )
+  , m_dep( (Task **)( ((unsigned char *) this) + padded_sizeof_derived( arg_sizeof_derived ) ) )
+  , m_wait( 0 )
+  , m_next( 0 )
+  , m_dep_capacity( arg_dependence_capacity )
+  , m_dep_size( 0 )
+  , m_ref_count( 0 )
+  , m_state( TASK_STATE_CONSTRUCTING )
+{
+  for ( unsigned i = 0 ; i < arg_dependence_capacity ; ++i ) m_dep[i] = 0 ;
+}
+
+Task::TaskMember( const Task::function_dealloc_type  arg_dealloc
+                , const Task::function_apply_type    arg_apply
+                , const unsigned                     arg_sizeof_derived
+                , const unsigned                     arg_dependence_capacity
+                )
+  : m_dealloc( arg_dealloc )
+  , m_verify(  & Task::verify_type<void> )
+  , m_apply(   arg_apply )
+  , m_dep( (Task **)( ((unsigned char *) this) + padded_sizeof_derived( arg_sizeof_derived ) ) )
+  , m_wait( 0 )
+  , m_next( 0 )
+  , m_dep_capacity( arg_dependence_capacity )
+  , m_dep_size( 0 )
+  , m_ref_count( 0 )
+  , m_state( TASK_STATE_CONSTRUCTING )
+{
+  for ( unsigned i = 0 ; i < arg_dependence_capacity ; ++i ) m_dep[i] = 0 ;
+}
+
+//----------------------------------------------------------------------------
+
+void Task::throw_error_add_dependence() const
+{
+  std::cerr << "TaskMember< Serial >::add_dependence ERROR"
+            << " state(" << m_state << ")"
+            << " dep_size(" << m_dep_size << ")"
+            << std::endl ;
+  throw std::runtime_error("TaskMember< Serial >::add_dependence ERROR");
+}
+
+void Task::throw_error_verify_type()
+{
+  throw std::runtime_error("TaskMember< Serial >::verify_type ERROR");
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+
+void Task::assign( Task ** const lhs , Task * rhs , const bool no_throw )
+{
+  static const char msg_error_header[]      = "Kokkos::Experimental::Impl::TaskManager<Kokkos::Serial>::assign ERROR" ;
+  static const char msg_error_count[]       = ": negative reference count" ;
+  static const char msg_error_complete[]    = ": destroy task that is not complete" ;
+  static const char msg_error_dependences[] = ": destroy task that has dependences" ;
+  static const char msg_error_exception[]   = ": caught internal exception" ;
+
+  const char * msg_error = 0 ;
+
+  try {
+
+    if ( *lhs ) {
+
+      const int count = --((**lhs).m_ref_count);
+
+      if ( 0 == count ) {
+
+        // Reference count at zero, delete it
+
+        // Should only be deallocating a completed task
+        if ( (**lhs).m_state == Kokkos::Experimental::TASK_STATE_COMPLETE ) {
+
+          // A completed task should not have dependences...
+          for ( int i = 0 ; i < (**lhs).m_dep_size && 0 == msg_error ; ++i ) {
+            if ( (**lhs).m_dep[i] ) msg_error = msg_error_dependences ;
+          }
+        }
+        else {
+          msg_error = msg_error_complete ;
+        }
+
+        if ( 0 == msg_error ) {
+          // Get deletion function and apply it
+          const Task::function_dealloc_type d = (**lhs).m_dealloc ;
+
+          (*d)( *lhs );
+        }
+      }
+      else if ( count <= 0 ) {
+        msg_error = msg_error_count ;
+      }
+    }
+
+    if ( 0 == msg_error && rhs ) { ++( rhs->m_ref_count ); }
+
+    *lhs = rhs ;
+  }
+  catch( ... ) {
+    if ( 0 == msg_error ) msg_error = msg_error_exception ;
+  }
+
+  if ( 0 != msg_error ) {
+    if ( no_throw ) {
+      std::cerr << msg_error_header << msg_error << std::endl ;
+      std::cerr.flush();
+    }
+    else {
+      std::string msg(msg_error_header);
+      msg.append(msg_error);
+      throw std::runtime_error( msg );
+    }
+  }
+}
+#endif
+
+namespace {
+
+Task * s_ready = 0 ;
+Task * s_denied = reinterpret_cast<Task*>( ~((uintptr_t)0) );
+
+}
+
+void Task::schedule()
+{
+  // Execute ready tasks in case the task being scheduled
+  // is dependent upon a waiting and ready task.
+
+  Task::execute_ready_tasks();
+
+  // spawning   : Constructing -> Waiting
+  // respawning : Executing    -> Waiting
+  // updating   : Waiting      -> Waiting
+
+  // Must not be in a dependence linked list:  0 == t->m_next
+
+  const bool ok_state = TASK_STATE_COMPLETE != m_state ;
+  const bool ok_list  = 0 == m_next ;
+
+  if ( ok_state && ok_list ) {
+
+    if ( TASK_STATE_CONSTRUCTING == m_state ) {
+      // Initial scheduling increment,
+      // matched by decrement when task is complete.
+      ++m_ref_count ;
+    }
+
+    // Will be waiting for execution upon return from this function
+
+    m_state = Kokkos::Experimental::TASK_STATE_WAITING ;
+
+    // Insert this task into another dependence that is not complete
+
+    int i = 0 ;
+    for ( ; i < m_dep_size ; ++i ) {
+      Task * const y = m_dep[i] ;
+      if ( y && s_denied != ( m_next = y->m_wait ) ) {
+        y->m_wait = this ; // CAS( & y->m_wait , m_next , this );
+        break ;
+      }
+    }
+    if ( i == m_dep_size ) {
+      // All dependences are complete, insert into the ready list
+      m_next  = s_ready ;
+      s_ready = this ; // CAS( & s_ready , m_next = s_ready , this );
+    }
+  }
+  else {
+    throw std::runtime_error(std::string("Kokkos::Experimental::Impl::Task spawn or respawn state error"));
+  }
+}
+
+void Task::execute_ready_tasks()
+{
+  while ( s_ready ) {
+
+    // Remove this task from the ready list
+
+    // Task * task ;
+    // while ( ! CAS( & s_ready , task = s_ready , s_ready->m_next ) );
+
+    Task * task = s_ready ;
+
+    s_ready = task->m_next ;
+
+    task->m_next = 0 ;
+
+    // precondition: task->m_state = TASK_STATE_WAITING
+    // precondition: task->m_dep[i]->m_state == TASK_STATE_COMPLETE  for all i
+    // precondition: does not exist T such that T->m_wait = task
+    // precondition: does not exist T such that T->m_next = task
+
+    task->m_state = Kokkos::Experimental::TASK_STATE_EXECUTING ;
+
+    (*task->m_apply)( task );
+
+    if ( task->m_state == Kokkos::Experimental::TASK_STATE_EXECUTING ) {
+      // task did not respawn itself
+      task->m_state = Kokkos::Experimental::TASK_STATE_COMPLETE ;
+
+      // release dependences:
+      for ( int i = 0 ; i < task->m_dep_size ; ++i ) {
+        assign( task->m_dep + i , 0 );
+      }
+
+      // Stop other tasks from adding themselves to 'task->m_wait' ;
+
+      Task * x ;
+      // CAS( & task->m_wait , x = task->m_wait , s_denied );
+      x = task->m_wait ; task->m_wait = s_denied ;
+
+      // update tasks waiting on this task
+      while ( x ) {
+        Task * const next = x->m_next ;
+
+        x->m_next = 0 ;
+
+        x->schedule(); // could happen concurrently
+
+        x = next ;
+      }
+
+      // Decrement to match the initial scheduling increment
+      assign( & task , 0 );
+    }
+  }
+}
+
+} // namespace Impl
+} // namespace Experimental
+} // namespace Kokkos
+
+#endif /* #if defined( KOKKOS_HAVE_SERIAL ) && defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.hpp b/lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.hpp
new file mode 100644
index 0000000000..a333f948ae
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Serial_TaskPolicy.hpp
@@ -0,0 +1,677 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#ifndef KOKKOS_EXPERIMENTAL_SERIAL_TASKPOLICY_HPP
+#define KOKKOS_EXPERIMENTAL_SERIAL_TASKPOLICY_HPP
+
+#include <Kokkos_Macros.hpp>
+
+#if defined( KOKKOS_HAVE_SERIAL )
+
+#include <string>
+#include <typeinfo>
+#include <stdexcept>
+
+#include <Kokkos_Serial.hpp>
+#include <Kokkos_TaskPolicy.hpp>
+#include <Kokkos_View.hpp>
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+#include <impl/Kokkos_FunctorAdapter.hpp>
+
+//----------------------------------------------------------------------------
+/*  Inheritance structure to allow static_cast from the task root type
+ *  and a task's FunctorType.
+ *
+ *    task_root_type == TaskMember< Space , void , void >
+ *
+ *    TaskMember< PolicyType , ResultType , FunctorType >
+ *      : TaskMember< PolicyType::Space , ResultType , FunctorType >
+ *      { ... };
+ *
+ *    TaskMember< Space , ResultType , FunctorType >
+ *      : TaskMember< Space , ResultType , void >
+ *      , FunctorType
+ *      { ... };
+ *
+ *  when ResultType != void
+ *
+ *    TaskMember< Space , ResultType , void >
+ *      : TaskMember< Space , void , void >
+ *      { ... };
+ *
+ */
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+namespace Impl {
+
+/** \brief  Base class for all tasks in the Serial execution space */
+template<>
+class TaskMember< Kokkos::Serial , void , void >
+{
+public:
+
+  typedef void         (* function_apply_type)  ( TaskMember * );
+  typedef void         (* function_dealloc_type)( TaskMember * );
+  typedef TaskMember * (* function_verify_type) ( TaskMember * );
+
+private:
+
+  const function_dealloc_type  m_dealloc ; ///< Deallocation
+  const function_verify_type   m_verify ;  ///< Result type verification
+  const function_apply_type    m_apply ;   ///< Apply function
+  TaskMember ** const          m_dep ;     ///< Dependences
+  TaskMember *                 m_wait ;    ///< Linked list of tasks waiting on this task
+  TaskMember *                 m_next ;    ///< Linked list of tasks waiting on a different task
+  const int                    m_dep_capacity ; ///< Capacity of dependences
+  int                          m_dep_size ;     ///< Actual count of dependences
+  int                          m_ref_count ;    ///< Reference count
+  int                          m_state ;        ///< State of the task
+
+  // size = 6 Pointers + 4 ints
+
+  TaskMember() /* = delete */ ;
+  TaskMember( const TaskMember & ) /* = delete */ ;
+  TaskMember & operator = ( const TaskMember & ) /* = delete */ ;
+
+  static void * allocate( const unsigned arg_sizeof_derived , const unsigned arg_dependence_capacity );
+  static void   deallocate( void * );
+
+  void throw_error_add_dependence() const ;
+  static void throw_error_verify_type();
+
+  template < class DerivedTaskType >
+  static
+  void deallocate( TaskMember * t )
+    {
+      DerivedTaskType * ptr = static_cast< DerivedTaskType * >(t);
+      ptr->~DerivedTaskType();
+      deallocate( (void *) ptr );
+    }
+
+protected :
+
+  ~TaskMember();
+
+  // Used by TaskMember< Serial , ResultType , void >
+  TaskMember( const function_verify_type   arg_verify
+            , const function_dealloc_type  arg_dealloc
+            , const function_apply_type    arg_apply
+            , const unsigned               arg_sizeof_derived
+            , const unsigned               arg_dependence_capacity
+            );
+
+  // Used for TaskMember< Serial , void , void >
+  TaskMember( const function_dealloc_type  arg_dealloc
+            , const function_apply_type    arg_apply
+            , const unsigned               arg_sizeof_derived
+            , const unsigned               arg_dependence_capacity
+            );
+
+public:
+
+  template< typename ResultType >
+  KOKKOS_FUNCTION static
+  TaskMember * verify_type( TaskMember * t )
+    {
+      enum { check_type = ! Kokkos::Impl::is_same< ResultType , void >::value };
+
+      if ( check_type && t != 0 ) {
+
+        // Verify that t->m_verify is this function
+        const function_verify_type self = & TaskMember::template verify_type< ResultType > ;
+
+        if ( t->m_verify != self ) {
+          t = 0 ;
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+          throw_error_verify_type();
+#endif
+        }
+      }
+      return t ;
+    }
+
+  //----------------------------------------
+  /*  Inheritence Requirements on task types:
+   *    typedef  FunctorType::value_type  value_type ;
+   *    class DerivedTaskType
+   *      : public TaskMember< Serial , value_type , FunctorType >
+   *      { ... };
+   *    class TaskMember< Serial , value_type , FunctorType >
+   *      : public TaskMember< Serial , value_type , void >
+   *      , public Functor
+   *      { ... };
+   *  If value_type != void
+   *    class TaskMember< Serial , value_type , void >
+   *      : public TaskMember< Serial , void , void >
+   *
+   *  Allocate space for DerivedTaskType followed by TaskMember*[ dependence_capacity ]
+   *
+   */
+
+  /** \brief  Allocate and construct a single-thread task */
+  template< class DerivedTaskType >
+  static
+  TaskMember * create( const typename DerivedTaskType::functor_type &  arg_functor
+                     , const unsigned                                  arg_dependence_capacity
+                     )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+      typedef typename functor_type::value_type       value_type ;
+
+      DerivedTaskType * const task =
+        new( allocate( sizeof(DerivedTaskType) , arg_dependence_capacity ) )
+          DerivedTaskType( & TaskMember::template deallocate< DerivedTaskType >
+                         , & TaskMember::template apply_single< functor_type , value_type >
+                         , sizeof(DerivedTaskType)
+                         , arg_dependence_capacity
+                         , arg_functor );
+
+      return static_cast< TaskMember * >( task );
+    }
+
+  /** \brief  Allocate and construct a data parallel task */
+  template< class DerivedTaskType >
+  static
+  TaskMember * create( const typename DerivedTaskType::policy_type &   arg_policy
+                     , const typename DerivedTaskType::functor_type &  arg_functor
+                     , const unsigned                                  arg_dependence_capacity
+                     )
+    {
+      DerivedTaskType * const task =
+        new( allocate( sizeof(DerivedTaskType) , arg_dependence_capacity ) )
+          DerivedTaskType( & TaskMember::template deallocate< DerivedTaskType >
+                         , sizeof(DerivedTaskType)
+                         , arg_dependence_capacity
+                         , arg_policy
+                         , arg_functor
+                         );
+
+      return static_cast< TaskMember * >( task );
+    }
+
+  /** \brief  Allocate and construct a thread-team task */
+  template< class DerivedTaskType >
+  static
+  TaskMember * create_team( const typename DerivedTaskType::functor_type &  arg_functor
+                          , const unsigned                                  arg_dependence_capacity
+                          )
+    {
+      typedef typename DerivedTaskType::functor_type  functor_type ;
+      typedef typename functor_type::value_type       value_type ;
+
+      DerivedTaskType * const task =
+        new( allocate( sizeof(DerivedTaskType) , arg_dependence_capacity ) )
+          DerivedTaskType( & TaskMember::template deallocate< DerivedTaskType >
+                         , & TaskMember::template apply_team< functor_type , value_type >
+                         , sizeof(DerivedTaskType)
+                         , arg_dependence_capacity
+                         , arg_functor );
+
+      return static_cast< TaskMember * >( task );
+    }
+
+  void schedule();
+  static void execute_ready_tasks();
+
+  //----------------------------------------
+
+  typedef FutureValueTypeIsVoidError get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const { return get_result_type() ; }
+
+  KOKKOS_INLINE_FUNCTION
+  Kokkos::Experimental::TaskState get_state() const { return Kokkos::Experimental::TaskState( m_state ); }
+
+  //----------------------------------------
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+  static
+  void assign( TaskMember ** const lhs , TaskMember * const rhs , const bool no_throw = false );
+#else
+  KOKKOS_INLINE_FUNCTION static
+  void assign( TaskMember ** const lhs , TaskMember * const rhs , const bool no_throw = false ) {}
+#endif
+
+  KOKKOS_INLINE_FUNCTION
+  TaskMember * get_dependence( int i ) const
+    { return ( Kokkos::Experimental::TASK_STATE_EXECUTING == m_state && 0 <= i && i < m_dep_size ) ? m_dep[i] : (TaskMember*) 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  int get_dependence() const
+    { return m_dep_size ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void clear_dependence()
+    {
+      for ( int i = 0 ; i < m_dep_size ; ++i ) assign( m_dep + i , 0 );
+      m_dep_size = 0 ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void add_dependence( TaskMember * before )
+    {
+      if ( ( Kokkos::Experimental::TASK_STATE_CONSTRUCTING == m_state ||
+             Kokkos::Experimental::TASK_STATE_EXECUTING    == m_state ) &&
+           m_dep_size < m_dep_capacity ) {
+        assign( m_dep + m_dep_size , before );
+        ++m_dep_size ;
+      }
+      else {
+        throw_error_add_dependence();
+      }
+    }
+
+  //----------------------------------------
+
+  template< class FunctorType , class ResultType >
+  KOKKOS_INLINE_FUNCTION static
+  void apply_single( typename Kokkos::Impl::enable_if< ! Kokkos::Impl::is_same< ResultType , void >::value , TaskMember * >::type t )
+    {
+      typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > derived_type ;
+
+      // TaskMember< Kokkos::Serial , ResultType , FunctorType >
+      //   : public TaskMember< Kokkos::Serial , ResultType , void >
+      //   , public FunctorType
+      //   { ... };
+
+      derived_type & m = * static_cast< derived_type * >( t );
+
+      Kokkos::Impl::FunctorApply< FunctorType , void , ResultType & >::apply( (FunctorType &) m , & m.m_result );
+    }
+
+  template< class FunctorType , class ResultType >
+  KOKKOS_INLINE_FUNCTION static
+  void apply_single( typename Kokkos::Impl::enable_if< Kokkos::Impl::is_same< ResultType , void >::value , TaskMember * >::type t )
+    {
+      typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > derived_type ;
+
+      // TaskMember< Kokkos::Serial , ResultType , FunctorType >
+      //   : public TaskMember< Kokkos::Serial , ResultType , void >
+      //   , public FunctorType
+      //   { ... };
+
+      derived_type & m = * static_cast< derived_type * >( t );
+
+      Kokkos::Impl::FunctorApply< FunctorType , void , void >::apply( (FunctorType &) m );
+    }
+
+  //----------------------------------------
+
+  template< class FunctorType , class ResultType >
+  static
+  void apply_team( typename Kokkos::Impl::enable_if< ! Kokkos::Impl::is_same< ResultType , void >::value , TaskMember * >::type t )
+    {
+      typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > derived_type ;
+      typedef Kokkos::Impl::SerialTeamMember                          member_type ;
+
+      // TaskMember< Kokkos::Serial , ResultType , FunctorType >
+      //   : public TaskMember< Kokkos::Serial , ResultType , void >
+      //   , public FunctorType
+      //   { ... };
+
+      derived_type & m = * static_cast< derived_type * >( t );
+
+      m.FunctorType::apply( member_type(0,1,0) , m.m_result );
+    }
+
+  template< class FunctorType , class ResultType >
+  static
+  void apply_team( typename Kokkos::Impl::enable_if< Kokkos::Impl::is_same< ResultType , void >::value , TaskMember * >::type t )
+    {
+      typedef TaskMember< Kokkos::Serial , ResultType , FunctorType > derived_type ;
+      typedef Kokkos::Impl::SerialTeamMember                          member_type ;
+
+      // TaskMember< Kokkos::Serial , ResultType , FunctorType >
+      //   : public TaskMember< Kokkos::Serial , ResultType , void >
+      //   , public FunctorType
+      //   { ... };
+
+      derived_type & m = * static_cast< derived_type * >( t );
+
+      m.FunctorType::apply( member_type(0,1,0) );
+    }
+};
+
+//----------------------------------------------------------------------------
+/** \brief  Base class for tasks with a result value in the Serial execution space.
+ *
+ *  The FunctorType must be void because this class is accessed by the
+ *  Future class for the task and result value.
+ *
+ *  Must be derived from TaskMember<S,void,void> 'root class' so the Future class
+ *  can correctly static_cast from the 'root class' to this class.
+ */
+template < class ResultType >
+class TaskMember< Kokkos::Serial , ResultType , void >
+  : public TaskMember< Kokkos::Serial , void , void >
+{
+public:
+
+  ResultType  m_result ;
+
+  typedef const ResultType & get_result_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_result_type get() const { return m_result ; }
+
+protected:
+
+  typedef TaskMember< Kokkos::Serial , void , void >  task_root_type ;
+  typedef task_root_type::function_dealloc_type       function_dealloc_type ;
+  typedef task_root_type::function_apply_type         function_apply_type ;
+
+  inline
+  TaskMember( const function_dealloc_type  arg_dealloc
+            , const function_apply_type    arg_apply
+            , const unsigned               arg_sizeof_derived
+            , const unsigned               arg_dependence_capacity
+            )
+    : task_root_type( & task_root_type::template verify_type< ResultType >
+                    , arg_dealloc
+                    , arg_apply
+                    , arg_sizeof_derived
+                    , arg_dependence_capacity )
+    , m_result()
+    {}
+};
+
+template< class ResultType , class FunctorType >
+class TaskMember< Kokkos::Serial , ResultType , FunctorType >
+  : public TaskMember< Kokkos::Serial , ResultType , void >
+  , public FunctorType
+{
+public:
+
+  typedef FunctorType  functor_type ;
+
+  typedef TaskMember< Kokkos::Serial , void , void >        task_root_type ;
+  typedef TaskMember< Kokkos::Serial , ResultType , void >  task_base_type ;
+  typedef task_root_type::function_dealloc_type             function_dealloc_type ;
+  typedef task_root_type::function_apply_type               function_apply_type ;
+
+  inline
+  TaskMember( const function_dealloc_type  arg_dealloc
+            , const function_apply_type    arg_apply
+            , const unsigned               arg_sizeof_derived
+            , const unsigned               arg_dependence_capacity
+            , const functor_type &         arg_functor
+            )
+    : task_base_type( arg_dealloc , arg_apply , arg_sizeof_derived , arg_dependence_capacity )
+    , functor_type( arg_functor )
+    {}
+};
+
+} /* namespace Impl */
+} /* namespace Experimental */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Experimental {
+
+template<>
+class TaskPolicy< Kokkos::Serial >
+{
+public:
+
+  typedef Kokkos::Serial                  execution_space ;
+  typedef Kokkos::Impl::SerialTeamMember  member_type ;
+
+private:
+
+  typedef Impl::TaskMember< execution_space , void , void > task_root_type ;
+
+  template< class FunctorType >
+  static inline
+  const task_root_type * get_task_root( const FunctorType * f )
+    {
+      typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
+      return static_cast< const task_root_type * >( static_cast< const task_type * >(f) );
+    }
+
+  template< class FunctorType >
+  static inline
+  task_root_type * get_task_root( FunctorType * f )
+    {
+      typedef Impl::TaskMember< execution_space , typename FunctorType::value_type , FunctorType > task_type ;
+      return static_cast< task_root_type * >( static_cast< task_type * >(f) );
+    }
+
+  unsigned m_default_dependence_capacity ;
+
+public:
+
+  // Stubbed out for now.
+  KOKKOS_INLINE_FUNCTION
+  int allocated_task_count() const { return 0 ; }
+
+  TaskPolicy
+    ( const unsigned /* arg_task_max_count */
+    , const unsigned /* arg_task_max_size */
+    , const unsigned arg_task_default_dependence_capacity = 4
+    , const unsigned /* arg_task_team_size */ = 0
+    )
+    : m_default_dependence_capacity( arg_task_default_dependence_capacity )
+    {}
+
+  KOKKOS_FUNCTION TaskPolicy() = default ;
+  KOKKOS_FUNCTION TaskPolicy( TaskPolicy && rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy( const TaskPolicy & rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy & operator = ( TaskPolicy && rhs ) = default ;
+  KOKKOS_FUNCTION TaskPolicy & operator = ( const TaskPolicy & rhs ) = default ;
+
+  //----------------------------------------
+
+  template< class ValueType >
+  KOKKOS_INLINE_FUNCTION
+  const Future< ValueType , execution_space > &
+    spawn( const Future< ValueType , execution_space > & f 
+         , const bool priority = false ) const
+      {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        f.m_task->schedule();
+#endif
+        return f ;
+      }
+
+  //----------------------------------------
+  // Create single-thread task
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  task_create( const FunctorType & functor
+             , const unsigned dependence_capacity = ~0u ) const
+    {
+      typedef typename FunctorType::value_type value_type ;
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >  task_type ;
+      return Future< value_type , execution_space >(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        task_root_type::create< task_type >(
+          functor , ( ~0u == dependence_capacity ? m_default_dependence_capacity : dependence_capacity ) )
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  proc_create( const FunctorType & functor
+             , const unsigned dependence_capacity = ~0u ) const
+    { return task_create( functor , dependence_capacity ); }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  task_create_team( const FunctorType & functor
+                  , const unsigned dependence_capacity = ~0u ) const
+    {
+      typedef typename FunctorType::value_type value_type ;
+      typedef Impl::TaskMember< execution_space , value_type , FunctorType >  task_type ;
+      return Future< value_type , execution_space >(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        task_root_type::create_team< task_type >(
+          functor , ( ~0u == dependence_capacity ? m_default_dependence_capacity : dependence_capacity ) )
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< typename FunctorType::value_type , execution_space >
+  proc_create_team( const FunctorType & functor
+                  , const unsigned dependence_capacity = ~0u ) const
+    { return task_create_team( functor , dependence_capacity ); }
+
+  //----------------------------------------
+  // Add dependence
+  template< class A1 , class A2 , class A3 , class A4 >
+  KOKKOS_INLINE_FUNCTION
+  void add_dependence( const Future<A1,A2> & after
+                     , const Future<A3,A4> & before
+                     , typename Kokkos::Impl::enable_if
+                        < Kokkos::Impl::is_same< typename Future<A1,A2>::execution_space , execution_space >::value
+                          &&
+                          Kokkos::Impl::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
+                        >::type * = 0
+                      ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      after.m_task->add_dependence( before.m_task );
+#endif
+    }
+
+  //----------------------------------------
+  // Functions for an executing task functor to query dependences,
+  // set new dependences, and respawn itself.
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  Future< void , execution_space >
+  get_dependence( const FunctorType * task_functor , int i ) const
+    {
+      return Future<void,execution_space>(
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+        get_task_root(task_functor)->get_dependence(i)
+#endif
+        );
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  int get_dependence( const FunctorType * task_functor ) const
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { return get_task_root(task_functor)->get_dependence(); }
+#else
+    { return 0 ; }
+#endif
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void clear_dependence( FunctorType * task_functor ) const
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { get_task_root(task_functor)->clear_dependence(); }
+#else
+    {}
+#endif
+
+  template< class FunctorType , class A3 , class A4 >
+  KOKKOS_INLINE_FUNCTION
+  void add_dependence( FunctorType * task_functor
+                     , const Future<A3,A4> & before
+                     , typename Kokkos::Impl::enable_if
+                        < Kokkos::Impl::is_same< typename Future<A3,A4>::execution_space , execution_space >::value
+                        >::type * = 0
+                      ) const
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+    { get_task_root(task_functor)->add_dependence( before.m_task ); }
+#else
+    {}
+#endif
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void respawn( FunctorType * task_functor 
+              , const bool priority = false ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      get_task_root(task_functor)->schedule();
+#endif
+    }
+
+  template< class FunctorType >
+  KOKKOS_INLINE_FUNCTION
+  void respawn_needing_memory( FunctorType * task_functor ) const
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      get_task_root(task_functor)->schedule();
+#endif
+    }
+
+  //----------------------------------------
+
+  static member_type & member_single();
+};
+
+inline
+void wait( TaskPolicy< Kokkos::Serial > & )
+{ Impl::TaskMember< Kokkos::Serial , void , void >::execute_ready_tasks(); }
+
+} /* namespace Experimental */
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* defined( KOKKOS_HAVE_SERIAL ) */
+#endif /* #define KOKKOS_EXPERIMENTAL_SERIAL_TASK_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Shape.cpp b/lib/kokkos/core/src/impl/Kokkos_Shape.cpp
new file mode 100644
index 0000000000..da12db1f38
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Shape.cpp
@@ -0,0 +1,178 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+
+#include <sstream>
+#include <impl/Kokkos_Error.hpp>
+#include <impl/Kokkos_Shape.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+void assert_counts_are_equal_throw(
+  const size_t x_count ,
+  const size_t y_count )
+{
+  std::ostringstream msg ;
+
+  msg << "Kokkos::Impl::assert_counts_are_equal_throw( "
+      << x_count << " != " << y_count << " )" ;
+
+  throw_runtime_exception( msg.str() );
+}
+
+void assert_shapes_are_equal_throw(
+  const unsigned x_scalar_size ,
+  const unsigned x_rank ,
+  const size_t   x_N0 , const unsigned x_N1 ,
+  const unsigned x_N2 , const unsigned x_N3 ,
+  const unsigned x_N4 , const unsigned x_N5 ,
+  const unsigned x_N6 , const unsigned x_N7 ,
+
+  const unsigned y_scalar_size ,
+  const unsigned y_rank ,
+  const size_t   y_N0 , const unsigned y_N1 ,
+  const unsigned y_N2 , const unsigned y_N3 ,
+  const unsigned y_N4 , const unsigned y_N5 ,
+  const unsigned y_N6 , const unsigned y_N7 )
+{
+  std::ostringstream msg ;
+
+  msg << "Kokkos::Impl::assert_shape_are_equal_throw( {"
+      << " scalar_size(" << x_scalar_size
+      << ") rank(" << x_rank
+      << ") dimension(" ;
+  if ( 0 < x_rank ) { msg << " " << x_N0 ; }
+  if ( 1 < x_rank ) { msg << " " << x_N1 ; }
+  if ( 2 < x_rank ) { msg << " " << x_N2 ; }
+  if ( 3 < x_rank ) { msg << " " << x_N3 ; }
+  if ( 4 < x_rank ) { msg << " " << x_N4 ; }
+  if ( 5 < x_rank ) { msg << " " << x_N5 ; }
+  if ( 6 < x_rank ) { msg << " " << x_N6 ; }
+  if ( 7 < x_rank ) { msg << " " << x_N7 ; }
+  msg << " ) } != { "
+      << " scalar_size(" << y_scalar_size
+      << ") rank(" << y_rank
+      << ") dimension(" ;
+  if ( 0 < y_rank ) { msg << " " << y_N0 ; }
+  if ( 1 < y_rank ) { msg << " " << y_N1 ; }
+  if ( 2 < y_rank ) { msg << " " << y_N2 ; }
+  if ( 3 < y_rank ) { msg << " " << y_N3 ; }
+  if ( 4 < y_rank ) { msg << " " << y_N4 ; }
+  if ( 5 < y_rank ) { msg << " " << y_N5 ; }
+  if ( 6 < y_rank ) { msg << " " << y_N6 ; }
+  if ( 7 < y_rank ) { msg << " " << y_N7 ; }
+  msg << " ) } )" ;
+
+  throw_runtime_exception( msg.str() );
+}
+
+void AssertShapeBoundsAbort< Kokkos::HostSpace >::apply(
+  const size_t rank ,
+  const size_t n0 , const size_t n1 , 
+  const size_t n2 , const size_t n3 ,
+  const size_t n4 , const size_t n5 ,
+  const size_t n6 , const size_t n7 ,
+
+  const size_t arg_rank ,
+  const size_t i0 , const size_t i1 ,
+  const size_t i2 , const size_t i3 ,
+  const size_t i4 , const size_t i5 ,
+  const size_t i6 , const size_t i7 )
+{
+  std::ostringstream msg ;
+  msg << "Kokkos::Impl::AssertShapeBoundsAbort( shape = {" ;
+  if ( 0 < rank ) { msg << " " << n0 ; }
+  if ( 1 < rank ) { msg << " " << n1 ; }
+  if ( 2 < rank ) { msg << " " << n2 ; }
+  if ( 3 < rank ) { msg << " " << n3 ; }
+  if ( 4 < rank ) { msg << " " << n4 ; }
+  if ( 5 < rank ) { msg << " " << n5 ; }
+  if ( 6 < rank ) { msg << " " << n6 ; }
+  if ( 7 < rank ) { msg << " " << n7 ; }
+  msg << " } index = {" ;
+  if ( 0 < arg_rank ) { msg << " " << i0 ; }
+  if ( 1 < arg_rank ) { msg << " " << i1 ; }
+  if ( 2 < arg_rank ) { msg << " " << i2 ; }
+  if ( 3 < arg_rank ) { msg << " " << i3 ; }
+  if ( 4 < arg_rank ) { msg << " " << i4 ; }
+  if ( 5 < arg_rank ) { msg << " " << i5 ; }
+  if ( 6 < arg_rank ) { msg << " " << i6 ; }
+  if ( 7 < arg_rank ) { msg << " " << i7 ; }
+  msg << " } )" ;
+
+  throw_runtime_exception( msg.str() );
+}
+
+void assert_shape_effective_rank1_at_leastN_throw(
+  const size_t x_rank , const size_t x_N0 ,
+  const size_t x_N1 ,   const size_t x_N2 ,
+  const size_t x_N3 ,   const size_t x_N4 ,
+  const size_t x_N5 ,   const size_t x_N6 ,
+  const size_t x_N7 ,
+  const size_t N0 )
+{
+  std::ostringstream msg ;
+
+  msg << "Kokkos::Impl::assert_shape_effective_rank1_at_leastN_throw( shape = {" ;
+  if ( 0 < x_rank ) { msg << " " << x_N0 ; }
+  if ( 1 < x_rank ) { msg << " " << x_N1 ; }
+  if ( 2 < x_rank ) { msg << " " << x_N2 ; }
+  if ( 3 < x_rank ) { msg << " " << x_N3 ; }
+  if ( 4 < x_rank ) { msg << " " << x_N4 ; }
+  if ( 5 < x_rank ) { msg << " " << x_N5 ; }
+  if ( 6 < x_rank ) { msg << " " << x_N6 ; }
+  if ( 7 < x_rank ) { msg << " " << x_N7 ; }
+  msg << " } N = " << N0 << " )" ;
+
+  throw_runtime_exception( msg.str() );
+}
+
+
+
+}
+}
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Shape.hpp b/lib/kokkos/core/src/impl/Kokkos_Shape.hpp
new file mode 100644
index 0000000000..9749e0a1ff
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Shape.hpp
@@ -0,0 +1,917 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_SHAPE_HPP
+#define KOKKOS_SHAPE_HPP
+
+#include <typeinfo>
+#include <utility>
+#include <Kokkos_Core_fwd.hpp>
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_StaticAssert.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+/** \brief  The shape of a Kokkos with dynamic and static dimensions.
+ *          Dynamic dimensions are member values and static dimensions are
+ *          'static const' values.
+ *
+ *  The upper bound on the array rank is eight.
+ */
+template< unsigned ScalarSize ,
+          unsigned Rank ,
+          unsigned s0  = 1 ,
+          unsigned s1  = 1 ,
+          unsigned s2  = 1 ,
+          unsigned s3  = 1 ,
+          unsigned s4  = 1 ,
+          unsigned s5  = 1 ,
+          unsigned s6  = 1 ,
+          unsigned s7  = 1 >
+struct Shape ;
+
+//----------------------------------------------------------------------------
+/** \brief  Shape equality if the value type, layout, and dimensions
+ *          are equal.
+ */
+template< unsigned xSize , unsigned xRank ,
+          unsigned xN0 , unsigned xN1 , unsigned xN2 , unsigned xN3 ,
+          unsigned xN4 , unsigned xN5 , unsigned xN6 , unsigned xN7 ,
+
+          unsigned ySize , unsigned yRank ,
+          unsigned yN0 , unsigned yN1 , unsigned yN2 , unsigned yN3 ,
+          unsigned yN4 , unsigned yN5 , unsigned yN6 , unsigned yN7 >
+KOKKOS_INLINE_FUNCTION
+bool operator == ( const Shape<xSize,xRank,xN0,xN1,xN2,xN3,xN4,xN5,xN6,xN7> & x ,
+                   const Shape<ySize,yRank,yN0,yN1,yN2,yN3,yN4,yN5,yN6,yN7> & y )
+{
+  enum { same_size = xSize == ySize };
+  enum { same_rank = xRank == yRank };
+
+  return same_size && same_rank &&
+         size_t( x.N0 )   == size_t( y.N0 ) &&
+         unsigned( x.N1 ) == unsigned( y.N1 ) &&
+         unsigned( x.N2 ) == unsigned( y.N2 ) &&
+         unsigned( x.N3 ) == unsigned( y.N3 ) &&
+         unsigned( x.N4 ) == unsigned( y.N4 ) &&
+         unsigned( x.N5 ) == unsigned( y.N5 ) &&
+         unsigned( x.N6 ) == unsigned( y.N6 ) &&
+         unsigned( x.N7 ) == unsigned( y.N7 ) ;
+}
+
+template< unsigned xSize , unsigned xRank ,
+          unsigned xN0 , unsigned xN1 , unsigned xN2 , unsigned xN3 ,
+          unsigned xN4 , unsigned xN5 , unsigned xN6 , unsigned xN7 ,
+
+          unsigned ySize ,unsigned yRank ,
+          unsigned yN0 , unsigned yN1 , unsigned yN2 , unsigned yN3 ,
+          unsigned yN4 , unsigned yN5 , unsigned yN6 , unsigned yN7 >
+KOKKOS_INLINE_FUNCTION
+bool operator != ( const Shape<xSize,xRank,xN0,xN1,xN2,xN3,xN4,xN5,xN6,xN7> & x ,
+                   const Shape<ySize,yRank,yN0,yN1,yN2,yN3,yN4,yN5,yN6,yN7> & y )
+{ return ! operator == ( x , y ); }
+
+//----------------------------------------------------------------------------
+
+void assert_counts_are_equal_throw(
+  const size_t x_count ,
+  const size_t y_count );
+
+inline
+void assert_counts_are_equal(
+  const size_t x_count ,
+  const size_t y_count )
+{
+  if ( x_count != y_count ) {
+    assert_counts_are_equal_throw( x_count , y_count );
+  }
+}
+
+void assert_shapes_are_equal_throw(
+  const unsigned x_scalar_size ,
+  const unsigned x_rank ,
+  const size_t   x_N0 , const unsigned x_N1 ,
+  const unsigned x_N2 , const unsigned x_N3 ,
+  const unsigned x_N4 , const unsigned x_N5 ,
+  const unsigned x_N6 , const unsigned x_N7 ,
+
+  const unsigned y_scalar_size ,
+  const unsigned y_rank ,
+  const size_t   y_N0 , const unsigned y_N1 ,
+  const unsigned y_N2 , const unsigned y_N3 ,
+  const unsigned y_N4 , const unsigned y_N5 ,
+  const unsigned y_N6 , const unsigned y_N7 );
+
+template< unsigned xSize , unsigned xRank ,
+          unsigned xN0 , unsigned xN1 , unsigned xN2 , unsigned xN3 ,
+          unsigned xN4 , unsigned xN5 , unsigned xN6 , unsigned xN7 ,
+
+          unsigned ySize , unsigned yRank ,
+          unsigned yN0 , unsigned yN1 , unsigned yN2 , unsigned yN3 ,
+          unsigned yN4 , unsigned yN5 , unsigned yN6 , unsigned yN7 >
+inline
+void assert_shapes_are_equal(
+  const Shape<xSize,xRank,xN0,xN1,xN2,xN3,xN4,xN5,xN6,xN7> & x ,
+  const Shape<ySize,yRank,yN0,yN1,yN2,yN3,yN4,yN5,yN6,yN7> & y )
+{
+  typedef Shape<xSize,xRank,xN0,xN1,xN2,xN3,xN4,xN5,xN6,xN7> x_type ;
+  typedef Shape<ySize,yRank,yN0,yN1,yN2,yN3,yN4,yN5,yN6,yN7> y_type ;
+
+  if ( x != y ) {
+    assert_shapes_are_equal_throw(
+      x_type::scalar_size, x_type::rank, x.N0, x.N1, x.N2, x.N3, x.N4, x.N5, x.N6, x.N7,
+      y_type::scalar_size, y_type::rank, y.N0, y.N1, y.N2, y.N3, y.N4, y.N5, y.N6, y.N7 );
+  }
+}
+
+template< unsigned xSize , unsigned xRank ,
+          unsigned xN0 , unsigned xN1 , unsigned xN2 , unsigned xN3 ,
+          unsigned xN4 , unsigned xN5 , unsigned xN6 , unsigned xN7 ,
+
+          unsigned ySize , unsigned yRank ,
+          unsigned yN0 , unsigned yN1 , unsigned yN2 , unsigned yN3 ,
+          unsigned yN4 , unsigned yN5 , unsigned yN6 , unsigned yN7 >
+void assert_shapes_equal_dimension(
+  const Shape<xSize,xRank,xN0,xN1,xN2,xN3,xN4,xN5,xN6,xN7> & x ,
+  const Shape<ySize,yRank,yN0,yN1,yN2,yN3,yN4,yN5,yN6,yN7> & y )
+{
+  typedef Shape<xSize,xRank,xN0,xN1,xN2,xN3,xN4,xN5,xN6,xN7> x_type ;
+  typedef Shape<ySize,yRank,yN0,yN1,yN2,yN3,yN4,yN5,yN6,yN7> y_type ;
+
+  // Omit comparison of scalar_size.
+  if ( unsigned( x.rank ) != unsigned( y.rank ) ||
+       size_t( x.N0 )   != size_t( y.N0 ) || 
+       unsigned( x.N1 ) != unsigned( y.N1 ) || 
+       unsigned( x.N2 ) != unsigned( y.N2 ) || 
+       unsigned( x.N3 ) != unsigned( y.N3 ) ||
+       unsigned( x.N4 ) != unsigned( y.N4 ) || 
+       unsigned( x.N5 ) != unsigned( y.N5 ) || 
+       unsigned( x.N6 ) != unsigned( y.N6 ) || 
+       unsigned( x.N7 ) != unsigned( y.N7 ) ) {
+    assert_shapes_are_equal_throw(
+      x_type::scalar_size, x_type::rank, x.N0, x.N1, x.N2, x.N3, x.N4, x.N5, x.N6, x.N7,
+      y_type::scalar_size, y_type::rank, y.N0, y.N1, y.N2, y.N3, y.N4, y.N5, y.N6, y.N7 );
+  }
+}
+
+//----------------------------------------------------------------------------
+
+template< class ShapeType > struct assert_shape_is_rank_zero ;
+template< class ShapeType > struct assert_shape_is_rank_one ;
+
+template< unsigned Size >
+struct assert_shape_is_rank_zero< Shape<Size,0> >
+  : public true_type {};
+
+template< unsigned Size , unsigned s0 >
+struct assert_shape_is_rank_one< Shape<Size,1,s0> >
+  : public true_type {};
+
+//----------------------------------------------------------------------------
+
+/** \brief  Array bounds assertion templated on the execution space
+ *          to allow device-specific abort code.
+ */
+template< class Space >
+struct AssertShapeBoundsAbort ;
+
+template<>
+struct AssertShapeBoundsAbort< Kokkos::HostSpace >
+{
+  static void apply( const size_t rank ,
+                     const size_t n0 , const size_t n1 ,
+                     const size_t n2 , const size_t n3 ,
+                     const size_t n4 , const size_t n5 ,
+                     const size_t n6 , const size_t n7 ,
+                     const size_t arg_rank ,
+                     const size_t i0 , const size_t i1 ,
+                     const size_t i2 , const size_t i3 ,
+                     const size_t i4 , const size_t i5 ,
+                     const size_t i6 , const size_t i7 );
+};
+
+template< class ExecutionSpace >
+struct AssertShapeBoundsAbort
+{
+  KOKKOS_INLINE_FUNCTION
+  static void apply( const size_t rank ,
+                     const size_t n0 , const size_t n1 ,
+                     const size_t n2 , const size_t n3 ,
+                     const size_t n4 , const size_t n5 ,
+                     const size_t n6 , const size_t n7 ,
+                     const size_t arg_rank ,
+                     const size_t i0 , const size_t i1 ,
+                     const size_t i2 , const size_t i3 ,
+                     const size_t i4 , const size_t i5 ,
+                     const size_t i6 , const size_t i7 )
+    {
+      AssertShapeBoundsAbort< Kokkos::HostSpace >
+        ::apply( rank ,    n0 , n1 , n2 , n3 , n4 , n5 , n6 , n7 ,
+                 arg_rank, i0 , i1 , i2 , i3 , i4 , i5 , i6 , i7 );
+    }
+};
+
+template< class ShapeType >
+KOKKOS_INLINE_FUNCTION
+void assert_shape_bounds( const ShapeType & shape ,
+                          const size_t arg_rank ,
+                          const size_t i0 ,
+                          const size_t i1 = 0 ,
+                          const size_t i2 = 0 ,
+                          const size_t i3 = 0 ,
+                          const size_t i4 = 0 ,
+                          const size_t i5 = 0 ,
+                          const size_t i6 = 0 ,
+                          const size_t i7 = 0 )
+{
+  // Must supply at least as many indices as ranks.
+  // Every index must be within bounds.
+  const bool ok = ShapeType::rank <= arg_rank &&
+                  i0 < size_t(shape.N0) && 
+                  i1 < size_t(shape.N1) &&
+                  i2 < size_t(shape.N2) &&
+                  i3 < size_t(shape.N3) &&
+                  i4 < size_t(shape.N4) &&
+                  i5 < size_t(shape.N5) &&
+                  i6 < size_t(shape.N6) &&
+                  i7 < size_t(shape.N7) ;
+
+  if ( ! ok ) {
+    AssertShapeBoundsAbort< Kokkos::Impl::ActiveExecutionMemorySpace >
+      ::apply( ShapeType::rank ,
+               shape.N0 , shape.N1 , shape.N2 , shape.N3 ,
+               shape.N4 , shape.N5 , shape.N6 , shape.N7 ,
+               arg_rank , i0 , i1 , i2 , i3 , i4 , i5 , i6 , i7 );
+  }
+}
+
+#if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_1( S , I0 ) assert_shape_bounds(S,1,I0);
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_2( S , I0 , I1 ) assert_shape_bounds(S,2,I0,I1);
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_3( S , I0 , I1 , I2 ) assert_shape_bounds(S,3,I0,I1,I2);
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_4( S , I0 , I1 , I2 , I3 ) assert_shape_bounds(S,4,I0,I1,I2,I3);
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_5( S , I0 , I1 , I2 , I3 , I4 ) assert_shape_bounds(S,5,I0,I1,I2,I3,I4);
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_6( S , I0 , I1 , I2 , I3 , I4 , I5 ) assert_shape_bounds(S,6,I0,I1,I2,I3,I4,I5);
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_7( S , I0 , I1 , I2 , I3 , I4 , I5 , I6 ) assert_shape_bounds(S,7,I0,I1,I2,I3,I4,I5,I6);
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_8( S , I0 , I1 , I2 , I3 , I4 , I5 , I6 , I7 ) assert_shape_bounds(S,8,I0,I1,I2,I3,I4,I5,I6,I7);
+#else
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_1( S , I0 ) /* */
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_2( S , I0 , I1 ) /* */
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_3( S , I0 , I1 , I2 ) /* */
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_4( S , I0 , I1 , I2 , I3 ) /* */
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_5( S , I0 , I1 , I2 , I3 , I4 ) /* */
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_6( S , I0 , I1 , I2 , I3 , I4 , I5 ) /* */
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_7( S , I0 , I1 , I2 , I3 , I4 , I5 , I6 ) /* */
+#define KOKKOS_ASSERT_SHAPE_BOUNDS_8( S , I0 , I1 , I2 , I3 , I4 , I5 , I6 , I7 ) /* */
+#endif
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// Specialization and optimization for the Rank 0 shape.
+
+template < unsigned ScalarSize >
+struct Shape< ScalarSize , 0, 1,1,1,1, 1,1,1,1 >
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 0 };
+  enum { rank         = 0 };
+
+  enum { N0 = 1 };
+  enum { N1 = 1 };
+  enum { N2 = 1 };
+  enum { N3 = 1 };
+  enum { N4 = 1 };
+  enum { N5 = 1 };
+  enum { N6 = 1 };
+  enum { N7 = 1 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & ,
+               unsigned = 0 , unsigned = 0 , unsigned = 0 , unsigned = 0 ,
+               unsigned = 0 , unsigned = 0 , unsigned = 0 , unsigned = 0 )
+  {}
+};
+
+//----------------------------------------------------------------------------
+
+template< unsigned R > struct assign_shape_dimension ;
+
+#define KOKKOS_ASSIGN_SHAPE_DIMENSION( R ) \
+template<> \
+struct assign_shape_dimension< R > \
+{ \
+  template< class ShapeType > \
+  KOKKOS_INLINE_FUNCTION \
+  assign_shape_dimension( ShapeType & shape \
+                        , typename Impl::enable_if<( R < ShapeType::rank_dynamic ), size_t >::type n \
+                        ) { shape.N ## R = n ; } \
+};
+
+KOKKOS_ASSIGN_SHAPE_DIMENSION(0)
+KOKKOS_ASSIGN_SHAPE_DIMENSION(1)
+KOKKOS_ASSIGN_SHAPE_DIMENSION(2)
+KOKKOS_ASSIGN_SHAPE_DIMENSION(3)
+KOKKOS_ASSIGN_SHAPE_DIMENSION(4)
+KOKKOS_ASSIGN_SHAPE_DIMENSION(5)
+KOKKOS_ASSIGN_SHAPE_DIMENSION(6)
+KOKKOS_ASSIGN_SHAPE_DIMENSION(7)
+
+#undef KOKKOS_ASSIGN_SHAPE_DIMENSION
+
+//----------------------------------------------------------------------------
+// All-static dimension array
+
+template < unsigned ScalarSize ,
+           unsigned Rank ,
+           unsigned s0 ,
+           unsigned s1 ,
+           unsigned s2 ,
+           unsigned s3 ,
+           unsigned s4 ,
+           unsigned s5 ,
+           unsigned s6 ,
+           unsigned s7 >
+struct Shape {
+
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 0 };
+  enum { rank         = Rank };
+
+  enum { N0 = s0 };
+  enum { N1 = s1 };
+  enum { N2 = s2 };
+  enum { N3 = s3 };
+  enum { N4 = s4 };
+  enum { N5 = s5 };
+  enum { N6 = s6 };
+  enum { N7 = s7 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & ,
+               unsigned = 0 , unsigned = 0 , unsigned = 0 , unsigned = 0 ,
+               unsigned = 0 , unsigned = 0 , unsigned = 0 , unsigned = 0 )
+  {}
+};
+
+// 1 == dynamic_rank <= rank <= 8
+template < unsigned ScalarSize ,
+           unsigned Rank ,
+           unsigned s1 ,
+           unsigned s2 ,
+           unsigned s3 ,
+           unsigned s4 ,
+           unsigned s5 ,
+           unsigned s6 ,
+           unsigned s7 >
+struct Shape< ScalarSize , Rank , 0,s1,s2,s3, s4,s5,s6,s7 >
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 1 };
+  enum { rank         = Rank };
+
+  size_t N0 ; // For 1 == dynamic_rank allow  N0 > 2^32
+
+  enum { N1 = s1 };
+  enum { N2 = s2 };
+  enum { N3 = s3 };
+  enum { N4 = s4 };
+  enum { N5 = s5 };
+  enum { N6 = s6 };
+  enum { N7 = s7 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & s ,
+               size_t n0 , unsigned = 0 , unsigned = 0 , unsigned = 0 ,
+               unsigned = 0 , unsigned = 0 , unsigned = 0 , unsigned = 0 )
+  { s.N0 = n0 ; }
+};
+
+// 2 == dynamic_rank <= rank <= 8
+template < unsigned ScalarSize , unsigned Rank ,
+           unsigned s2 ,
+           unsigned s3 ,
+           unsigned s4 ,
+           unsigned s5 ,
+           unsigned s6 ,
+           unsigned s7 >
+struct Shape< ScalarSize , Rank , 0,0,s2,s3, s4,s5,s6,s7 >
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 2 };
+  enum { rank         = Rank };
+
+  unsigned N0 ;
+  unsigned N1 ;
+
+  enum { N2 = s2 };
+  enum { N3 = s3 };
+  enum { N4 = s4 };
+  enum { N5 = s5 };
+  enum { N6 = s6 };
+  enum { N7 = s7 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & s ,
+               unsigned n0 , unsigned n1 , unsigned = 0 , unsigned = 0 ,
+               unsigned = 0 , unsigned = 0 , unsigned = 0 , unsigned = 0 )
+  { s.N0 = n0 ; s.N1 = n1 ; }
+};
+
+// 3 == dynamic_rank <= rank <= 8
+template < unsigned Rank , unsigned ScalarSize ,
+           unsigned s3 ,
+           unsigned s4 ,
+           unsigned s5 ,
+           unsigned s6 ,
+           unsigned s7 >
+struct Shape< ScalarSize , Rank , 0,0,0,s3, s4,s5,s6,s7>
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 3 };
+  enum { rank         = Rank };
+
+  unsigned N0 ;
+  unsigned N1 ;
+  unsigned N2 ;
+
+  enum { N3 = s3 };
+  enum { N4 = s4 };
+  enum { N5 = s5 };
+  enum { N6 = s6 };
+  enum { N7 = s7 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & s ,
+               unsigned n0 , unsigned n1 , unsigned n2 , unsigned = 0 ,
+               unsigned = 0 , unsigned = 0 , unsigned = 0 , unsigned = 0 )
+  { s.N0 = n0 ; s.N1 = n1 ; s.N2 = n2 ; }
+};
+
+// 4 == dynamic_rank <= rank <= 8
+template < unsigned ScalarSize , unsigned Rank ,
+           unsigned s4 ,
+           unsigned s5 ,
+           unsigned s6 ,
+           unsigned s7 >
+struct Shape< ScalarSize , Rank, 0,0,0,0, s4,s5,s6,s7 >
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 4 };
+  enum { rank         = Rank };
+
+  unsigned N0 ;
+  unsigned N1 ;
+  unsigned N2 ;
+  unsigned N3 ;
+
+  enum { N4 = s4 };
+  enum { N5 = s5 };
+  enum { N6 = s6 };
+  enum { N7 = s7 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & s ,
+               unsigned n0 , unsigned n1 , unsigned n2 , unsigned n3 ,
+               unsigned = 0 , unsigned = 0 , unsigned = 0 , unsigned = 0 )
+  { s.N0 = n0 ; s.N1 = n1 ; s.N2 = n2 ; s.N3 = n3 ; }
+};
+
+// 5 == dynamic_rank <= rank <= 8
+template < unsigned ScalarSize , unsigned Rank ,
+           unsigned s5 ,
+           unsigned s6 ,
+           unsigned s7 >
+struct Shape< ScalarSize , Rank , 0,0,0,0, 0,s5,s6,s7 >
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 5 };
+  enum { rank         = Rank };
+
+  unsigned N0 ;
+  unsigned N1 ;
+  unsigned N2 ;
+  unsigned N3 ;
+  unsigned N4 ;
+
+  enum { N5 = s5 };
+  enum { N6 = s6 };
+  enum { N7 = s7 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & s ,
+               unsigned n0 , unsigned n1 , unsigned n2 , unsigned n3 ,
+               unsigned n4 , unsigned = 0 , unsigned = 0 , unsigned = 0 )
+  { s.N0 = n0 ; s.N1 = n1 ; s.N2 = n2 ; s.N3 = n3 ; s.N4 = n4 ; }
+};
+
+// 6 == dynamic_rank <= rank <= 8
+template < unsigned ScalarSize , unsigned Rank ,
+           unsigned s6 ,
+           unsigned s7 >
+struct Shape< ScalarSize , Rank , 0,0,0,0, 0,0,s6,s7 >
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 6 };
+  enum { rank         = Rank };
+
+  unsigned N0 ;
+  unsigned N1 ;
+  unsigned N2 ;
+  unsigned N3 ;
+  unsigned N4 ;
+  unsigned N5 ;
+
+  enum { N6 = s6 };
+  enum { N7 = s7 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & s ,
+               unsigned n0 , unsigned n1 , unsigned n2 , unsigned n3 ,
+               unsigned n4 , unsigned n5 = 0 , unsigned = 0 , unsigned = 0 )
+  {
+    s.N0 = n0 ; s.N1 = n1 ; s.N2 = n2 ; s.N3 = n3 ;
+    s.N4 = n4 ; s.N5 = n5 ;
+  }
+};
+
+// 7 == dynamic_rank <= rank <= 8
+template < unsigned ScalarSize , unsigned Rank ,
+           unsigned s7 >
+struct Shape< ScalarSize , Rank , 0,0,0,0, 0,0,0,s7 >
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 7 };
+  enum { rank         = Rank };
+
+  unsigned N0 ;
+  unsigned N1 ;
+  unsigned N2 ;
+  unsigned N3 ;
+  unsigned N4 ;
+  unsigned N5 ;
+  unsigned N6 ;
+
+  enum { N7 = s7 };
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & s ,
+               unsigned n0 , unsigned n1 , unsigned n2 , unsigned n3 ,
+               unsigned n4 , unsigned n5 , unsigned n6 , unsigned = 0 )
+  {
+    s.N0 = n0 ; s.N1 = n1 ; s.N2 = n2 ; s.N3 = n3 ;
+    s.N4 = n4 ; s.N5 = n5 ; s.N6 = n6 ;
+  }
+};
+
+// 8 == dynamic_rank <= rank <= 8
+template < unsigned ScalarSize >
+struct Shape< ScalarSize , 8 , 0,0,0,0, 0,0,0,0 >
+{
+  enum { scalar_size   = ScalarSize };
+  enum { rank_dynamic = 8 };
+  enum { rank         = 8 };
+
+  unsigned N0 ;
+  unsigned N1 ;
+  unsigned N2 ;
+  unsigned N3 ;
+  unsigned N4 ;
+  unsigned N5 ;
+  unsigned N6 ;
+  unsigned N7 ;
+
+  KOKKOS_INLINE_FUNCTION
+  static
+  void assign( Shape & s ,
+               unsigned n0 , unsigned n1 , unsigned n2 , unsigned n3 ,
+               unsigned n4 , unsigned n5 , unsigned n6 , unsigned n7 )
+  {
+    s.N0 = n0 ; s.N1 = n1 ; s.N2 = n2 ; s.N3 = n3 ;
+    s.N4 = n4 ; s.N5 = n5 ; s.N6 = n6 ; s.N7 = n7 ;
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< class ShapeType , unsigned N ,
+          unsigned R = ShapeType::rank_dynamic >
+struct ShapeInsert ;
+
+template< class ShapeType , unsigned N >
+struct ShapeInsert< ShapeType , N , 0 >
+{
+  typedef Shape< ShapeType::scalar_size ,
+                 ShapeType::rank + 1 ,
+                 N ,
+                 ShapeType::N0 ,
+                 ShapeType::N1 ,
+                 ShapeType::N2 ,
+                 ShapeType::N3 ,
+                 ShapeType::N4 ,
+                 ShapeType::N5 ,
+                 ShapeType::N6 > type ;
+};
+
+template< class ShapeType , unsigned N >
+struct ShapeInsert< ShapeType , N , 1 >
+{
+  typedef Shape< ShapeType::scalar_size ,
+                 ShapeType::rank + 1 ,
+                 0 ,
+                 N ,
+                 ShapeType::N1 ,
+                 ShapeType::N2 ,
+                 ShapeType::N3 ,
+                 ShapeType::N4 ,
+                 ShapeType::N5 ,
+                 ShapeType::N6 > type ;
+};
+
+template< class ShapeType , unsigned N >
+struct ShapeInsert< ShapeType , N , 2 >
+{
+  typedef Shape< ShapeType::scalar_size ,
+                 ShapeType::rank + 1 ,
+                 0 ,
+                 0 ,
+                 N ,
+                 ShapeType::N2 ,
+                 ShapeType::N3 ,
+                 ShapeType::N4 ,
+                 ShapeType::N5 ,
+                 ShapeType::N6 > type ;
+};
+
+template< class ShapeType , unsigned N >
+struct ShapeInsert< ShapeType , N , 3 >
+{
+  typedef Shape< ShapeType::scalar_size ,
+                 ShapeType::rank + 1 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 N ,
+                 ShapeType::N3 ,
+                 ShapeType::N4 ,
+                 ShapeType::N5 ,
+                 ShapeType::N6 > type ;
+};
+
+template< class ShapeType , unsigned N >
+struct ShapeInsert< ShapeType , N , 4 >
+{
+  typedef Shape< ShapeType::scalar_size ,
+                 ShapeType::rank + 1 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 N ,
+                 ShapeType::N4 ,
+                 ShapeType::N5 ,
+                 ShapeType::N6 > type ;
+};
+
+template< class ShapeType , unsigned N >
+struct ShapeInsert< ShapeType , N , 5 >
+{
+  typedef Shape< ShapeType::scalar_size ,
+                 ShapeType::rank + 1 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 N ,
+                 ShapeType::N5 ,
+                 ShapeType::N6 > type ;
+};
+
+template< class ShapeType , unsigned N >
+struct ShapeInsert< ShapeType , N , 6 >
+{
+  typedef Shape< ShapeType::scalar_size ,
+                 ShapeType::rank + 1 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 N ,
+                 ShapeType::N6 > type ;
+};
+
+template< class ShapeType , unsigned N >
+struct ShapeInsert< ShapeType , N , 7 >
+{
+  typedef Shape< ShapeType::scalar_size ,
+                 ShapeType::rank + 1 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 0 ,
+                 N > type ;
+};
+
+//----------------------------------------------------------------------------
+
+template< class DstShape , class SrcShape ,
+          unsigned DstRankDynamic   = DstShape::rank_dynamic ,
+          bool     DstRankDynamicOK = unsigned(DstShape::rank_dynamic) >= unsigned(SrcShape::rank_dynamic) >
+struct ShapeCompatible { enum { value = false }; };
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 8 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) };
+};
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 7 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) &&
+                 unsigned(DstShape::N7) == unsigned(SrcShape::N7) };
+};
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 6 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) &&
+                 unsigned(DstShape::N6) == unsigned(SrcShape::N6) &&
+                 unsigned(DstShape::N7) == unsigned(SrcShape::N7) };
+};
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 5 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) &&
+                 unsigned(DstShape::N5) == unsigned(SrcShape::N5) &&
+                 unsigned(DstShape::N6) == unsigned(SrcShape::N6) &&
+                 unsigned(DstShape::N7) == unsigned(SrcShape::N7) };
+};
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 4 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) &&
+                 unsigned(DstShape::N4) == unsigned(SrcShape::N4) &&
+                 unsigned(DstShape::N5) == unsigned(SrcShape::N5) &&
+                 unsigned(DstShape::N6) == unsigned(SrcShape::N6) &&
+                 unsigned(DstShape::N7) == unsigned(SrcShape::N7) };
+};
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 3 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) &&
+                 unsigned(DstShape::N3) == unsigned(SrcShape::N3) &&
+                 unsigned(DstShape::N4) == unsigned(SrcShape::N4) &&
+                 unsigned(DstShape::N5) == unsigned(SrcShape::N5) &&
+                 unsigned(DstShape::N6) == unsigned(SrcShape::N6) &&
+                 unsigned(DstShape::N7) == unsigned(SrcShape::N7) };
+};
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 2 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) &&
+                 unsigned(DstShape::N2) == unsigned(SrcShape::N2) &&
+                 unsigned(DstShape::N3) == unsigned(SrcShape::N3) &&
+                 unsigned(DstShape::N4) == unsigned(SrcShape::N4) &&
+                 unsigned(DstShape::N5) == unsigned(SrcShape::N5) &&
+                 unsigned(DstShape::N6) == unsigned(SrcShape::N6) &&
+                 unsigned(DstShape::N7) == unsigned(SrcShape::N7) };
+};
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 1 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) &&
+                 unsigned(DstShape::N1) == unsigned(SrcShape::N1) &&
+                 unsigned(DstShape::N2) == unsigned(SrcShape::N2) &&
+                 unsigned(DstShape::N3) == unsigned(SrcShape::N3) &&
+                 unsigned(DstShape::N4) == unsigned(SrcShape::N4) &&
+                 unsigned(DstShape::N5) == unsigned(SrcShape::N5) &&
+                 unsigned(DstShape::N6) == unsigned(SrcShape::N6) &&
+                 unsigned(DstShape::N7) == unsigned(SrcShape::N7) };
+};
+
+template< class DstShape , class SrcShape >
+struct ShapeCompatible< DstShape , SrcShape , 0 , true >
+{
+  enum { value = unsigned(DstShape::scalar_size) == unsigned(SrcShape::scalar_size) &&
+                 unsigned(DstShape::N0) == unsigned(SrcShape::N0) &&
+                 unsigned(DstShape::N1) == unsigned(SrcShape::N1) &&
+                 unsigned(DstShape::N2) == unsigned(SrcShape::N2) &&
+                 unsigned(DstShape::N3) == unsigned(SrcShape::N3) &&
+                 unsigned(DstShape::N4) == unsigned(SrcShape::N4) &&
+                 unsigned(DstShape::N5) == unsigned(SrcShape::N5) &&
+                 unsigned(DstShape::N6) == unsigned(SrcShape::N6) &&
+                 unsigned(DstShape::N7) == unsigned(SrcShape::N7) };
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< unsigned ScalarSize , unsigned Rank ,
+          unsigned s0 , unsigned s1 , unsigned s2 , unsigned s3 ,
+          unsigned s4 , unsigned s5 , unsigned s6 , unsigned s7 ,
+          typename iType >
+KOKKOS_INLINE_FUNCTION
+size_t dimension( 
+  const Shape<ScalarSize,Rank,s0,s1,s2,s3,s4,s5,s6,s7> & shape ,
+  const iType & r )
+{
+  return 0 == r ? shape.N0 : (
+         1 == r ? shape.N1 : (
+         2 == r ? shape.N2 : (
+         3 == r ? shape.N3 : (
+         4 == r ? shape.N4 : (
+         5 == r ? shape.N5 : (
+         6 == r ? shape.N6 : (
+         7 == r ? shape.N7 : 1 )))))));
+}
+
+template< unsigned ScalarSize , unsigned Rank ,
+          unsigned s0 , unsigned s1 , unsigned s2 , unsigned s3 ,
+          unsigned s4 , unsigned s5 , unsigned s6 , unsigned s7 >
+KOKKOS_INLINE_FUNCTION
+size_t cardinality_count(
+  const Shape<ScalarSize,Rank,s0,s1,s2,s3,s4,s5,s6,s7> & shape )
+{
+  return size_t(shape.N0) * shape.N1 * shape.N2 * shape.N3 *
+         shape.N4 * shape.N5 * shape.N6 * shape.N7 ;
+}
+
+//----------------------------------------------------------------------------
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_CORESHAPE_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Singleton.hpp b/lib/kokkos/core/src/impl/Kokkos_Singleton.hpp
new file mode 100644
index 0000000000..86bc94ab0b
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Singleton.hpp
@@ -0,0 +1,55 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_SINGLETON_HPP
+#define KOKKOS_SINGLETON_HPP
+
+#include <Kokkos_Macros.hpp>
+#include <cstddef>
+
+namespace Kokkos { namespace Impl {
+
+
+}} // namespace Kokkos::Impl
+
+#endif // KOKKOS_SINGLETON_HPP
diff --git a/lib/kokkos/core/src/impl/Kokkos_StaticAssert.hpp b/lib/kokkos/core/src/impl/Kokkos_StaticAssert.hpp
new file mode 100644
index 0000000000..25e2ec9dc1
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_StaticAssert.hpp
@@ -0,0 +1,79 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_STATICASSERT_HPP
+#define KOKKOS_STATICASSERT_HPP
+
+namespace Kokkos {
+namespace Impl {
+
+template < bool , class T = void >
+struct StaticAssert ;
+
+template< class T >
+struct StaticAssert< true , T > {
+  typedef T type ;
+  static const bool value = true ;
+};
+
+template < class A , class B >
+struct StaticAssertSame ;
+
+template < class A >
+struct StaticAssertSame<A,A> { typedef A type ; };
+
+template < class A , class B >
+struct StaticAssertAssignable ;
+
+template < class A >
+struct StaticAssertAssignable<A,A> { typedef A type ; };
+
+template < class A >
+struct StaticAssertAssignable< const A , A > { typedef const A type ; };
+
+} // namespace Impl
+} // namespace Kokkos
+
+#endif /* KOKKOS_STATICASSERT_HPP */
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Synchronic.hpp b/lib/kokkos/core/src/impl/Kokkos_Synchronic.hpp
new file mode 100644
index 0000000000..b2aea14df4
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Synchronic.hpp
@@ -0,0 +1,693 @@
+/*
+
+Copyright (c) 2014, NVIDIA Corporation
+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 HOLDER 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 KOKKOS_SYNCHRONIC_HPP
+#define KOKKOS_SYNCHRONIC_HPP
+
+#include <impl/Kokkos_Synchronic_Config.hpp>
+
+#include <atomic>
+#include <chrono>
+#include <thread>
+#include <functional>
+#include <algorithm>
+
+namespace Kokkos {
+namespace Impl {
+
+enum notify_hint {
+  notify_all,
+  notify_one,
+  notify_none
+};
+enum expect_hint {
+  expect_urgent,
+  expect_delay
+};
+
+namespace Details {
+
+template <class S, class T>
+bool __synchronic_spin_wait_for_update(S const& arg, T const& nval, int attempts) noexcept {
+  int i = 0;
+  for(;i < __SYNCHRONIC_SPIN_RELAX(attempts); ++i)
+    if(__builtin_expect(arg.load(std::memory_order_relaxed) != nval,1))
+      return true;
+    else
+      __synchronic_relax();
+  for(;i < attempts; ++i)
+    if(__builtin_expect(arg.load(std::memory_order_relaxed) != nval,1))
+      return true;
+    else
+      __synchronic_yield();
+  return false;
+}
+
+struct __exponential_backoff {
+  __exponential_backoff(int arg_maximum=512) : maximum(arg_maximum), microseconds(8), x(123456789), y(362436069), z(521288629) {
+  }
+  static inline void sleep_for(std::chrono::microseconds const& time) {
+    auto t = time.count();
+    if(__builtin_expect(t > 75,0)) {
+      portable_sleep(time);
+    }
+    else if(__builtin_expect(t > 25,0))
+      __synchronic_yield();
+    else
+      __synchronic_relax();
+  }
+  void sleep_for_step() {
+    sleep_for(step());
+  }
+  std::chrono::microseconds step() {
+    float const f = ranfu();
+    int const t = int(microseconds * f);
+    if(__builtin_expect(f >= 0.95f,0))
+      microseconds = 8;
+    else
+      microseconds = (std::min)(microseconds>>1,maximum);
+    return std::chrono::microseconds(t);
+  }
+private :
+  int maximum, microseconds, x, y, z;
+  int xorshf96() {
+    int t;
+    x ^= x << 16; x ^= x >> 5; x ^= x << 1;
+    t = x; x = y; y = z; z = t ^ x ^ y;
+    return z;
+  }
+  float ranfu() {
+    return (float)(xorshf96()&(~0UL>>1)) / (float)(~0UL>>1);
+  }
+};
+
+template <class T, class Enable = void>
+struct __synchronic_base {
+
+protected:
+  std::atomic<T> atom;
+
+  void notify(notify_hint = notify_all) noexcept {
+  }
+  void notify(notify_hint = notify_all) volatile noexcept {
+  }
+
+public :
+  __synchronic_base() noexcept = default;
+  constexpr __synchronic_base(T v) noexcept : atom(v) { }
+  __synchronic_base(const __synchronic_base&) = delete;
+  ~__synchronic_base() { }
+  __synchronic_base& operator=(const __synchronic_base&) = delete;
+  __synchronic_base& operator=(const __synchronic_base&) volatile = delete;
+
+  void expect_update(T val, expect_hint = expect_urgent) const noexcept {
+    if(__synchronic_spin_wait_for_update(atom, val, __SYNCHRONIC_SPIN_COUNT_A))
+      return;
+    __exponential_backoff b;
+    while(atom.load(std::memory_order_relaxed) == val) {
+      __do_backoff(b);
+      if(__synchronic_spin_wait_for_update(atom, val, __SYNCHRONIC_SPIN_COUNT_B))
+        return;
+    }
+  }
+  void expect_update(T val, expect_hint = expect_urgent) const volatile noexcept {
+    if(__synchronic_spin_wait_for_update(atom, val, __SYNCHRONIC_SPIN_COUNT_A))
+      return;
+    __exponential_backoff b;
+    while(atom.load(std::memory_order_relaxed) == val) {
+      __do_backoff(b);
+      if(__synchronic_spin_wait_for_update(atom, val, __SYNCHRONIC_SPIN_COUNT_B))
+        return;
+    }
+  }
+
+  template <class Clock, class Duration>
+  void expect_update_until(T val, std::chrono::time_point<Clock,Duration> const& then, expect_hint = expect_urgent) const {
+    if(__synchronic_spin_wait_for_update(atom, val, __SYNCHRONIC_SPIN_COUNT_A))
+      return;
+    __exponential_backoff b;
+    std::chrono::milliseconds remains = then - std::chrono::high_resolution_clock::now();
+    while(remains > std::chrono::milliseconds::zero() && atom.load(std::memory_order_relaxed) == val) {
+      __do_backoff(b);
+      if(__synchronic_spin_wait_for_update(atom, val, __SYNCHRONIC_SPIN_COUNT_B))
+        return;
+      remains = then - std::chrono::high_resolution_clock::now();
+    }
+  }
+  template <class Clock, class Duration>
+  void expect_update_until(T val, std::chrono::time_point<Clock,Duration> const& then, expect_hint = expect_urgent) const volatile {
+    if(__synchronic_spin_wait_for_update(atom, val, __SYNCHRONIC_SPIN_COUNT_A))
+      return;
+    __exponential_backoff b;
+    std::chrono::milliseconds remains = then - std::chrono::high_resolution_clock::now();
+    while(remains > std::chrono::milliseconds::zero() && atom.load(std::memory_order_relaxed) == val) {
+      __do_backoff(b);
+      if(__synchronic_spin_wait_for_update(atom, val, __SYNCHRONIC_SPIN_COUNT_B))
+        return;
+      remains = then - std::chrono::high_resolution_clock::now();
+    }
+  }
+};
+
+#ifdef __SYNCHRONIC_COMPATIBLE
+template <class T>
+struct __synchronic_base<T, typename std::enable_if<__SYNCHRONIC_COMPATIBLE(T)>::type> {
+
+public:
+  std::atomic<T> atom;
+
+  void notify(notify_hint hint = notify_all) noexcept {
+    if(__builtin_expect(hint == notify_none,1))
+      return;
+    auto const x = count.fetch_add(0,std::memory_order_acq_rel);
+    if(__builtin_expect(x,0)) {
+      if(__builtin_expect(hint == notify_all,1))
+        __synchronic_wake_all(&atom);
+      else
+        __synchronic_wake_one(&atom);
+    }
+  }
+  void notify(notify_hint hint = notify_all) volatile noexcept {
+    if(__builtin_expect(hint == notify_none,1))
+      return;
+    auto const x = count.fetch_add(0,std::memory_order_acq_rel);
+    if(__builtin_expect(x,0)) {
+      if(__builtin_expect(hint == notify_all,1))
+        __synchronic_wake_all_volatile(&atom);
+      else
+        __synchronic_wake_one_volatile(&atom);
+    }
+  }
+
+public :
+  __synchronic_base() noexcept : count(0) { }
+  constexpr __synchronic_base(T v) noexcept : atom(v), count(0) { }
+  __synchronic_base(const __synchronic_base&) = delete;
+  ~__synchronic_base() { }
+  __synchronic_base& operator=(const __synchronic_base&) = delete;
+  __synchronic_base& operator=(const __synchronic_base&) volatile = delete;
+
+  void expect_update(T val, expect_hint = expect_urgent) const noexcept {
+    if(__builtin_expect(__synchronic_spin_wait_for_update(atom, val,__SYNCHRONIC_SPIN_COUNT_A),1))
+      return;
+    while(__builtin_expect(atom.load(std::memory_order_relaxed) == val,1)) {
+      count.fetch_add(1,std::memory_order_release);
+      __synchronic_wait(&atom,val);
+      count.fetch_add(-1,std::memory_order_acquire);
+    }
+  }
+  void expect_update(T val, expect_hint = expect_urgent) const volatile noexcept {
+    if(__builtin_expect(__synchronic_spin_wait_for_update(atom, val,__SYNCHRONIC_SPIN_COUNT_A),1))
+      return;
+    while(__builtin_expect(atom.load(std::memory_order_relaxed) == val,1)) {
+      count.fetch_add(1,std::memory_order_release);
+      __synchronic_wait_volatile(&atom,val);
+      count.fetch_add(-1,std::memory_order_acquire);
+    }
+  }
+
+  template <class Clock, class Duration>
+  void expect_update_until(T val, std::chrono::time_point<Clock,Duration> const& then, expect_hint = expect_urgent) const {
+    if(__builtin_expect(__synchronic_spin_wait_for_update(atom, val,__SYNCHRONIC_SPIN_COUNT_A),1))
+      return;
+    std::chrono::milliseconds remains = then - std::chrono::high_resolution_clock::now();
+    while(__builtin_expect(remains > std::chrono::milliseconds::zero() && atom.load(std::memory_order_relaxed) == val,1)) {
+      count.fetch_add(1,std::memory_order_release);
+      __synchronic_wait_timed(&atom,val,remains);
+      count.fetch_add(-1,std::memory_order_acquire);
+      remains = then - std::chrono::high_resolution_clock::now();
+    }
+  }
+  template <class Clock, class Duration>
+  void expect_update_until(T val, std::chrono::time_point<Clock,Duration> const& then, expect_hint = expect_urgent) const volatile {
+    if(__builtin_expect(__synchronic_spin_wait_for_update(atom, val,__SYNCHRONIC_SPIN_COUNT_A),1))
+      return;
+    std::chrono::milliseconds remains = then - std::chrono::high_resolution_clock::now();
+    while(__builtin_expect(remains > std::chrono::milliseconds::zero() && atom.load(std::memory_order_relaxed) == val,1)) {
+      count.fetch_add(1,std::memory_order_release);
+      __synchronic_wait_timed_volatile(&atom,val,remains);
+      count.fetch_add(-1,std::memory_order_acquire);
+      remains = then - std::chrono::high_resolution_clock::now();
+    }
+  }
+private:
+  mutable std::atomic<int> count;
+};
+#endif
+
+template <class T, class Enable = void>
+struct __synchronic : public __synchronic_base<T> {
+
+  __synchronic() noexcept = default;
+  constexpr __synchronic(T v) noexcept : __synchronic_base<T>(v) { }
+  __synchronic(const __synchronic&) = delete;
+  __synchronic& operator=(const __synchronic&) = delete;
+  __synchronic& operator=(const __synchronic&) volatile = delete;
+};
+
+template <class T>
+struct __synchronic<T,typename std::enable_if<std::is_integral<T>::value>::type> : public __synchronic_base<T> {
+
+  T fetch_add(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.fetch_add(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_add(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.fetch_add(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_sub(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.fetch_sub(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_sub(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.fetch_sub(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_and(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.fetch_and(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_and(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.fetch_and(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_or(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.fetch_or(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_or(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.fetch_or(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_xor(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.fetch_xor(v,m);
+    this->notify(n);
+    return t;
+  }
+  T fetch_xor(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.fetch_xor(v,m);
+    this->notify(n);
+    return t;
+  }
+
+  __synchronic() noexcept = default;
+  constexpr __synchronic(T v) noexcept : __synchronic_base<T>(v) { }
+  __synchronic(const __synchronic&) = delete;
+  __synchronic& operator=(const __synchronic&) = delete;
+  __synchronic& operator=(const __synchronic&) volatile = delete;
+
+  T operator=(T v) volatile noexcept {
+    auto const t = this->atom = v;
+    this->notify();
+    return t;
+  }
+  T operator=(T v) noexcept {
+    auto const t = this->atom = v;
+    this->notify();
+    return t;
+  }
+  T operator++(int) volatile noexcept {
+    auto const t = ++this->atom;
+    this->notify();
+    return t;
+  }
+  T operator++(int) noexcept {
+    auto const t = ++this->atom;
+    this->notify();
+    return t;
+  }
+  T operator--(int) volatile noexcept {
+    auto const t = --this->atom;
+    this->notify();
+    return t;
+  }
+  T operator--(int) noexcept {
+    auto const t = --this->atom;
+    this->notify();
+    return t;
+  }
+  T operator++() volatile noexcept {
+    auto const t = this->atom++;
+    this->notify();
+    return t;
+  }
+  T operator++() noexcept {
+    auto const t = this->atom++;
+    this->notify();
+    return t;
+  }
+  T operator--() volatile noexcept {
+    auto const t = this->atom--;
+    this->notify();
+    return t;
+  }
+  T operator--() noexcept {
+    auto const t = this->atom--;
+    this->notify();
+    return t;
+  }
+  T operator+=(T v) volatile noexcept {
+    auto const t = this->atom += v;
+    this->notify();
+    return t;
+  }
+  T operator+=(T v) noexcept {
+    auto const t = this->atom += v;
+    this->notify();
+    return t;
+  }
+  T operator-=(T v) volatile noexcept {
+    auto const t = this->atom -= v;
+    this->notify();
+    return t;
+  }
+  T operator-=(T v) noexcept {
+    auto const t = this->atom -= v;
+    this->notify();
+    return t;
+  }
+  T operator&=(T v) volatile noexcept {
+    auto const t = this->atom &= v;
+    this->notify();
+    return t;
+  }
+  T operator&=(T v) noexcept {
+    auto const t = this->atom &= v;
+    this->notify();
+    return t;
+  }
+  T operator|=(T v) volatile noexcept {
+    auto const t = this->atom |= v;
+    this->notify();
+    return t;
+  }
+  T operator|=(T v) noexcept {
+    auto const t = this->atom |= v;
+    this->notify();
+    return t;
+  }
+  T operator^=(T v) volatile noexcept {
+    auto const t = this->atom ^= v;
+    this->notify();
+    return t;
+  }
+  T operator^=(T v) noexcept {
+    auto const t = this->atom ^= v;
+    this->notify();
+    return t;
+  }
+};
+
+template <class T>
+struct __synchronic<T*> : public __synchronic_base<T*> {
+
+  T* fetch_add(ptrdiff_t v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.fetch_add(v,m);
+    this->notify(n);
+    return t;
+  }
+  T* fetch_add(ptrdiff_t v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.fetch_add(v,m);
+    this->notify(n);
+    return t;
+  }
+  T* fetch_sub(ptrdiff_t v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.fetch_sub(v,m);
+    this->notify(n);
+    return t;
+  }
+  T* fetch_sub(ptrdiff_t v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.fetch_sub(v,m);
+    this->notify(n);
+    return t;
+  }
+
+  __synchronic() noexcept = default;
+  constexpr __synchronic(T* v) noexcept : __synchronic_base<T*>(v) { }
+  __synchronic(const __synchronic&) = delete;
+  __synchronic& operator=(const __synchronic&) = delete;
+  __synchronic& operator=(const __synchronic&) volatile = delete;
+
+  T* operator=(T* v) volatile noexcept {
+    auto const t = this->atom = v;
+    this->notify();
+    return t;
+  }
+  T* operator=(T* v) noexcept {
+    auto const t = this->atom = v;
+    this->notify();
+    return t;
+  }
+  T* operator++(int) volatile noexcept {
+    auto const t = ++this->atom;
+    this->notify();
+    return t;
+  }
+  T* operator++(int) noexcept {
+    auto const t = ++this->atom;
+    this->notify();
+    return t;
+  }
+  T* operator--(int) volatile noexcept {
+    auto const t = --this->atom;
+    this->notify();
+    return t;
+  }
+  T* operator--(int) noexcept {
+    auto const t = --this->atom;
+    this->notify();
+    return t;
+  }
+  T* operator++() volatile noexcept {
+    auto const t = this->atom++;
+    this->notify();
+    return t;
+  }
+  T* operator++() noexcept {
+    auto const t = this->atom++;
+    this->notify();
+    return t;
+  }
+  T* operator--() volatile noexcept {
+    auto const t = this->atom--;
+    this->notify();
+    return t;
+  }
+  T* operator--() noexcept {
+    auto const t = this->atom--;
+    this->notify();
+    return t;
+  }
+  T* operator+=(ptrdiff_t v) volatile noexcept {
+    auto const t = this->atom += v;
+    this->notify();
+    return t;
+  }
+  T* operator+=(ptrdiff_t v) noexcept {
+    auto const t = this->atom += v;
+    this->notify();
+    return t;
+  }
+  T* operator-=(ptrdiff_t v) volatile noexcept {
+    auto const t = this->atom -= v;
+    this->notify();
+    return t;
+  }
+  T* operator-=(ptrdiff_t v) noexcept {
+    auto const t = this->atom -= v;
+    this->notify();
+    return t;
+  }
+};
+
+} //namespace Details
+
+template <class T>
+struct synchronic : public Details::__synchronic<T> {
+
+  bool is_lock_free() const volatile noexcept { return this->atom.is_lock_free(); }
+  bool is_lock_free() const noexcept { return this->atom.is_lock_free(); }
+  void store(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    this->atom.store(v,m);
+    this->notify(n);
+  }
+  void store(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    this->atom.store(v,m);
+    this->notify(n);
+  }
+  T load(std::memory_order m = std::memory_order_seq_cst) const volatile noexcept { return this->atom.load(m); }
+  T load(std::memory_order m = std::memory_order_seq_cst) const noexcept { return this->atom.load(m); }
+
+  operator T() const volatile noexcept { return (T)this->atom; }
+  operator T() const noexcept { return (T)this->atom; }
+
+  T exchange(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.exchange(v,m);
+    this->notify(n);
+    return t;
+  }
+  T exchange(T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.exchange(v,m);
+    this->notify(n);
+    return t;
+  }
+  bool compare_exchange_weak(T& r, T v, std::memory_order m1, std::memory_order m2, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.compare_exchange_weak(r,v,m1,m2);
+    this->notify(n);
+    return t;
+  }
+  bool compare_exchange_weak(T& r, T v, std::memory_order m1, std::memory_order m2, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.compare_exchange_weak(r,v,m1, m2);
+    this->notify(n);
+    return t;
+  }
+  bool compare_exchange_strong(T& r, T v, std::memory_order m1, std::memory_order m2, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.compare_exchange_strong(r,v,m1,m2);
+    this->notify(n);
+    return t;
+  }
+  bool compare_exchange_strong(T& r, T v, std::memory_order m1, std::memory_order m2, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.compare_exchange_strong(r,v,m1,m2);
+    this->notify(n);
+    return t;
+  }
+  bool compare_exchange_weak(T& r, T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.compare_exchange_weak(r,v,m);
+    this->notify(n);
+    return t;
+  }
+  bool compare_exchange_weak(T& r, T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.compare_exchange_weak(r,v,m);
+    this->notify(n);
+    return t;
+  }
+  bool compare_exchange_strong(T& r, T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) volatile noexcept {
+    auto const t = this->atom.compare_exchange_strong(r,v,m);
+    this->notify(n);
+    return t;
+  }
+  bool compare_exchange_strong(T& r, T v, std::memory_order m = std::memory_order_seq_cst, notify_hint n = notify_all) noexcept {
+    auto const t = this->atom.compare_exchange_strong(r,v,m);
+    this->notify(n);
+    return t;
+  }
+
+  synchronic() noexcept = default;
+  constexpr synchronic(T val) noexcept : Details::__synchronic<T>(val) { }
+  synchronic(const synchronic&) = delete;
+  ~synchronic() { }
+  synchronic& operator=(const synchronic&) = delete;
+  synchronic& operator=(const synchronic&) volatile = delete;
+  T operator=(T val) noexcept {
+    return Details::__synchronic<T>::operator=(val);
+  }
+  T operator=(T val) volatile noexcept {
+    return Details::__synchronic<T>::operator=(val);
+  }
+
+  T load_when_not_equal(T val, std::memory_order order = std::memory_order_seq_cst, expect_hint h = expect_urgent) const noexcept {
+    Details::__synchronic<T>::expect_update(val,h);
+    return load(order);
+  }
+  T load_when_not_equal(T val, std::memory_order order = std::memory_order_seq_cst, expect_hint h = expect_urgent) const volatile noexcept {
+    Details::__synchronic<T>::expect_update(val,h);
+    return load(order);
+  }
+  T load_when_equal(T val, std::memory_order order = std::memory_order_seq_cst, expect_hint h = expect_urgent) const noexcept {
+    for(T nval = load(std::memory_order_relaxed); nval != val; nval = load(std::memory_order_relaxed))
+      Details::__synchronic<T>::expect_update(nval,h);
+    return load(order);
+  }
+  T load_when_equal(T val, std::memory_order order = std::memory_order_seq_cst, expect_hint h = expect_urgent) const volatile noexcept {
+    for(T nval = load(std::memory_order_relaxed); nval != val; nval = load(std::memory_order_relaxed))
+      expect_update(nval,h);
+    return load(order);
+  }
+  template <class Rep, class Period>
+  void expect_update_for(T val, std::chrono::duration<Rep,Period> const& delta, expect_hint h = expect_urgent) const {
+    Details::__synchronic<T>::expect_update_until(val, std::chrono::high_resolution_clock::now() + delta,h);
+  }
+  template < class Rep, class Period>
+  void expect_update_for(T val, std::chrono::duration<Rep,Period> const& delta, expect_hint h = expect_urgent) const volatile {
+    Details::__synchronic<T>::expect_update_until(val, std::chrono::high_resolution_clock::now() + delta,h);
+  }
+};
+
+#include <inttypes.h>
+
+typedef synchronic<char> synchronic_char;
+typedef synchronic<char> synchronic_schar;
+typedef synchronic<unsigned char> synchronic_uchar;
+typedef synchronic<short> synchronic_short;
+typedef synchronic<unsigned short> synchronic_ushort;
+typedef synchronic<int> synchronic_int;
+typedef synchronic<unsigned int> synchronic_uint;
+typedef synchronic<long> synchronic_long;
+typedef synchronic<unsigned long> synchronic_ulong;
+typedef synchronic<long long> synchronic_llong;
+typedef synchronic<unsigned long long> synchronic_ullong;
+//typedef synchronic<char16_t> synchronic_char16_t;
+//typedef synchronic<char32_t> synchronic_char32_t;
+typedef synchronic<wchar_t> synchronic_wchar_t;
+
+typedef synchronic<int_least8_t> synchronic_int_least8_t;
+typedef synchronic<uint_least8_t> synchronic_uint_least8_t;
+typedef synchronic<int_least16_t> synchronic_int_least16_t;
+typedef synchronic<uint_least16_t> synchronic_uint_least16_t;
+typedef synchronic<int_least32_t> synchronic_int_least32_t;
+typedef synchronic<uint_least32_t> synchronic_uint_least32_t;
+//typedef synchronic<int_least_64_t> synchronic_int_least_64_t;
+typedef synchronic<uint_least64_t> synchronic_uint_least64_t;
+typedef synchronic<int_fast8_t> synchronic_int_fast8_t;
+typedef synchronic<uint_fast8_t> synchronic_uint_fast8_t;
+typedef synchronic<int_fast16_t> synchronic_int_fast16_t;
+typedef synchronic<uint_fast16_t> synchronic_uint_fast16_t;
+typedef synchronic<int_fast32_t> synchronic_int_fast32_t;
+typedef synchronic<uint_fast32_t> synchronic_uint_fast32_t;
+typedef synchronic<int_fast64_t> synchronic_int_fast64_t;
+typedef synchronic<uint_fast64_t> synchronic_uint_fast64_t;
+typedef synchronic<intptr_t> synchronic_intptr_t;
+typedef synchronic<uintptr_t> synchronic_uintptr_t;
+typedef synchronic<size_t> synchronic_size_t;
+typedef synchronic<ptrdiff_t> synchronic_ptrdiff_t;
+typedef synchronic<intmax_t> synchronic_intmax_t;
+typedef synchronic<uintmax_t> synchronic_uintmax_t;
+
+}
+}
+
+#endif //__SYNCHRONIC_H
diff --git a/lib/kokkos/core/src/impl/Kokkos_Synchronic_Config.hpp b/lib/kokkos/core/src/impl/Kokkos_Synchronic_Config.hpp
new file mode 100644
index 0000000000..0a6dd6e715
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Synchronic_Config.hpp
@@ -0,0 +1,169 @@
+/*
+
+Copyright (c) 2014, NVIDIA Corporation
+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 HOLDER 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 KOKKOS_SYNCHRONIC_CONFIG_H
+#define KOKKOS_SYNCHRONIC_CONFIG_H
+
+#include <thread>
+#include <chrono>
+
+namespace Kokkos {
+namespace Impl {
+
+//the default yield function used inside the implementation is the Standard one
+#define __synchronic_yield std::this_thread::yield
+#define __synchronic_relax __synchronic_yield
+
+#if defined(_MSC_VER)
+    //this is a handy GCC optimization that I use inside the implementation
+    #define __builtin_expect(condition,common) condition
+    #if _MSC_VER <= 1800
+        //using certain keywords that VC++ temporarily doesn't support
+        #define _ALLOW_KEYWORD_MACROS
+        #define noexcept
+        #define constexpr
+    #endif
+    //yes, I define multiple assignment operators
+    #pragma warning(disable:4522)
+    //I don't understand how Windows is so bad at timing functions, but is OK
+    //with straight-up yield loops
+    #define __do_backoff(b) __synchronic_yield()
+#else
+#define __do_backoff(b) b.sleep_for_step()
+#endif
+
+//certain platforms have efficient support for spin-waiting built into the operating system
+#if defined(__linux__) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602)
+#if defined(_WIN32_WINNT)
+#include <winsock2.h>
+#include <Windows.h>
+    //the combination of WaitOnAddress and WakeByAddressAll is supported on Windows 8.1+
+    #define __synchronic_wait(x,v) WaitOnAddress((PVOID)x,(PVOID)&v,sizeof(v),-1)
+    #define __synchronic_wait_timed(x,v,t) WaitOnAddress((PVOID)x,(PVOID)&v,sizeof(v),std::chrono::duration_cast<std::chrono::milliseconds>(t).count())
+    #define __synchronic_wake_one(x) WakeByAddressSingle((PVOID)x)
+    #define __synchronic_wake_all(x) WakeByAddressAll((PVOID)x)
+    #define __synchronic_wait_volatile(x,v) WaitOnAddress((PVOID)x,(PVOID)&v,sizeof(v),-1)
+    #define __synchronic_wait_timed_volatile(x,v,t) WaitOnAddress((PVOID)x,(PVOID)&v,sizeof(v),std::chrono::duration_cast<std::chrono::milliseconds>(t).count())
+    #define __synchronic_wake_one_volatile(x) WakeByAddressSingle((PVOID)x)
+    #define __synchronic_wake_all_volatile(x) WakeByAddressAll((PVOID)x)
+    #define __SYNCHRONIC_COMPATIBLE(x) (std::is_pod<x>::value && (sizeof(x) <= 8))
+
+    inline void native_sleep(unsigned long microseconds)
+    {
+      // What to do if microseconds is < 1000?
+      Sleep(microseconds / 1000);
+    }
+
+    inline void native_yield()
+    {
+      SwitchToThread();
+    }
+#elif defined(__linux__)
+    #include <chrono>
+    #include <time.h>
+    #include <unistd.h>
+    #include <pthread.h>
+    #include <linux/futex.h>
+    #include <sys/syscall.h>
+    #include <climits>
+    #include <cassert>
+    template < class Rep, class Period>
+    inline timespec to_timespec(std::chrono::duration<Rep,Period> const& delta) {
+      struct timespec ts;
+      ts.tv_sec = static_cast<long>(std::chrono::duration_cast<std::chrono::seconds>(delta).count());
+      assert(!ts.tv_sec);
+      ts.tv_nsec = static_cast<long>(std::chrono::duration_cast<std::chrono::nanoseconds>(delta).count());
+      return ts;
+    }
+    inline long futex(void const* addr1, int op, int val1) {
+        return syscall(SYS_futex, addr1, op, val1, 0, 0, 0);
+    }
+    inline long futex(void const* addr1, int op, int val1, struct timespec timeout) {
+        return syscall(SYS_futex, addr1, op, val1, &timeout, 0, 0);
+    }
+    inline void native_sleep(unsigned long microseconds)
+    {
+      usleep(microseconds);
+    }
+    inline void native_yield()
+    {
+      pthread_yield();
+    }
+
+    //the combination of SYS_futex(WAIT) and SYS_futex(WAKE) is supported on all recent Linux distributions
+    #define __synchronic_wait(x,v) futex(x, FUTEX_WAIT_PRIVATE, v)
+    #define __synchronic_wait_timed(x,v,t) futex(x, FUTEX_WAIT_PRIVATE, v, to_timespec(t))
+    #define __synchronic_wake_one(x) futex(x, FUTEX_WAKE_PRIVATE, 1)
+    #define __synchronic_wake_all(x) futex(x, FUTEX_WAKE_PRIVATE, INT_MAX)
+    #define __synchronic_wait_volatile(x,v) futex(x, FUTEX_WAIT, v)
+    #define __synchronic_wait_volatile_timed(x,v,t) futex(x, FUTEX_WAIT, v, to_timespec(t))
+    #define __synchronic_wake_one_volatile(x) futex(x, FUTEX_WAKE, 1)
+    #define __synchronic_wake_all_volatile(x) futex(x, FUTEX_WAKE, INT_MAX)
+    #define __SYNCHRONIC_COMPATIBLE(x) (std::is_integral<x>::value && (sizeof(x) <= 4))
+
+    //the yield function on Linux is better replaced by sched_yield, which is tuned for spin-waiting
+    #undef __synchronic_yield
+    #define __synchronic_yield sched_yield
+
+    //for extremely short wait times, just let another hyper-thread run
+    #undef __synchronic_relax
+    #define __synchronic_relax() asm volatile("rep; nop" ::: "memory")
+
+#endif
+#endif
+
+#ifdef _GLIBCXX_USE_NANOSLEEP
+inline void portable_sleep(std::chrono::microseconds const& time)
+{ std::this_thread::sleep_for(time); }
+#else
+inline void portable_sleep(std::chrono::microseconds const& time)
+{ native_sleep(time.count()); }
+#endif
+
+#ifdef _GLIBCXX_USE_SCHED_YIELD
+inline void portable_yield()
+{ std::this_thread::yield(); }
+#else
+inline void portable_yield()
+{ native_yield(); }
+#endif
+
+//this is the number of times we initially spin, on the first wait attempt
+#define __SYNCHRONIC_SPIN_COUNT_A 16
+
+//this is how decide to yield instead of just spinning, 'c' is the current trip count
+//#define __SYNCHRONIC_SPIN_YIELD(c) true
+#define __SYNCHRONIC_SPIN_RELAX(c) (c>>3)
+
+//this is the number of times we normally spin, on every subsequent wait attempt
+#define __SYNCHRONIC_SPIN_COUNT_B 8
+
+}
+}
+
+#endif //__SYNCHRONIC_CONFIG_H
diff --git a/lib/kokkos/core/src/impl/Kokkos_Synchronic_n3998.hpp b/lib/kokkos/core/src/impl/Kokkos_Synchronic_n3998.hpp
new file mode 100644
index 0000000000..facc8d6d8e
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Synchronic_n3998.hpp
@@ -0,0 +1,162 @@
+/*
+
+Copyright (c) 2014, NVIDIA Corporation
+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 HOLDER 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 KOKKOS_SYNCHRONIC_N3998_HPP
+#define KOKKOS_SYNCHRONIC_N3998_HPP
+
+#include <impl/Kokkos_Synchronic.hpp>
+#include <functional>
+
+/*
+In the section below, a synchronization point represents a point at which a
+thread may block until a given synchronization condition has been reached or
+at which it may notify other threads that a synchronization condition has
+been achieved.
+*/
+namespace Kokkos { namespace Impl {
+
+    /*
+    A latch maintains an internal counter that is initialized when the latch
+    is created. The synchronization condition is reached when the counter is
+    decremented to 0. Threads may block at a synchronization point waiting
+    for the condition to be reached. When the condition is reached, any such
+    blocked threads will be released.
+    */
+    struct latch {
+        latch(int val) : count(val), released(false) { }
+        latch(const latch&) = delete;
+        latch& operator=(const latch&) = delete;
+        ~latch( ) { }
+        void arrive( ) {
+            __arrive( );
+        }
+        void arrive_and_wait( ) {
+            if(!__arrive( ))
+                wait( );
+        }
+        void wait( ) {
+            while(!released.load_when_not_equal(false,std::memory_order_acquire))
+                ;
+        }
+        bool try_wait( ) {
+            return released.load(std::memory_order_acquire);
+        }
+    private:
+        bool __arrive( ) {
+            if(count.fetch_add(-1,std::memory_order_release)!=1)
+                return false;
+            released.store(true,std::memory_order_release);
+            return true;
+        }
+        std::atomic<int> count;
+        synchronic<bool> released;
+    };
+
+    /*
+    A barrier is created with an initial value representing the number of threads
+    that can arrive at the synchronization point. When that many threads have
+    arrived, the  synchronization condition is reached and the threads are
+    released. The barrier will then reset, and may be reused for a new cycle, in
+    which the same set of threads may arrive again at the synchronization point.
+    The same set of threads shall arrive at the barrier in each cycle, otherwise
+    the behaviour is undefined.
+    */
+    struct barrier {
+        barrier(int val) : expected(val), arrived(0), nexpected(val), epoch(0) { }
+        barrier(const barrier&) = delete;
+        barrier& operator=(const barrier&) = delete;
+        ~barrier() { }
+        void arrive_and_wait() {
+            int const myepoch = epoch.load(std::memory_order_relaxed);
+            if(!__arrive(myepoch))
+                while(epoch.load_when_not_equal(myepoch,std::memory_order_acquire) == myepoch)
+                    ;
+        }
+        void arrive_and_drop() {
+            nexpected.fetch_add(-1,std::memory_order_relaxed);
+            __arrive(epoch.load(std::memory_order_relaxed));
+        }
+    private:
+        bool __arrive(int const myepoch) {
+            int const myresult = arrived.fetch_add(1,std::memory_order_acq_rel) + 1;
+            if(__builtin_expect(myresult == expected,0)) {
+                expected = nexpected.load(std::memory_order_relaxed);
+                arrived.store(0,std::memory_order_relaxed);
+                epoch.store(myepoch+1,std::memory_order_release);
+                return true;
+            }
+            return false;
+        }
+        int expected;
+        std::atomic<int> arrived, nexpected;
+        synchronic<int> epoch;
+    };
+
+    /*
+    A notifying barrier behaves as a barrier, but is constructed with a callable
+    completion function that is invoked after all threads have arrived at the
+    synchronization point, and before the synchronization condition is reached.
+    The completion may modify the set of threads that arrives at the barrier in
+    each cycle.
+    */
+    struct notifying_barrier {
+        template <typename T>
+        notifying_barrier(int val, T && f) : expected(val), arrived(0), nexpected(val), epoch(0), completion(std::forward<T>(f)) { }
+        notifying_barrier(const notifying_barrier&) = delete;
+        notifying_barrier& operator=(const notifying_barrier&) = delete;
+        ~notifying_barrier( ) { }
+        void arrive_and_wait() {
+            int const myepoch = epoch.load(std::memory_order_relaxed);
+            if(!__arrive(myepoch))
+                while(epoch.load_when_not_equal(myepoch,std::memory_order_acquire) == myepoch)
+                    ;
+        }
+        void arrive_and_drop() {
+            nexpected.fetch_add(-1,std::memory_order_relaxed);
+            __arrive(epoch.load(std::memory_order_relaxed));
+        }
+    private:
+        bool __arrive(int const myepoch) {
+            int const myresult = arrived.fetch_add(1,std::memory_order_acq_rel) + 1;
+            if(__builtin_expect(myresult == expected,0)) {
+                int const newexpected = completion();
+                expected = newexpected ? newexpected : nexpected.load(std::memory_order_relaxed);
+                arrived.store(0,std::memory_order_relaxed);
+                epoch.store(myepoch+1,std::memory_order_release);
+                return true;
+            }
+            return false;
+        }
+        int expected;
+        std::atomic<int> arrived, nexpected;
+        synchronic<int> epoch;
+        std::function<int()> completion;
+    };
+}}
+
+#endif //__N3998_H
diff --git a/lib/kokkos/core/src/impl/Kokkos_Tags.hpp b/lib/kokkos/core/src/impl/Kokkos_Tags.hpp
new file mode 100644
index 0000000000..0bc2864ff1
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Tags.hpp
@@ -0,0 +1,198 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_TAGS_HPP
+#define KOKKOS_TAGS_HPP
+
+#include <impl/Kokkos_Traits.hpp>
+#include <Kokkos_Core_fwd.hpp>
+#include <type_traits>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+/** KOKKOS_HAVE_TYPE( Type )
+ *
+ * defines a meta-function that check if a type expose an internal typedef or
+ * type alias which matches Type
+ *
+ * e.g.
+ *   KOKKOS_HAVE_TYPE( array_layout );
+ *   struct Foo { using array_layout = void; };
+ *   have_array_layout<Foo>::value == 1;
+ */
+#define KOKKOS_HAVE_TYPE( Type )                                                \
+template <typename T>                                                           \
+struct have_##Type {                                                            \
+  template <typename U> static std::false_type have_type(...);                  \
+  template <typename U> static std::true_type  have_type( typename U::Type* );  \
+  using type = decltype(have_type<T>(nullptr));                                 \
+  static constexpr bool value = type::value;                                    \
+}
+
+/** KOKKOS_IS_CONCEPT( Concept )
+ *
+ * defines a meta-function that check if a type match the given Kokkos concept
+ * type alias which matches Type
+ *
+ * e.g.
+ *   KOKKOS_IS_CONCEPT( array_layout );
+ *   struct Foo { using array_layout = Foo; };
+ *   is_array_layout<Foo>::value == 1;
+ */
+#define KOKKOS_IS_CONCEPT( Concept )                                            \
+template <typename T>                                                           \
+struct is_##Concept {                                                           \
+  template <typename U> static std::false_type have_concept(...);               \
+  template <typename U> static auto have_concept( typename U::Concept* )        \
+                          ->typename std::is_same<T, typename U::Concept>::type;\
+  using type = decltype(have_concept<T>(nullptr));                              \
+  static constexpr bool value = type::value;                                    \
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos { namespace Impl {
+
+template <typename T>
+using is_void = std::is_same<void,T>;
+
+// is_memory_space<T>::value
+KOKKOS_IS_CONCEPT( memory_space );
+
+// is_memory_traits<T>::value
+KOKKOS_IS_CONCEPT( memory_traits );
+
+// is_execution_space<T>::value
+KOKKOS_IS_CONCEPT( execution_space );
+
+// is_execution_policy<T>::value
+KOKKOS_IS_CONCEPT( execution_policy );
+
+// is_array_layout<T>::value
+KOKKOS_IS_CONCEPT( array_layout );
+
+// is_iteration_pattern<T>::value
+KOKKOS_IS_CONCEPT( iteration_pattern );
+
+// is_schedule_type<T>::value
+KOKKOS_IS_CONCEPT( schedule_type );
+
+// is_index_type<T>::value
+KOKKOS_IS_CONCEPT( index_type );
+
+}} // namespace Kokkos::Impl
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template< class ExecutionSpace , class MemorySpace >
+struct Device {
+  static_assert( Impl::is_execution_space<ExecutionSpace>::value
+               , "Execution space is not valid" );
+  static_assert( Impl::is_memory_space<MemorySpace>::value
+               , "Memory space is not valid" );
+  typedef ExecutionSpace execution_space;
+  typedef MemorySpace memory_space;
+  typedef Device<execution_space,memory_space> device_type;
+};
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class C , class Enable = void >
+struct is_space : public Impl::false_type {};
+
+template< class C >
+struct is_space< C
+                 , typename Impl::enable_if<(
+                     Impl::is_same< C , typename C::execution_space >::value ||
+                     Impl::is_same< C , typename C::memory_space    >::value ||
+                     Impl::is_same< C , Device<
+                                             typename C::execution_space,
+                                             typename C::memory_space> >::value
+                   )>::type
+                 >
+  : public Impl::true_type
+{
+  typedef typename C::execution_space  execution_space ;
+  typedef typename C::memory_space     memory_space ;
+
+  // The host_memory_space defines a space with host-resident memory.
+  // If the execution space's memory space is host accessible then use that execution space.
+  // else use the HostSpace.
+  typedef
+      typename Impl::if_c< Impl::is_same< memory_space , HostSpace >::value
+#ifdef KOKKOS_HAVE_CUDA
+                        || Impl::is_same< memory_space , CudaUVMSpace>::value
+                        || Impl::is_same< memory_space , CudaHostPinnedSpace>::value
+#endif
+                          , memory_space , HostSpace >::type
+      host_memory_space ;
+
+  // The host_execution_space defines a space which has access to HostSpace.
+  // If the execution space can access HostSpace then use that execution space.
+  // else use the DefaultHostExecutionSpace.
+#ifdef KOKKOS_HAVE_CUDA
+  typedef
+      typename Impl::if_c< Impl::is_same< execution_space , Cuda >::value
+                          , DefaultHostExecutionSpace , execution_space >::type
+      host_execution_space ;
+#else
+  typedef execution_space host_execution_space;
+#endif
+
+  typedef Device<host_execution_space,host_memory_space> host_mirror_space;
+};
+}
+}
+
+#endif
diff --git a/lib/kokkos/core/src/impl/Kokkos_TaskQueue.hpp b/lib/kokkos/core/src/impl/Kokkos_TaskQueue.hpp
new file mode 100644
index 0000000000..663bb1985d
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_TaskQueue.hpp
@@ -0,0 +1,499 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// Experimental unified task-data parallel manycore LDRD
+
+#ifndef KOKKOS_IMPL_TASKQUEUE_HPP
+#define KOKKOS_IMPL_TASKQUEUE_HPP
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+#include <string>
+#include <typeinfo>
+#include <stdexcept>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+template< typename > class TaskPolicy ;
+
+template< typename Arg1 = void , typename Arg2 = void > class Future ;
+
+} /* namespace Kokkos */
+
+namespace Kokkos {
+namespace Impl {
+
+template< typename , typename , typename > class TaskBase ;
+template< typename > class TaskExec ;
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< typename Space >
+class TaskQueueSpecialization ;
+
+/** \brief  Manage task allocation, deallocation, and scheduling.
+ *
+ *  Task execution is deferred to the TaskQueueSpecialization.
+ *  All other aspects of task management have shared implementation.
+ */
+template< typename ExecSpace >
+class TaskQueue {
+private:
+
+  friend class TaskQueueSpecialization< ExecSpace > ;
+  friend class Kokkos::TaskPolicy< ExecSpace > ;
+
+  using execution_space = ExecSpace ;
+  using specialization  = TaskQueueSpecialization< execution_space > ;
+  using memory_space    = typename specialization::memory_space ;
+  using device_type     = Kokkos::Device< execution_space , memory_space > ;
+  using memory_pool     = Kokkos::Experimental::MemoryPool< device_type > ;
+  using task_root_type  = Kokkos::Impl::TaskBase<execution_space,void,void> ;
+
+  struct Destroy {
+    TaskQueue * m_queue ;
+    void destroy_shared_allocation();
+  };
+
+  //----------------------------------------
+
+  enum : int { NumQueue = 3 };
+
+  // Queue is organized as [ priority ][ type ]
+
+  memory_pool               m_memory ;
+  task_root_type * volatile m_ready[ NumQueue ][ 2 ];
+  long                      m_accum_alloc ; // Accumulated number of allocations
+  int                       m_count_alloc ; // Current number of allocations
+  int                       m_max_alloc ;   // Maximum number of allocations
+  int                       m_ready_count ; // Number of ready or executing
+
+  //----------------------------------------
+
+  ~TaskQueue();
+  TaskQueue() = delete ;
+  TaskQueue( TaskQueue && ) = delete ;
+  TaskQueue( TaskQueue const & ) = delete ;
+  TaskQueue & operator = ( TaskQueue && ) = delete ;
+  TaskQueue & operator = ( TaskQueue const & ) = delete ;
+
+  TaskQueue
+    ( const memory_space & arg_space
+    , unsigned const arg_memory_pool_capacity
+    , unsigned const arg_memory_pool_superblock_capacity_log2
+    );
+
+  // Schedule a task
+  //   Precondition:
+  //     task is not executing
+  //     task->m_next is the dependence or zero
+  //   Postcondition:
+  //     task->m_next is linked list membership
+  KOKKOS_FUNCTION
+  void schedule( task_root_type * const );
+
+  // Complete a task
+  //   Precondition:
+  //     task is not executing
+  //     task->m_next == LockTag  =>  task is complete
+  //     task->m_next != LockTag  =>  task is respawn
+  //   Postcondition:
+  //     task->m_wait == LockTag  =>  task is complete
+  //     task->m_wait != LockTag  =>  task is waiting
+  KOKKOS_FUNCTION
+  void complete( task_root_type * );
+
+  KOKKOS_FUNCTION
+  static bool push_task( task_root_type * volatile * const
+                       , task_root_type * const );
+
+  KOKKOS_FUNCTION
+  static task_root_type * pop_task( task_root_type * volatile * const );
+
+  KOKKOS_FUNCTION static
+  void decrement( task_root_type * task );
+
+public:
+
+  // If and only if the execution space is a single thread
+  // then execute ready tasks.
+  KOKKOS_INLINE_FUNCTION
+  void iff_single_thread_recursive_execute()
+    {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      specialization::iff_single_thread_recursive_execute( this );
+#endif
+    }
+
+  void execute() { specialization::execute( this ); }
+
+  // Assign task pointer with reference counting of assigned tasks
+  template< typename LV , typename RV >
+  KOKKOS_FUNCTION static
+  void assign( TaskBase< execution_space,LV,void> ** const lhs
+             , TaskBase< execution_space,RV,void> *  const rhs )
+    {
+      using task_lhs = TaskBase< execution_space,LV,void> ;
+#if 0
+  {
+    printf( "assign( 0x%lx { 0x%lx %d %d } , 0x%lx { 0x%lx %d %d } )\n"
+          , uintptr_t( lhs ? *lhs : 0 )
+          , uintptr_t( lhs && *lhs ? (*lhs)->m_next : 0 )
+          , int( lhs && *lhs ? (*lhs)->m_task_type : 0 )
+          , int( lhs && *lhs ? (*lhs)->m_ref_count : 0 )
+          , uintptr_t(rhs)
+          , uintptr_t( rhs ? rhs->m_next : 0 )
+          , int( rhs ? rhs->m_task_type : 0 )
+          , int( rhs ? rhs->m_ref_count : 0 )
+          );
+    fflush( stdout );
+  }
+#endif
+
+      if ( *lhs ) decrement( *lhs );
+      if ( rhs ) { Kokkos::atomic_fetch_add( &(rhs->m_ref_count) , 1 ); }
+
+      // Force write of *lhs
+
+      *static_cast< task_lhs * volatile * >(lhs) = rhs ;
+
+      Kokkos::memory_fence();
+    }
+
+  KOKKOS_FUNCTION
+  size_t allocate_block_size( size_t n ); ///< Actual block size allocated
+
+  KOKKOS_FUNCTION
+  void * allocate( size_t n ); ///< Allocate from the memory pool
+
+  KOKKOS_FUNCTION
+  void deallocate( void * p , size_t n ); ///< Deallocate to the memory pool
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+class TaskBase< void , void , void > {
+public:
+  enum : int16_t   { TaskTeam = 0 , TaskSingle = 1 , Aggregate = 2 };
+  enum : uintptr_t { LockTag = ~uintptr_t(0) , EndTag = ~uintptr_t(1) };
+};
+
+/** \brief  Base class for task management, access, and execution.
+ *
+ *  Inheritance structure to allow static_cast from the task root type
+ *  and a task's FunctorType.
+ *
+ *    // Enable a Future to access result data
+ *    TaskBase< Space , ResultType , void >
+ *      : TaskBase< void , void , void >
+ *      { ... };
+ *
+ *    // Enable a functor to access the base class
+ *    TaskBase< Space , ResultType , FunctorType >
+ *      : TaskBase< Space , ResultType , void >
+ *      , FunctorType
+ *      { ... };
+ *
+ *
+ *  States of a task:
+ *
+ *    Constructing State, NOT IN a linked list
+ *      m_wait == 0
+ *      m_next == 0
+ *
+ *    Scheduling transition : Constructing -> Waiting
+ *      before:
+ *        m_wait == 0
+ *        m_next == this task's initial dependence, 0 if none
+ *      after:
+ *        m_wait == EndTag
+ *        m_next == EndTag
+ *
+ *    Waiting State, IN a linked list
+ *      m_apply != 0
+ *      m_queue != 0
+ *      m_ref_count > 0
+ *      m_wait == head of linked list of tasks waiting on this task
+ *      m_next == next of linked list of tasks
+ *
+ *    transition : Waiting -> Executing
+ *      before:
+ *        m_next == EndTag
+ *      after::
+ *        m_next == LockTag
+ *
+ *    Executing State, NOT IN a linked list
+ *      m_apply != 0
+ *      m_queue != 0
+ *      m_ref_count > 0
+ *      m_wait == head of linked list of tasks waiting on this task
+ *      m_next == LockTag
+ *
+ *    Respawn transition : Executing -> Executing-Respawn
+ *      before:
+ *        m_next == LockTag
+ *      after:
+ *        m_next == this task's updated dependence, 0 if none
+ *
+ *    Executing-Respawn State, NOT IN a linked list
+ *      m_apply != 0
+ *      m_queue != 0
+ *      m_ref_count > 0
+ *      m_wait == head of linked list of tasks waiting on this task
+ *      m_next == this task's updated dependence, 0 if none
+ *
+ *    transition : Executing -> Complete
+ *      before:
+ *        m_wait == head of linked list
+ *      after:
+ *        m_wait == LockTag
+ *
+ *    Complete State, NOT IN a linked list
+ *      m_wait == LockTag: cannot add dependence
+ *      m_next == LockTag: not a member of a wait queue
+ *
+ */
+template< typename ExecSpace >
+class TaskBase< ExecSpace , void , void >
+{
+public:
+
+  enum : int16_t   { TaskTeam   = TaskBase<void,void,void>::TaskTeam
+                   , TaskSingle = TaskBase<void,void,void>::TaskSingle
+                   , Aggregate  = TaskBase<void,void,void>::Aggregate };
+
+  enum : uintptr_t { LockTag = TaskBase<void,void,void>::LockTag
+                   , EndTag  = TaskBase<void,void,void>::EndTag };
+
+  using execution_space = ExecSpace ;
+  using queue_type      = TaskQueue< execution_space > ;
+
+  template< typename > friend class Kokkos::TaskPolicy ;
+
+  typedef void (* function_type) ( TaskBase * , void * );
+
+  // sizeof(TaskBase) == 48
+
+  function_type  m_apply ;     ///< Apply function pointer
+  queue_type   * m_queue ;     ///< Queue in which this task resides
+  TaskBase     * m_wait ;      ///< Linked list of tasks waiting on this
+  TaskBase     * m_next ;      ///< Waiting linked-list next
+  int32_t        m_ref_count ; ///< Reference count
+  int32_t        m_alloc_size ;///< Allocation size
+  int32_t        m_dep_count ; ///< Aggregate's number of dependences
+  int16_t        m_task_type ; ///< Type of task
+  int16_t        m_priority ;  ///< Priority of runnable task
+
+  TaskBase( TaskBase && ) = delete ;
+  TaskBase( const TaskBase & ) = delete ;
+  TaskBase & operator = ( TaskBase && ) = delete ;
+  TaskBase & operator = ( const TaskBase & ) = delete ;
+
+  KOKKOS_INLINE_FUNCTION ~TaskBase() = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  constexpr TaskBase() noexcept
+    : m_apply(0)
+    , m_queue(0)
+    , m_wait(0)
+    , m_next(0)
+    , m_ref_count(0)
+    , m_alloc_size(0)
+    , m_dep_count(0)
+    , m_task_type( TaskSingle )
+    , m_priority( 1 /* TaskRegularPriority */ )
+    {}
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  TaskBase ** aggregate_dependences()
+    { return reinterpret_cast<TaskBase**>( this + 1 ); }
+
+  using get_return_type = void ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_return_type get() const {}
+};
+
+template < typename ExecSpace , typename ResultType >
+class TaskBase< ExecSpace , ResultType , void >
+  : public TaskBase< ExecSpace , void , void >
+{
+private:
+
+  static_assert( sizeof(TaskBase<ExecSpace,void,void>) == 48 , "" );
+
+  TaskBase( TaskBase && ) = delete ;
+  TaskBase( const TaskBase & ) = delete ;
+  TaskBase & operator = ( TaskBase && ) = delete ;
+  TaskBase & operator = ( const TaskBase & ) = delete ;
+
+public:
+
+  ResultType   m_result ;
+
+  KOKKOS_INLINE_FUNCTION ~TaskBase() = default ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskBase()
+    : TaskBase< ExecSpace , void , void >()
+    , m_result()
+    {}
+
+  using get_return_type = ResultType const & ;
+
+  KOKKOS_INLINE_FUNCTION
+  get_return_type get() const { return m_result ; }
+};
+
+
+template< typename ExecSpace , typename ResultType , typename FunctorType >
+class TaskBase
+  : public TaskBase< ExecSpace , ResultType , void >
+  , public FunctorType
+{
+private:
+
+  TaskBase() = delete ;
+  TaskBase( TaskBase && ) = delete ;
+  TaskBase( const TaskBase & ) = delete ;
+  TaskBase & operator = ( TaskBase && ) = delete ;
+  TaskBase & operator = ( const TaskBase & ) = delete ;
+
+public:
+
+  using root_type    = TaskBase< ExecSpace , void , void > ;
+  using base_type    = TaskBase< ExecSpace , ResultType , void > ;
+  using member_type  = TaskExec< ExecSpace > ;
+  using functor_type = FunctorType ;
+  using result_type  = ResultType ;
+
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION static
+  void apply_functor
+    ( Type * const task
+    , typename std::enable_if
+        < std::is_same< typename Type::result_type , void >::value
+        , member_type * const 
+        >::type member
+    )
+    {
+      using fType = typename Type::functor_type ;
+      static_cast<fType*>(task)->operator()( *member );
+    }
+
+  template< typename Type >
+  KOKKOS_INLINE_FUNCTION static
+  void apply_functor
+    ( Type * const task
+    , typename std::enable_if
+        < ! std::is_same< typename Type::result_type , void >::value
+        , member_type * const 
+        >::type member
+    )
+    {
+      using fType = typename Type::functor_type ;
+      static_cast<fType*>(task)->operator()( *member , task->m_result );
+    }
+
+  KOKKOS_FUNCTION static
+  void apply( root_type * root , void * exec )
+    {
+      TaskBase    * const lock   = reinterpret_cast< TaskBase * >( root_type::LockTag );
+      TaskBase    * const task   = static_cast< TaskBase * >( root );
+      member_type * const member = reinterpret_cast< member_type * >( exec );
+
+      TaskBase::template apply_functor( task , member );
+
+      // Task may be serial or team.
+      // If team then must synchronize before querying task->m_next.
+      // If team then only one thread calls destructor.
+
+      member->team_barrier();
+
+      if ( 0 == member->team_rank() && lock == task->m_next ) {
+        // Did not respawn, destroy the functor to free memory
+        static_cast<functor_type*>(task)->~functor_type();
+        // Cannot destroy the task until its dependences
+        // have been processed.
+      }
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  TaskBase( FunctorType const & arg_functor )
+    : base_type()
+    , FunctorType( arg_functor )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  ~TaskBase() {}
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #ifndef KOKKOS_IMPL_TASKQUEUE_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_TaskQueue_impl.hpp b/lib/kokkos/core/src/impl/Kokkos_TaskQueue_impl.hpp
new file mode 100644
index 0000000000..70a880d4a2
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_TaskQueue_impl.hpp
@@ -0,0 +1,569 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+void TaskQueue< ExecSpace >::Destroy::destroy_shared_allocation()
+{
+  m_queue->~TaskQueue();
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+TaskQueue< ExecSpace >::TaskQueue
+  ( const TaskQueue< ExecSpace >::memory_space & arg_space
+  , unsigned const arg_memory_pool_capacity
+  , unsigned const arg_memory_pool_superblock_capacity_log2
+  )
+  : m_memory( arg_space
+            , arg_memory_pool_capacity
+            , arg_memory_pool_superblock_capacity_log2 )
+  , m_ready()
+  , m_accum_alloc(0)
+  , m_max_alloc(0)
+  , m_ready_count(0)
+{
+  for ( int i = 0 ; i < NumQueue ; ++i ) {
+    m_ready[i][0] = (task_root_type *) task_root_type::EndTag ;
+    m_ready[i][1] = (task_root_type *) task_root_type::EndTag ;
+  }
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+TaskQueue< ExecSpace >::~TaskQueue()
+{
+  // Verify that queues are empty and ready count is zero
+
+  for ( int i = 0 ; i < NumQueue ; ++i ) {
+    for ( int j = 0 ; j < 2 ; ++j ) {
+      if ( m_ready[i][j] != (task_root_type *) task_root_type::EndTag ) {
+        Kokkos::abort("TaskQueue::~TaskQueue ERROR: has ready tasks");
+      }
+    }
+  }
+
+  if ( 0 != m_ready_count ) {
+    Kokkos::abort("TaskQueue::~TaskQueue ERROR: has ready or executing tasks");
+  }
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+KOKKOS_FUNCTION
+void TaskQueue< ExecSpace >::decrement
+  ( TaskQueue< ExecSpace >::task_root_type * task )
+{
+  const int count = Kokkos::atomic_fetch_add(&(task->m_ref_count),-1);
+
+#if 0
+  if ( 1 == count ) {
+    printf( "decrement-destroy( 0x%lx { 0x%lx %d %d } )\n"
+          , uintptr_t( task )
+          , uintptr_t( task->m_next )
+          , int( task->m_task_type )
+          , int( task->m_ref_count )
+          );
+  }
+#endif
+
+  if ( ( 1 == count ) && 
+       ( task->m_next == (task_root_type *) task_root_type::LockTag ) ) {
+    // Reference count is zero and task is complete, deallocate.
+    task->m_queue->deallocate( task , task->m_alloc_size );
+  }   
+  else if ( count <= 1 ) { 
+    Kokkos::abort("TaskPolicy task has negative reference count or is incomplete" );
+  }   
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+KOKKOS_FUNCTION
+size_t TaskQueue< ExecSpace >::allocate_block_size( size_t n )
+{
+  return m_memory.allocate_block_size( n );
+}
+
+template< typename ExecSpace >
+KOKKOS_FUNCTION
+void * TaskQueue< ExecSpace >::allocate( size_t n )
+{
+  void * const p = m_memory.allocate(n);
+
+  if ( p ) {
+    Kokkos::atomic_increment( & m_accum_alloc );
+    Kokkos::atomic_increment( & m_count_alloc );
+
+    if ( m_max_alloc < m_count_alloc ) m_max_alloc = m_count_alloc ;
+  }
+
+  return p ;
+}
+
+template< typename ExecSpace >
+KOKKOS_FUNCTION
+void TaskQueue< ExecSpace >::deallocate( void * p , size_t n )
+{
+  m_memory.deallocate( p , n );
+  Kokkos::atomic_decrement( & m_count_alloc );
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+KOKKOS_FUNCTION
+bool TaskQueue< ExecSpace >::push_task
+  ( TaskQueue< ExecSpace >::task_root_type * volatile * const queue
+  , TaskQueue< ExecSpace >::task_root_type * const task
+  )
+{
+  // Push task into a concurrently pushed and popped queue.
+  // The queue is a linked list where 'task->m_next' form the links.
+  // Fail the push attempt if the queue is locked;
+  // otherwise retry until the push succeeds.
+
+#if 0
+  printf( "push_task( 0x%lx { 0x%lx } 0x%lx { 0x%lx 0x%lx %d %d %d } )\n"
+        , uintptr_t(queue)
+        , uintptr_t(*queue)
+        , uintptr_t(task)
+        , uintptr_t(task->m_wait)
+        , uintptr_t(task->m_next)
+        , task->m_task_type
+        , task->m_priority
+        , task->m_ref_count );
+#endif
+
+  task_root_type * const zero = (task_root_type *) 0 ;
+  task_root_type * const lock = (task_root_type *) task_root_type::LockTag ;
+
+  task_root_type * volatile * const next = & task->m_next ;
+
+  if ( zero != *next ) {
+    Kokkos::abort("TaskQueue::push_task ERROR: already a member of another queue" );
+  }
+
+  task_root_type * y = *queue ;
+
+  while ( lock != y ) {
+
+    *next = y ;
+
+    // Do not proceed until '*next' has been stored.
+    Kokkos::memory_fence();
+
+    task_root_type * const x = y ;
+
+    y = Kokkos::atomic_compare_exchange(queue,y,task);
+
+    if ( x == y ) return true ;
+  }
+
+  // Failed, replace 'task->m_next' value since 'task' remains
+  // not a member of a queue.
+
+  *next = zero ;
+
+  // Do not proceed until '*next' has been stored.
+  Kokkos::memory_fence();
+
+  return false ;
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+KOKKOS_FUNCTION
+typename TaskQueue< ExecSpace >::task_root_type *
+TaskQueue< ExecSpace >::pop_task
+  ( TaskQueue< ExecSpace >::task_root_type * volatile * const queue )
+{
+  // Pop task from a concurrently pushed and popped queue.
+  // The queue is a linked list where 'task->m_next' form the links.
+
+  task_root_type * const zero = (task_root_type *) 0 ;
+  task_root_type * const lock = (task_root_type *) task_root_type::LockTag ;
+  task_root_type * const end  = (task_root_type *) task_root_type::EndTag ;
+
+  // *queue is
+  //   end   => an empty queue
+  //   lock  => a locked queue
+  //   valid
+
+  // Retry until the lock is acquired or the queue is empty.
+
+  task_root_type * task = *queue ;
+
+  while ( end != task ) {
+
+    // The only possible values for the queue are
+    // (1) lock, (2) end, or (3) a valid task.
+    // Thus zero will never appear in the queue.
+    //
+    // If queue is locked then just read by guaranteeing
+    // the CAS will fail.
+
+    if ( lock == task ) task = 0 ;
+
+    task_root_type * const x = task ;
+
+    task = Kokkos::atomic_compare_exchange(queue,task,lock);
+
+    if ( x == task ) break ; // CAS succeeded and queue is locked
+  }
+
+  if ( end != task ) {
+
+    // This thread has locked the queue and removed 'task' from the queue.
+    // Extract the next entry of the queue from 'task->m_next'
+    // and mark 'task' as popped from a queue by setting
+    // 'task->m_next = lock'.
+
+    task_root_type * const next =
+      Kokkos::atomic_exchange( & task->m_next , lock );
+
+    // Place the next entry in the head of the queue,
+    // which also unlocks the queue.
+
+    task_root_type * const unlock =
+      Kokkos::atomic_exchange( queue , next );
+
+    if ( next == zero || next == lock || lock != unlock ) {
+      Kokkos::abort("TaskQueue::pop_task ERROR");
+    }
+  }
+
+#if 0
+  if ( end != task ) {
+    printf( "pop_task( 0x%lx 0x%lx { 0x%lx 0x%lx %d %d %d } )\n"
+          , uintptr_t(queue)
+          , uintptr_t(task)
+          , uintptr_t(task->m_wait)
+          , uintptr_t(task->m_next)
+          , int(task->m_task_type)
+          , int(task->m_priority)
+          , int(task->m_ref_count) );
+  }
+#endif
+
+  return task ;
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+KOKKOS_FUNCTION
+void TaskQueue< ExecSpace >::schedule
+  ( TaskQueue< ExecSpace >::task_root_type * const task )
+{
+  // Schedule a runnable or when_all task upon construction / spawn
+  // and upon completion of other tasks that 'task' is waiting on.
+
+  // Precondition on runnable task state:
+  //   task is either constructing or executing
+  //
+  //   Constructing state:
+  //     task->m_wait == 0
+  //     task->m_next == dependence
+  //   Executing-respawn state:
+  //     task->m_wait == head of linked list
+  //     task->m_next == dependence
+  //
+  //  Task state transition:
+  //     Constructing      ->  Waiting
+  //     Executing-respawn ->  Waiting
+  //
+  //  Postcondition on task state:
+  //     task->m_wait == head of linked list
+  //     task->m_next == member of linked list
+
+#if 0
+  printf( "schedule( 0x%lx { 0x%lx 0x%lx %d %d %d }\n"
+        , uintptr_t(task)
+        , uintptr_t(task->m_wait)
+        , uintptr_t(task->m_next)
+        , task->m_task_type
+        , task->m_priority
+        , task->m_ref_count );
+#endif
+
+  task_root_type * const zero = (task_root_type *) 0 ;
+  task_root_type * const lock = (task_root_type *) task_root_type::LockTag ;
+  task_root_type * const end  = (task_root_type *) task_root_type::EndTag ;
+
+  //----------------------------------------
+  {
+    // If Constructing then task->m_wait == 0
+    // Change to waiting by task->m_wait = EndTag
+
+    task_root_type * const init =
+      Kokkos::atomic_compare_exchange( & task->m_wait , zero , end );
+
+    // Precondition
+
+    if ( lock == init ) {
+      Kokkos::abort("TaskQueue::schedule ERROR: task is complete");
+    }
+
+    // if ( init == 0 ) Constructing       ->  Waiting
+    // else             Executing-Respawn  ->  Waiting
+  }
+  //----------------------------------------
+
+  if ( task_root_type::Aggregate != task->m_task_type ) {
+
+    // Scheduling a runnable task which may have a depencency 'dep'.
+    // Extract dependence, if any, from task->m_next.
+    // If 'dep' is not null then attempt to push 'task'
+    // into the wait queue of 'dep'.
+    // If the push succeeds then 'task' may be
+    // processed or executed by another thread at any time.
+    // If the push fails then 'dep' is complete and 'task'
+    // is ready to execute.
+
+    task_root_type * dep = Kokkos::atomic_exchange( & task->m_next , zero );
+
+    const bool is_ready = 
+      ( 0 == dep ) || ( ! push_task( & dep->m_wait , task ) );
+
+    // Reference count for dep was incremented when assigned
+    // to task->m_next so that if it completed prior to the
+    // above push_task dep would not be destroyed.
+    // dep reference count can now be decremented,
+    // which may deallocate the task.
+    TaskQueue::assign( & dep , (task_root_type *)0 );
+
+    if ( is_ready ) {
+
+      // No dependence or 'dep' is complete so push task into ready queue.
+      // Increment the ready count before pushing into ready queue
+      // to track number of ready + executing tasks.
+      // The ready count will be decremented when the task is complete.
+
+      Kokkos::atomic_increment( & m_ready_count );
+
+      task_root_type * volatile * const queue =
+        & m_ready[ task->m_priority ][ task->m_task_type ];
+
+      // A push_task fails if the ready queue is locked.
+      // A ready queue is only locked during a push or pop;
+      // i.e., it is never permanently locked.
+      // Retry push to ready queue until it succeeds.
+      // When the push succeeds then 'task' may be
+      // processed or executed by another thread at any time.
+
+      while ( ! push_task( queue , task ) );
+    }
+  }
+  //----------------------------------------
+  else {
+    // Scheduling a 'when_all' task with multiple dependences.
+    // This scheduling may be called when the 'when_all' is
+    // (1) created or
+    // (2) being removed from a completed task's wait list.
+
+    task_root_type ** const aggr = task->aggregate_dependences();
+
+    // Assume the 'when_all' is complete until a dependence is
+    // found that is not complete.
+
+    bool is_complete = true ;
+
+    for ( int i = task->m_dep_count ; 0 < i && is_complete ; ) {
+
+      --i ;
+
+      // Loop dependences looking for an incomplete task.
+      // Add this task to the incomplete task's wait queue.
+
+      // Remove a task 'x' from the dependence list.
+      // The reference count of 'x' was incremented when
+      // it was assigned into the dependence list.
+
+      task_root_type * x = Kokkos::atomic_exchange( aggr + i , zero );
+
+      if ( x ) {
+
+        // If x->m_wait is not locked then push succeeds
+        // and the aggregate is not complete.
+        // If the push succeeds then this when_all 'task' may be
+        // processed by another thread at any time.
+        // For example, 'x' may be completeed by another
+        // thread and then re-schedule this when_all 'task'.
+
+        is_complete = ! push_task( & x->m_wait , task );
+
+        // Decrement reference count which had been incremented
+        // when 'x' was added to the dependence list.
+
+        TaskQueue::assign( & x , zero );
+      }
+    }
+
+    if ( is_complete ) {
+      // The when_all 'task' was not added to a wait queue because
+      // all dependences were complete so this aggregate is complete.
+      // Complete the when_all 'task' to schedule other tasks
+      // that are waiting for the when_all 'task' to complete.
+
+      task->m_next = lock ;
+
+      complete( task );
+
+      // '*task' may have been deleted upon completion
+    }
+  }
+  //----------------------------------------
+  // Postcondition:
+  //   A runnable 'task' was pushed into a wait or ready queue.
+  //   An aggregate 'task' was either pushed to a wait queue
+  //   or completed.
+  // Concurrent execution may have already popped 'task'
+  // from a queue and processed it as appropriate.
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ExecSpace >
+KOKKOS_FUNCTION
+void TaskQueue< ExecSpace >::complete
+  ( TaskQueue< ExecSpace >::task_root_type * task )
+{
+  // Complete a runnable task that has finished executing
+  // or a when_all task when all of its dependeneces are complete.
+
+  task_root_type * const zero = (task_root_type *) 0 ;
+  task_root_type * const lock = (task_root_type *) task_root_type::LockTag ;
+  task_root_type * const end  = (task_root_type *) task_root_type::EndTag ;
+
+#if 0
+  printf( "complete( 0x%lx { 0x%lx 0x%lx %d %d %d }\n"
+        , uintptr_t(task)
+        , uintptr_t(task->m_wait)
+        , uintptr_t(task->m_next)
+        , task->m_task_type
+        , task->m_priority
+        , task->m_ref_count );
+  fflush( stdout );
+#endif
+
+  const bool runnable = task_root_type::Aggregate != task->m_task_type ;
+
+  //----------------------------------------
+
+  if ( runnable && lock != task->m_next ) {
+    // Is a runnable task has finished executing and requested respawn.
+    // Schedule the task for subsequent execution.
+
+    schedule( task );
+  }
+  //----------------------------------------
+  else {
+    // Is either an aggregate or a runnable task that executed
+    // and did not respawn.  Transition this task to complete.
+
+    // If 'task' is an aggregate then any of the runnable tasks that
+    // it depends upon may be attempting to complete this 'task'.
+    // Must only transition a task once to complete status.
+    // This is controled by atomically locking the wait queue.
+
+    // Stop other tasks from adding themselves to this task's wait queue
+    // by locking the head of this task's wait queue.
+
+    task_root_type * x = Kokkos::atomic_exchange( & task->m_wait , lock );
+
+    if ( x != (task_root_type *) lock ) {
+
+      // This thread has transitioned this 'task' to complete.
+      // 'task' is no longer in a queue and is not executing
+      // so decrement the reference count from 'task's creation.
+      // If no other references to this 'task' then it will be deleted.
+
+      TaskQueue::assign( & task , zero );
+
+      // This thread has exclusive access to the wait list so
+      // the concurrency-safe pop_task function is not needed.
+      // Schedule the tasks that have been waiting on the input 'task',
+      // which may have been deleted.
+
+      while ( x != end ) {
+
+        // Set x->m_next = zero  <=  no dependence
+
+        task_root_type * const next =
+          (task_root_type *) Kokkos::atomic_exchange( & x->m_next , zero );
+
+        schedule( x );
+
+        x = next ;
+      }
+    }
+  }
+
+  if ( runnable ) {
+    // A runnable task was popped from a ready queue and executed.
+    // If respawned into a ready queue then the ready count was incremented
+    // so decrement whether respawned or not.
+    Kokkos::atomic_decrement( & m_ready_count );
+  }
+}
+
+//----------------------------------------------------------------------------
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Timer.hpp b/lib/kokkos/core/src/impl/Kokkos_Timer.hpp
new file mode 100644
index 0000000000..1f14e42874
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Timer.hpp
@@ -0,0 +1,118 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_IMPLWALLTIME_HPP
+#define KOKKOS_IMPLWALLTIME_HPP
+
+#include <stddef.h>
+
+#ifdef _MSC_VER
+#undef KOKKOS_USE_LIBRT
+#include <gettimeofday.c>
+#else
+#ifdef KOKKOS_USE_LIBRT
+#include <ctime>
+#else
+#include <sys/time.h>
+#endif
+#endif
+
+namespace Kokkos {
+namespace Impl {
+
+/** \brief  Time since construction */
+
+class Timer {
+private:
+  #ifdef KOKKOS_USE_LIBRT
+	struct timespec m_old;
+  #else
+	struct timeval m_old ;
+  #endif
+  Timer( const Timer & );
+  Timer & operator = ( const Timer & );
+public:
+
+  inline
+  void reset() {
+    #ifdef KOKKOS_USE_LIBRT
+	  clock_gettime(CLOCK_REALTIME, &m_old);
+    #else
+	  gettimeofday( & m_old , ((struct timezone *) NULL ) );
+    #endif
+  }
+
+  inline
+  ~Timer() {}
+
+  inline
+  Timer() { reset(); }
+
+  inline
+  double seconds() const
+  {
+    #ifdef KOKKOS_USE_LIBRT
+      struct timespec m_new;
+      clock_gettime(CLOCK_REALTIME, &m_new);
+
+      return ( (double) ( m_new.tv_sec  - m_old.tv_sec ) ) +
+             ( (double) ( m_new.tv_nsec - m_old.tv_nsec ) * 1.0e-9 );
+    #else
+      struct timeval m_new ;
+
+      ::gettimeofday( & m_new , ((struct timezone *) NULL ) );
+
+      return ( (double) ( m_new.tv_sec  - m_old.tv_sec ) ) +
+             ( (double) ( m_new.tv_usec - m_old.tv_usec ) * 1.0e-6 );
+    #endif
+  }
+};
+
+} // namespace Impl
+
+  using Kokkos::Impl::Timer ;
+
+} // namespace Kokkos
+
+#endif /* #ifndef KOKKOS_IMPLWALLTIME_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Traits.hpp b/lib/kokkos/core/src/impl/Kokkos_Traits.hpp
new file mode 100644
index 0000000000..278f715bc9
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Traits.hpp
@@ -0,0 +1,501 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOSTRAITS_HPP
+#define KOKKOSTRAITS_HPP
+
+#include <stddef.h>
+#include <stdint.h>
+#include <Kokkos_Macros.hpp>
+#include <string>
+#include <type_traits>
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+// Help with C++11 variadic argument packs
+
+template< unsigned I , typename ... Pack >
+struct get_type { typedef void type ; };
+
+template< typename T , typename ... Pack >
+struct get_type< 0 , T , Pack ... >
+{ typedef T type ; };
+
+template< unsigned I , typename T , typename ... Pack >
+struct get_type< I , T , Pack ... >
+{ typedef typename get_type< I - 1 , Pack ... >::type type ; };
+
+
+template< typename T , typename ... Pack >
+struct has_type { enum { value = false }; };
+
+template< typename T , typename S , typename ... Pack >
+struct has_type<T,S,Pack...>
+{
+private:
+
+  enum { self_value = std::is_same<T,S>::value };
+
+  typedef has_type<T,Pack...> next ;
+
+  static_assert( ! ( self_value && next::value )
+               , "Error: more than one member of the argument pack matches the type" );
+
+public:
+
+  enum { value = self_value || next::value };
+
+};
+
+
+template< typename DefaultType
+        , template< typename > class Condition
+        , typename ... Pack >
+struct has_condition 
+{
+  enum { value = false };
+  typedef DefaultType type ;
+};
+
+template< typename DefaultType
+        , template< typename > class Condition
+        , typename S
+        , typename ... Pack >
+struct has_condition< DefaultType , Condition , S , Pack... >
+{
+private:
+
+  enum { self_value = Condition<S>::value };
+
+  typedef has_condition< DefaultType , Condition , Pack... > next ;
+
+  static_assert( ! ( self_value && next::value )
+               , "Error: more than one member of the argument pack satisfies condition" );
+
+public:
+
+  enum { value = self_value || next::value };
+
+  typedef typename
+    std::conditional< self_value , S , typename next::type >::type
+      type ;
+};
+
+
+template< class ... Args >
+struct are_integral { enum { value = true }; };
+
+template< typename T , class ... Args >
+struct are_integral<T,Args...> {
+  enum { value =
+    // Accept std::is_integral OR std::is_enum as an integral value
+    // since a simple enum value is automically convertable to an
+    // integral value.
+    ( std::is_integral<T>::value || std::is_enum<T>::value )
+    &&
+    are_integral<Args...>::value };
+};
+
+//----------------------------------------------------------------------------
+/* C++11 conformal compile-time type traits utilities.
+ * Prefer to use C++11 when portably available.
+ */
+//----------------------------------------------------------------------------
+// C++11 Helpers:
+
+template < class T , T v >
+struct integral_constant
+{
+  // Declaration of 'static const' causes an unresolved linker symbol in debug
+  // static const T value = v ;
+  enum { value = T(v) };
+  typedef T value_type;
+  typedef integral_constant<T,v> type;
+  KOKKOS_INLINE_FUNCTION operator T() { return v ; }
+};
+
+typedef integral_constant<bool,false> false_type ;
+typedef integral_constant<bool,true>  true_type ;
+
+//----------------------------------------------------------------------------
+// C++11 Type relationships:
+
+template< class X , class Y > struct is_same : public false_type {};
+template< class X >           struct is_same<X,X> : public true_type {};
+
+//----------------------------------------------------------------------------
+// C++11 Type properties:
+
+template <typename T> struct is_const : public false_type {};
+template <typename T> struct is_const<const T> : public true_type {};
+template <typename T> struct is_const<const T & > : public true_type {};
+
+template <typename T> struct is_array : public false_type {};
+template <typename T> struct is_array< T[] > : public true_type {};
+template <typename T, unsigned N > struct is_array< T[N] > : public true_type {};
+
+//----------------------------------------------------------------------------
+// C++11 Type transformations:
+
+template <typename T> struct remove_const { typedef T type; };
+template <typename T> struct remove_const<const T> { typedef T type; };
+template <typename T> struct remove_const<const T & > { typedef T & type; };
+
+template <typename T> struct add_const { typedef const T type; };
+template <typename T> struct add_const<T & > { typedef const T & type; };
+template <typename T> struct add_const<const T> { typedef const T type; };
+template <typename T> struct add_const<const T & > { typedef const T & type; };
+
+template <typename T> struct remove_reference { typedef T type ; };
+template <typename T> struct remove_reference< T & > { typedef T type ; };
+template <typename T> struct remove_reference< const T & > { typedef const T type ; };
+
+template <typename T> struct remove_extent { typedef T type ; };
+template <typename T> struct remove_extent<T[]> { typedef T type ; };
+template <typename T, unsigned N > struct remove_extent<T[N]> { typedef T type ; };
+
+//----------------------------------------------------------------------------
+// C++11 Other type generators:
+
+template< bool , class T , class F >
+struct condition { typedef F type ; };
+
+template< class T , class F >
+struct condition<true,T,F> { typedef T type ; };
+
+template< bool , class = void >
+struct enable_if ;
+
+template< class T >
+struct enable_if< true , T > { typedef T type ; };
+
+//----------------------------------------------------------------------------
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+// Other traits
+
+namespace Kokkos {
+namespace Impl {
+
+//----------------------------------------------------------------------------
+
+template< class , class T = void >
+struct enable_if_type { typedef T type ; };
+
+//----------------------------------------------------------------------------
+
+template< bool B >
+struct bool_ : public integral_constant<bool,B> {};
+
+template< unsigned I >
+struct unsigned_ : public integral_constant<unsigned,I> {};
+
+template< int I >
+struct int_ : public integral_constant<int,I> {};
+
+typedef bool_<true> true_;
+typedef bool_<false> false_;
+//----------------------------------------------------------------------------
+// if_
+
+template < bool Cond , typename TrueType , typename FalseType>
+struct if_c
+{
+  enum { value = Cond };
+
+  typedef FalseType type;
+
+
+  typedef typename remove_const<
+          typename remove_reference<type>::type >::type value_type ;
+
+  typedef typename add_const<value_type>::type const_value_type ;
+
+  static KOKKOS_INLINE_FUNCTION
+  const_value_type & select( const_value_type & v ) { return v ; }
+
+  static KOKKOS_INLINE_FUNCTION
+  value_type & select( value_type & v ) { return v ; }
+
+  template< class T >
+  static KOKKOS_INLINE_FUNCTION
+  value_type & select( const T & ) { value_type * ptr(0); return *ptr ; }
+
+
+  template< class T >
+  static KOKKOS_INLINE_FUNCTION
+  const_value_type & select( const T & , const_value_type & v ) { return v ; }
+
+  template< class T >
+  static KOKKOS_INLINE_FUNCTION
+  value_type & select( const T & , value_type & v ) { return v ; }
+};
+
+template <typename TrueType, typename FalseType>
+struct if_c< true , TrueType , FalseType >
+{
+  enum { value = true };
+
+  typedef TrueType type;
+
+
+  typedef typename remove_const<
+          typename remove_reference<type>::type >::type value_type ;
+
+  typedef typename add_const<value_type>::type const_value_type ;
+
+  static KOKKOS_INLINE_FUNCTION
+  const_value_type & select( const_value_type & v ) { return v ; }
+
+  static KOKKOS_INLINE_FUNCTION
+  value_type & select( value_type & v ) { return v ; }
+
+  template< class T >
+  static KOKKOS_INLINE_FUNCTION
+  value_type & select( const T & ) { value_type * ptr(0); return *ptr ; }
+
+
+  template< class F >
+  static KOKKOS_INLINE_FUNCTION
+  const_value_type & select( const_value_type & v , const F & ) { return v ; }
+
+  template< class F >
+  static KOKKOS_INLINE_FUNCTION
+  value_type & select( value_type & v , const F & ) { return v ; }
+};
+
+template< typename TrueType >
+struct if_c< false , TrueType , void >
+{
+  enum { value = false };
+
+  typedef void type ;
+  typedef void value_type ;
+};
+
+template< typename FalseType >
+struct if_c< true , void , FalseType >
+{
+  enum { value = true };
+
+  typedef void type ;
+  typedef void value_type ;
+};
+
+template <typename Cond, typename TrueType, typename FalseType>
+struct if_ : public if_c<Cond::value, TrueType, FalseType> {};
+
+//----------------------------------------------------------------------------
+
+// Allows aliased types:
+template< typename T >
+struct is_integral : public integral_constant< bool ,
+  (
+    std::is_same< T ,          char >::value ||
+    std::is_same< T , unsigned char >::value ||
+    std::is_same< T ,          short int >::value ||
+    std::is_same< T , unsigned short int >::value ||
+    std::is_same< T ,          int >::value ||
+    std::is_same< T , unsigned int >::value ||
+    std::is_same< T ,          long int >::value ||
+    std::is_same< T , unsigned long int >::value ||
+    std::is_same< T ,          long long int >::value ||
+    std::is_same< T , unsigned long long int >::value ||
+
+    std::is_same< T , int8_t   >::value ||
+    std::is_same< T , int16_t  >::value ||
+    std::is_same< T , int32_t  >::value ||
+    std::is_same< T , int64_t  >::value ||
+    std::is_same< T , uint8_t  >::value ||
+    std::is_same< T , uint16_t >::value ||
+    std::is_same< T , uint32_t >::value ||
+    std::is_same< T , uint64_t >::value 
+  )>
+{};
+//----------------------------------------------------------------------------
+
+template<typename T>
+struct is_label : public false_type {};
+
+template<>
+struct is_label<const char*> : public true_type {};
+
+template<>
+struct is_label<char*> : public true_type {};
+
+
+template<int N>
+struct is_label<const char[N]> : public true_type {};
+
+template<int N>
+struct is_label<char[N]> : public true_type {};
+
+
+template<>
+struct is_label<const std::string> : public true_type {};
+
+template<>
+struct is_label<std::string> : public true_type {};
+
+// These 'constexpr'functions can be used as
+// both regular functions and meta-function.
+
+/**\brief  There exists integral 'k' such that N = 2^k */
+KOKKOS_INLINE_FUNCTION
+constexpr bool is_integral_power_of_two( const size_t N )
+{ return ( 0 < N ) && ( 0 == ( N & ( N - 1 ) ) ); }
+
+/**\brief  Return integral 'k' such that N = 2^k, assuming valid.  */
+KOKKOS_INLINE_FUNCTION
+constexpr unsigned integral_power_of_two_assume_valid( const size_t N )
+{ return N == 1 ? 0 : 1 + integral_power_of_two_assume_valid( N >> 1 ); }
+
+/**\brief  Return integral 'k' such that N = 2^k, if exists.
+ *         If does not exist return ~0u.
+ */
+KOKKOS_INLINE_FUNCTION
+constexpr unsigned integral_power_of_two( const size_t N )
+{ return is_integral_power_of_two(N) ? integral_power_of_two_assume_valid(N) : ~0u ; }
+
+//----------------------------------------------------------------------------
+
+template < size_t N >
+struct is_power_of_two
+{
+  enum type { value = (N > 0) && !(N & (N-1)) };
+};
+
+template < size_t N , bool OK = is_power_of_two<N>::value >
+struct power_of_two ;
+
+template < size_t N >
+struct power_of_two<N,true>
+{
+  enum type { value = 1+ power_of_two<(N>>1),true>::value };
+};
+
+template <>
+struct power_of_two<2,true>
+{
+  enum type { value = 1 };
+};
+
+template <>
+struct power_of_two<1,true>
+{
+  enum type { value = 0 };
+};
+
+/** \brief  If power of two then return power,
+ *          otherwise return ~0u.
+ */
+static KOKKOS_FORCEINLINE_FUNCTION
+unsigned power_of_two_if_valid( const unsigned N )
+{
+  unsigned p = ~0u ;
+  if ( N && ! ( N & ( N - 1 ) ) ) {
+#if defined( __CUDA_ARCH__ ) && defined( KOKKOS_HAVE_CUDA )
+    p = __ffs(N) - 1 ;
+#elif defined( __GNUC__ ) || defined( __GNUG__ )
+    p = __builtin_ffs(N) - 1 ;
+#elif defined( __INTEL_COMPILER )
+    p = _bit_scan_forward(N);
+#else
+    p = 0 ;
+    for ( unsigned j = 1 ; ! ( N & j ) ; j <<= 1 ) { ++p ; }
+#endif
+  }
+  return p ;
+}
+
+//----------------------------------------------------------------------------
+
+template< typename T , T v , bool NonZero = ( v != T(0) ) >
+struct integral_nonzero_constant
+{
+  // Declaration of 'static const' causes an unresolved linker symbol in debug
+  // static const T value = v ;
+  enum { value = T(v) };
+  typedef T value_type ;
+  typedef integral_nonzero_constant<T,v> type ;
+  KOKKOS_INLINE_FUNCTION integral_nonzero_constant( const T & ) {}
+};
+
+template< typename T , T zero >
+struct integral_nonzero_constant<T,zero,false>
+{
+  const T value ;
+  typedef T value_type ;
+  typedef integral_nonzero_constant<T,0> type ;
+  KOKKOS_INLINE_FUNCTION integral_nonzero_constant( const T & v ) : value(v) {}
+};
+
+//----------------------------------------------------------------------------
+
+template < class C > struct is_integral_constant : public false_
+{
+  typedef void integral_type ;
+  enum { integral_value = 0 };
+};
+
+template < typename T , T v >
+struct is_integral_constant< integral_constant<T,v> > : public true_
+{
+  typedef T integral_type ;
+  enum { integral_value = v };
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOSTRAITS_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_ViewDefault.hpp b/lib/kokkos/core/src/impl/Kokkos_ViewDefault.hpp
new file mode 100644
index 0000000000..94c8e13c1d
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_ViewDefault.hpp
@@ -0,0 +1,886 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_VIEWDEFAULT_HPP
+#define KOKKOS_VIEWDEFAULT_HPP
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template<>
+struct ViewAssignment< ViewDefault , ViewDefault , void >
+{
+  typedef ViewDefault Specialize ;
+
+  //------------------------------------
+  /** \brief  Compatible value and shape and LayoutLeft/Right to LayoutStride*/
+
+  template< class DT , class DL , class DD , class DM ,
+            class ST , class SL , class SD , class SM >
+  KOKKOS_INLINE_FUNCTION
+  ViewAssignment(       View<DT,DL,DD,DM,Specialize> & dst ,
+                  const View<ST,SL,SD,SM,Specialize> & src ,
+                  const typename enable_if<(
+                    ViewAssignable< ViewTraits<DT,DL,DD,DM> ,
+                                    ViewTraits<ST,SL,SD,SM> >::value
+                    ||
+                    ( ViewAssignable< ViewTraits<DT,DL,DD,DM> ,
+                                      ViewTraits<ST,SL,SD,SM> >::assignable_value
+                      &&
+                      ShapeCompatible< typename ViewTraits<DT,DL,DD,DM>::shape_type ,
+                                       typename ViewTraits<ST,SL,SD,SM>::shape_type >::value
+                      &&
+                      is_same< typename ViewTraits<DT,DL,DD,DM>::array_layout,LayoutStride>::value
+                      && (is_same< typename ViewTraits<ST,SL,SD,SM>::array_layout,LayoutLeft>::value ||
+                          is_same< typename ViewTraits<ST,SL,SD,SM>::array_layout,LayoutRight>::value))
+                  )>::type * = 0 )
+  {
+    dst.m_offset_map.assign( src.m_offset_map );
+
+    dst.m_management = src.m_management ;
+
+    dst.m_ptr_on_device = ViewDataManagement< ViewTraits<DT,DL,DD,DM> >::create_handle( src.m_ptr_on_device, src.m_tracker );
+
+    if( dst.is_managed )
+      dst.m_tracker = src.m_tracker ;
+    else {
+      dst.m_tracker = AllocationTracker();
+      dst.m_management.set_unmanaged();
+    }
+  }
+
+
+  /** \brief  Assign 1D Strided View to LayoutLeft or LayoutRight if stride[0]==1 */
+
+  template< class DT , class DL , class DD , class DM ,
+            class ST , class SD , class SM >
+  KOKKOS_INLINE_FUNCTION
+  ViewAssignment(       View<DT,DL,DD,DM,Specialize> & dst ,
+                  const View<ST,LayoutStride,SD,SM,Specialize> & src ,
+                  const typename enable_if<(
+                    (
+                      ViewAssignable< ViewTraits<DT,DL,DD,DM> ,
+                                    ViewTraits<ST,LayoutStride,SD,SM> >::value
+                      ||
+                      ( ViewAssignable< ViewTraits<DT,DL,DD,DM> ,
+                                      ViewTraits<ST,LayoutStride,SD,SM> >::assignable_value
+                        &&
+                        ShapeCompatible< typename ViewTraits<DT,DL,DD,DM>::shape_type ,
+                                       typename ViewTraits<ST,LayoutStride,SD,SM>::shape_type >::value
+                      )
+                     )
+                     &&
+                      (View<DT,DL,DD,DM,Specialize>::rank==1)
+                     && (is_same< typename ViewTraits<DT,DL,DD,DM>::array_layout,LayoutLeft>::value ||
+                          is_same< typename ViewTraits<DT,DL,DD,DM>::array_layout,LayoutRight>::value)
+                  )>::type * = 0 )
+  {
+    size_t strides[8];
+    src.stride(strides);
+    if(strides[0]!=1) {
+      Kokkos::abort("Trying to assign strided 1D View to LayoutRight or LayoutLeft which is not stride-1");
+    }
+    dst.m_offset_map.assign( src.dimension_0(), 0, 0, 0, 0, 0, 0, 0, 0 );
+
+    dst.m_management = src.m_management ;
+
+    dst.m_ptr_on_device = ViewDataManagement< ViewTraits<DT,DL,DD,DM> >::create_handle( src.m_ptr_on_device, src.m_tracker );
+
+    if( dst.is_managed )
+      dst.m_tracker = src.m_tracker ;
+    else {
+      dst.m_tracker = AllocationTracker();
+      dst.m_management.set_unmanaged();
+    }
+  }
+
+  //------------------------------------
+  /** \brief  Deep copy data from compatible value type, layout, rank, and specialization.
+   *          Check the dimensions and allocation lengths at runtime.
+   */
+  template< class DT , class DL , class DD , class DM ,
+            class ST , class SL , class SD , class SM >
+  inline static
+  void deep_copy( const View<DT,DL,DD,DM,Specialize> & dst ,
+                  const View<ST,SL,SD,SM,Specialize> & src ,
+                  const typename Impl::enable_if<(
+                    Impl::is_same< typename ViewTraits<DT,DL,DD,DM>::value_type ,
+                                   typename ViewTraits<ST,SL,SD,SM>::non_const_value_type >::value
+                    &&
+                    Impl::is_same< typename ViewTraits<DT,DL,DD,DM>::array_layout ,
+                                   typename ViewTraits<ST,SL,SD,SM>::array_layout >::value
+                    &&
+                    ( unsigned(ViewTraits<DT,DL,DD,DM>::rank) == unsigned(ViewTraits<ST,SL,SD,SM>::rank) )
+                  )>::type * = 0 )
+  {
+    typedef typename ViewTraits<DT,DL,DD,DM>::memory_space dst_memory_space ;
+    typedef typename ViewTraits<ST,SL,SD,SM>::memory_space src_memory_space ;
+
+    if ( dst.ptr_on_device() != src.ptr_on_device() ) {
+
+      Impl::assert_shapes_are_equal( dst.m_offset_map , src.m_offset_map );
+
+      const size_t nbytes = dst.m_offset_map.scalar_size * dst.m_offset_map.capacity();
+
+      DeepCopy< dst_memory_space , src_memory_space >( dst.ptr_on_device() , src.ptr_on_device() , nbytes );
+    }
+  }
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class ExecSpace , class DT , class DL, class DD, class DM, class DS >
+struct ViewDefaultConstruct< ExecSpace , Kokkos::View<DT,DL,DD,DM,DS> , true >
+{
+  Kokkos::View<DT,DL,DD,DM,DS> * const m_ptr ;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator()( const typename ExecSpace::size_type& i ) const
+    { new(m_ptr+i) Kokkos::View<DT,DL,DD,DM,DS>(); }
+
+  ViewDefaultConstruct( Kokkos::View<DT,DL,DD,DM,DS> * pointer , size_t capacity )
+    : m_ptr( pointer )
+    {
+      Kokkos::RangePolicy< ExecSpace > range( 0 , capacity );
+      parallel_for( range , *this );
+      ExecSpace::fence();
+    }
+};
+
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type , class SubArg2_type , class SubArg3_type
+        , class SubArg4_type , class SubArg5_type , class SubArg6_type , class SubArg7_type
+        >
+struct ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                  , SubArg0_type , SubArg1_type , SubArg2_type , SubArg3_type
+                  , SubArg4_type , SubArg5_type , SubArg6_type , SubArg7_type >
+{
+private:
+
+  typedef View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >  SrcViewType ;
+
+  enum { V0 = Impl::is_same< SubArg0_type , void >::value ? 1 : 0 };
+  enum { V1 = Impl::is_same< SubArg1_type , void >::value ? 1 : 0 };
+  enum { V2 = Impl::is_same< SubArg2_type , void >::value ? 1 : 0 };
+  enum { V3 = Impl::is_same< SubArg3_type , void >::value ? 1 : 0 };
+  enum { V4 = Impl::is_same< SubArg4_type , void >::value ? 1 : 0 };
+  enum { V5 = Impl::is_same< SubArg5_type , void >::value ? 1 : 0 };
+  enum { V6 = Impl::is_same< SubArg6_type , void >::value ? 1 : 0 };
+  enum { V7 = Impl::is_same< SubArg7_type , void >::value ? 1 : 0 };
+
+  // The source view rank must be equal to the input argument rank
+  // Once a void argument is encountered all subsequent arguments must be void.
+  enum { InputRank =
+    Impl::StaticAssert<( SrcViewType::rank ==
+                         ( V0 ? 0 : (
+                           V1 ? 1 : (
+                           V2 ? 2 : (
+                           V3 ? 3 : (
+                           V4 ? 4 : (
+                           V5 ? 5 : (
+                           V6 ? 6 : (
+                           V7 ? 7 : 8 ))))))) ))
+                       &&
+                       ( SrcViewType::rank ==
+                         ( 8 - ( V0 + V1 + V2 + V3 + V4 + V5 + V6 + V7 ) ) )
+    >::value ? SrcViewType::rank : 0 };
+
+  enum { R0 = Impl::ViewOffsetRange< SubArg0_type >::is_range ? 1 : 0 };
+  enum { R1 = Impl::ViewOffsetRange< SubArg1_type >::is_range ? 1 : 0 };
+  enum { R2 = Impl::ViewOffsetRange< SubArg2_type >::is_range ? 1 : 0 };
+  enum { R3 = Impl::ViewOffsetRange< SubArg3_type >::is_range ? 1 : 0 };
+  enum { R4 = Impl::ViewOffsetRange< SubArg4_type >::is_range ? 1 : 0 };
+  enum { R5 = Impl::ViewOffsetRange< SubArg5_type >::is_range ? 1 : 0 };
+  enum { R6 = Impl::ViewOffsetRange< SubArg6_type >::is_range ? 1 : 0 };
+  enum { R7 = Impl::ViewOffsetRange< SubArg7_type >::is_range ? 1 : 0 };
+
+  enum { OutputRank = unsigned(R0) + unsigned(R1) + unsigned(R2) + unsigned(R3)
+                    + unsigned(R4) + unsigned(R5) + unsigned(R6) + unsigned(R7) };
+
+  // Reverse
+  enum { R0_rev = 0 == InputRank ? 0u : (
+                  1 == InputRank ? unsigned(R0) : (
+                  2 == InputRank ? unsigned(R1) : (
+                  3 == InputRank ? unsigned(R2) : (
+                  4 == InputRank ? unsigned(R3) : (
+                  5 == InputRank ? unsigned(R4) : (
+                  6 == InputRank ? unsigned(R5) : (
+                  7 == InputRank ? unsigned(R6) : unsigned(R7) ))))))) };
+
+  typedef typename SrcViewType::array_layout  SrcViewLayout ;
+
+  // Choose array layout, attempting to preserve original layout if at all possible.
+  typedef typename Impl::if_c<
+     ( // Same Layout IF
+       // OutputRank 0
+       ( OutputRank == 0 )
+       ||
+       // OutputRank 1 or 2, InputLayout Left, Interval 0
+       // because single stride one or second index has a stride.
+       ( OutputRank <= 2 && R0 && Impl::is_same<SrcViewLayout,LayoutLeft>::value )
+       ||
+       // OutputRank 1 or 2, InputLayout Right, Interval [InputRank-1]
+       // because single stride one or second index has a stride.
+       ( OutputRank <= 2 && R0_rev && Impl::is_same<SrcViewLayout,LayoutRight>::value )
+     ), SrcViewLayout , Kokkos::LayoutStride >::type OutputViewLayout ;
+
+  // Choose data type as a purely dynamic rank array to accomodate a runtime range.
+  typedef typename Impl::if_c< OutputRank == 0 , typename SrcViewType::value_type ,
+          typename Impl::if_c< OutputRank == 1 , typename SrcViewType::value_type *,
+          typename Impl::if_c< OutputRank == 2 , typename SrcViewType::value_type **,
+          typename Impl::if_c< OutputRank == 3 , typename SrcViewType::value_type ***,
+          typename Impl::if_c< OutputRank == 4 , typename SrcViewType::value_type ****,
+          typename Impl::if_c< OutputRank == 5 , typename SrcViewType::value_type *****,
+          typename Impl::if_c< OutputRank == 6 , typename SrcViewType::value_type ******,
+          typename Impl::if_c< OutputRank == 7 , typename SrcViewType::value_type *******,
+                                                 typename SrcViewType::value_type ********
+  >::type >::type >::type >::type >::type >::type >::type >::type  OutputData ;
+
+  // Choose space.
+  // If the source view's template arg1 or arg2 is a space then use it,
+  // otherwise use the source view's execution space.
+
+  typedef typename Impl::if_c< Impl::is_space< SrcArg1Type >::value , SrcArg1Type ,
+          typename Impl::if_c< Impl::is_space< SrcArg2Type >::value , SrcArg2Type , typename SrcViewType::device_type
+  >::type >::type OutputSpace ;
+
+public:
+
+  // If keeping the layout then match non-data type arguments
+  // else keep execution space and memory traits.
+  typedef typename
+    Impl::if_c< Impl::is_same< SrcViewLayout , OutputViewLayout >::value
+              , Kokkos::View< OutputData , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+              , Kokkos::View< OutputData , OutputViewLayout , OutputSpace
+                            , typename SrcViewType::memory_traits
+                            , Impl::ViewDefault >
+              >::type  type ;
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+// Construct subview of a Rank 8 view
+template< class DstDataType , class DstArg1Type , class DstArg2Type , class DstArg3Type >
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type , class SubArg2_type , class SubArg3_type
+        , class SubArg4_type , class SubArg5_type , class SubArg6_type , class SubArg7_type
+        >
+KOKKOS_INLINE_FUNCTION
+View< DstDataType , DstArg1Type , DstArg2Type , DstArg3Type , Impl::ViewDefault >::
+View( const View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault > & src
+    , const SubArg0_type & arg0
+    , const SubArg1_type & arg1
+    , const SubArg2_type & arg2
+    , const SubArg3_type & arg3
+    , const SubArg4_type & arg4
+    , const SubArg5_type & arg5
+    , const SubArg6_type & arg6
+    , const SubArg7_type & arg7
+    )
+  : m_ptr_on_device( (typename traits::value_type*) NULL)
+  , m_offset_map()
+  , m_management()
+  , m_tracker()
+{
+  // This constructor can only be used to construct a subview
+  // from the source view.  This type must match the subview type
+  // deduced from the source view and subview arguments.
+
+  typedef Impl::ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                           , SubArg0_type , SubArg1_type , SubArg2_type , SubArg3_type
+                           , SubArg4_type , SubArg5_type , SubArg6_type , SubArg7_type >
+    ViewSubviewDeduction ;
+
+  enum { is_a_valid_subview_constructor =
+    Impl::StaticAssert<
+      Impl::is_same< View , typename ViewSubviewDeduction::type >::value
+    >::value
+  };
+
+  if ( is_a_valid_subview_constructor ) {
+
+    typedef Impl::ViewOffsetRange< SubArg0_type > R0 ;
+    typedef Impl::ViewOffsetRange< SubArg1_type > R1 ;
+    typedef Impl::ViewOffsetRange< SubArg2_type > R2 ;
+    typedef Impl::ViewOffsetRange< SubArg3_type > R3 ;
+    typedef Impl::ViewOffsetRange< SubArg4_type > R4 ;
+    typedef Impl::ViewOffsetRange< SubArg5_type > R5 ;
+    typedef Impl::ViewOffsetRange< SubArg6_type > R6 ;
+    typedef Impl::ViewOffsetRange< SubArg7_type > R7 ;
+
+    // 'assign_subview' returns whether the subview offset_map
+    // introduces noncontiguity in the view.
+    const bool introduce_noncontiguity =
+      m_offset_map.assign_subview( src.m_offset_map
+                                 , R0::dimension( src.m_offset_map.N0 , arg0 )
+                                 , R1::dimension( src.m_offset_map.N1 , arg1 )
+                                 , R2::dimension( src.m_offset_map.N2 , arg2 )
+                                 , R3::dimension( src.m_offset_map.N3 , arg3 )
+                                 , R4::dimension( src.m_offset_map.N4 , arg4 )
+                                 , R5::dimension( src.m_offset_map.N5 , arg5 )
+                                 , R6::dimension( src.m_offset_map.N6 , arg6 )
+                                 , R7::dimension( src.m_offset_map.N7 , arg7 )
+                                 );
+
+    if ( m_offset_map.capacity() ) {
+
+      m_management = src.m_management ;
+
+      if ( introduce_noncontiguity ) m_management.set_noncontiguous();
+
+      m_ptr_on_device = src.m_ptr_on_device +
+                        src.m_offset_map( R0::begin( arg0 )
+                                        , R1::begin( arg1 )
+                                        , R2::begin( arg2 )
+                                        , R3::begin( arg3 )
+                                        , R4::begin( arg4 )
+                                        , R5::begin( arg5 )
+                                        , R6::begin( arg6 )
+                                        , R7::begin( arg7 ) );
+      m_tracker = src.m_tracker ;
+    }
+  }
+}
+
+// Construct subview of a Rank 7 view
+template< class DstDataType , class DstArg1Type , class DstArg2Type , class DstArg3Type >
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type , class SubArg2_type , class SubArg3_type
+        , class SubArg4_type , class SubArg5_type , class SubArg6_type
+        >
+KOKKOS_INLINE_FUNCTION
+View< DstDataType , DstArg1Type , DstArg2Type , DstArg3Type , Impl::ViewDefault >::
+View( const View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault > & src
+    , const SubArg0_type & arg0
+    , const SubArg1_type & arg1
+    , const SubArg2_type & arg2
+    , const SubArg3_type & arg3
+    , const SubArg4_type & arg4
+    , const SubArg5_type & arg5
+    , const SubArg6_type & arg6
+    )
+  : m_ptr_on_device( (typename traits::value_type*) NULL)
+  , m_offset_map()
+  , m_management()
+  , m_tracker()
+{
+  // This constructor can only be used to construct a subview
+  // from the source view.  This type must match the subview type
+  // deduced from the source view and subview arguments.
+
+  typedef Impl::ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                           , SubArg0_type , SubArg1_type , SubArg2_type , SubArg3_type
+                           , SubArg4_type , SubArg5_type , SubArg6_type , void >
+    ViewSubviewDeduction ;
+
+  enum { is_a_valid_subview_constructor =
+    Impl::StaticAssert<
+      Impl::is_same< View , typename ViewSubviewDeduction::type >::value
+    >::value
+  };
+
+  if ( is_a_valid_subview_constructor ) {
+
+    typedef Impl::ViewOffsetRange< SubArg0_type > R0 ;
+    typedef Impl::ViewOffsetRange< SubArg1_type > R1 ;
+    typedef Impl::ViewOffsetRange< SubArg2_type > R2 ;
+    typedef Impl::ViewOffsetRange< SubArg3_type > R3 ;
+    typedef Impl::ViewOffsetRange< SubArg4_type > R4 ;
+    typedef Impl::ViewOffsetRange< SubArg5_type > R5 ;
+    typedef Impl::ViewOffsetRange< SubArg6_type > R6 ;
+
+    // 'assign_subview' returns whether the subview offset_map
+    // introduces noncontiguity in the view.
+    const bool introduce_noncontiguity =
+      m_offset_map.assign_subview( src.m_offset_map
+                                 , R0::dimension( src.m_offset_map.N0 , arg0 )
+                                 , R1::dimension( src.m_offset_map.N1 , arg1 )
+                                 , R2::dimension( src.m_offset_map.N2 , arg2 )
+                                 , R3::dimension( src.m_offset_map.N3 , arg3 )
+                                 , R4::dimension( src.m_offset_map.N4 , arg4 )
+                                 , R5::dimension( src.m_offset_map.N5 , arg5 )
+                                 , R6::dimension( src.m_offset_map.N6 , arg6 )
+                                 , 0
+                                 );
+
+    if ( m_offset_map.capacity() ) {
+
+      m_management = src.m_management ;
+
+      if ( introduce_noncontiguity ) m_management.set_noncontiguous();
+
+      m_ptr_on_device = src.m_ptr_on_device +
+                        src.m_offset_map( R0::begin( arg0 )
+                                        , R1::begin( arg1 )
+                                        , R2::begin( arg2 )
+                                        , R3::begin( arg3 )
+                                        , R4::begin( arg4 )
+                                        , R5::begin( arg5 )
+                                        , R6::begin( arg6 )
+                                        );
+      m_tracker = src.m_tracker ;
+    }
+  }
+}
+
+// Construct subview of a Rank 6 view
+template< class DstDataType , class DstArg1Type , class DstArg2Type , class DstArg3Type >
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type , class SubArg2_type , class SubArg3_type
+        , class SubArg4_type , class SubArg5_type
+        >
+KOKKOS_INLINE_FUNCTION
+View< DstDataType , DstArg1Type , DstArg2Type , DstArg3Type , Impl::ViewDefault >::
+View( const View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault > & src
+    , const SubArg0_type & arg0
+    , const SubArg1_type & arg1
+    , const SubArg2_type & arg2
+    , const SubArg3_type & arg3
+    , const SubArg4_type & arg4
+    , const SubArg5_type & arg5
+    )
+  : m_ptr_on_device( (typename traits::value_type*) NULL)
+  , m_offset_map()
+  , m_management()
+  , m_tracker()
+{
+  // This constructor can only be used to construct a subview
+  // from the source view.  This type must match the subview type
+  // deduced from the source view and subview arguments.
+
+  typedef Impl::ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                           , SubArg0_type , SubArg1_type , SubArg2_type , SubArg3_type
+                           , SubArg4_type , SubArg5_type , void , void >
+    ViewSubviewDeduction ;
+
+  enum { is_a_valid_subview_constructor =
+    Impl::StaticAssert<
+      Impl::is_same< View , typename ViewSubviewDeduction::type >::value
+    >::value
+  };
+
+  if ( is_a_valid_subview_constructor ) {
+
+    typedef Impl::ViewOffsetRange< SubArg0_type > R0 ;
+    typedef Impl::ViewOffsetRange< SubArg1_type > R1 ;
+    typedef Impl::ViewOffsetRange< SubArg2_type > R2 ;
+    typedef Impl::ViewOffsetRange< SubArg3_type > R3 ;
+    typedef Impl::ViewOffsetRange< SubArg4_type > R4 ;
+    typedef Impl::ViewOffsetRange< SubArg5_type > R5 ;
+
+    // 'assign_subview' returns whether the subview offset_map
+    // introduces noncontiguity in the view.
+    const bool introduce_noncontiguity =
+      m_offset_map.assign_subview( src.m_offset_map
+                                 , R0::dimension( src.m_offset_map.N0 , arg0 )
+                                 , R1::dimension( src.m_offset_map.N1 , arg1 )
+                                 , R2::dimension( src.m_offset_map.N2 , arg2 )
+                                 , R3::dimension( src.m_offset_map.N3 , arg3 )
+                                 , R4::dimension( src.m_offset_map.N4 , arg4 )
+                                 , R5::dimension( src.m_offset_map.N5 , arg5 )
+                                 , 0
+                                 , 0
+                                 );
+
+    if ( m_offset_map.capacity() ) {
+
+      m_management = src.m_management ;
+
+      if ( introduce_noncontiguity ) m_management.set_noncontiguous();
+
+      m_ptr_on_device = src.m_ptr_on_device +
+                        src.m_offset_map( R0::begin( arg0 )
+                                        , R1::begin( arg1 )
+                                        , R2::begin( arg2 )
+                                        , R3::begin( arg3 )
+                                        , R4::begin( arg4 )
+                                        , R5::begin( arg5 )
+                                        );
+      m_tracker = src.m_tracker ;
+    }
+  }
+}
+
+// Construct subview of a Rank 5 view
+template< class DstDataType , class DstArg1Type , class DstArg2Type , class DstArg3Type >
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type , class SubArg2_type , class SubArg3_type
+        , class SubArg4_type
+        >
+KOKKOS_INLINE_FUNCTION
+View< DstDataType , DstArg1Type , DstArg2Type , DstArg3Type , Impl::ViewDefault >::
+View( const View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault > & src
+    , const SubArg0_type & arg0
+    , const SubArg1_type & arg1
+    , const SubArg2_type & arg2
+    , const SubArg3_type & arg3
+    , const SubArg4_type & arg4
+    )
+  : m_ptr_on_device( (typename traits::value_type*) NULL)
+  , m_offset_map()
+  , m_management()
+  , m_tracker()
+{
+  // This constructor can only be used to construct a subview
+  // from the source view.  This type must match the subview type
+  // deduced from the source view and subview arguments.
+
+  typedef Impl::ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                           , SubArg0_type , SubArg1_type , SubArg2_type , SubArg3_type
+                           , SubArg4_type , void , void , void >
+    ViewSubviewDeduction ;
+
+  enum { is_a_valid_subview_constructor =
+    Impl::StaticAssert<
+      Impl::is_same< View , typename ViewSubviewDeduction::type >::value
+    >::value
+  };
+
+  if ( is_a_valid_subview_constructor ) {
+
+    typedef Impl::ViewOffsetRange< SubArg0_type > R0 ;
+    typedef Impl::ViewOffsetRange< SubArg1_type > R1 ;
+    typedef Impl::ViewOffsetRange< SubArg2_type > R2 ;
+    typedef Impl::ViewOffsetRange< SubArg3_type > R3 ;
+    typedef Impl::ViewOffsetRange< SubArg4_type > R4 ;
+
+    // 'assign_subview' returns whether the subview offset_map
+    // introduces noncontiguity in the view.
+    const bool introduce_noncontiguity =
+      m_offset_map.assign_subview( src.m_offset_map
+                                 , R0::dimension( src.m_offset_map.N0 , arg0 )
+                                 , R1::dimension( src.m_offset_map.N1 , arg1 )
+                                 , R2::dimension( src.m_offset_map.N2 , arg2 )
+                                 , R3::dimension( src.m_offset_map.N3 , arg3 )
+                                 , R4::dimension( src.m_offset_map.N4 , arg4 )
+                                 , 0
+                                 , 0
+                                 , 0
+                                 );
+
+    if ( m_offset_map.capacity() ) {
+
+      m_management = src.m_management ;
+
+      if ( introduce_noncontiguity ) m_management.set_noncontiguous();
+
+      m_ptr_on_device = src.m_ptr_on_device +
+                        src.m_offset_map( R0::begin( arg0 )
+                                        , R1::begin( arg1 )
+                                        , R2::begin( arg2 )
+                                        , R3::begin( arg3 )
+                                        , R4::begin( arg4 )
+                                        );
+      m_tracker = src.m_tracker ;
+    }
+  }
+}
+
+// Construct subview of a Rank 4 view
+template< class DstDataType , class DstArg1Type , class DstArg2Type , class DstArg3Type >
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type , class SubArg2_type , class SubArg3_type
+        >
+KOKKOS_INLINE_FUNCTION
+View< DstDataType , DstArg1Type , DstArg2Type , DstArg3Type , Impl::ViewDefault >::
+View( const View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault > & src
+    , const SubArg0_type & arg0
+    , const SubArg1_type & arg1
+    , const SubArg2_type & arg2
+    , const SubArg3_type & arg3
+    )
+  : m_ptr_on_device( (typename traits::value_type*) NULL)
+  , m_offset_map()
+  , m_management()
+  , m_tracker()
+{
+  // This constructor can only be used to construct a subview
+  // from the source view.  This type must match the subview type
+  // deduced from the source view and subview arguments.
+
+  typedef Impl::ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                           , SubArg0_type , SubArg1_type , SubArg2_type , SubArg3_type
+                           , void , void , void , void >
+    ViewSubviewDeduction ;
+
+  enum { is_a_valid_subview_constructor =
+    Impl::StaticAssert<
+      Impl::is_same< View , typename ViewSubviewDeduction::type >::value
+    >::value
+  };
+
+  if ( is_a_valid_subview_constructor ) {
+
+    typedef Impl::ViewOffsetRange< SubArg0_type > R0 ;
+    typedef Impl::ViewOffsetRange< SubArg1_type > R1 ;
+    typedef Impl::ViewOffsetRange< SubArg2_type > R2 ;
+    typedef Impl::ViewOffsetRange< SubArg3_type > R3 ;
+
+    // 'assign_subview' returns whether the subview offset_map
+    // introduces noncontiguity in the view.
+    const bool introduce_noncontiguity =
+      m_offset_map.assign_subview( src.m_offset_map
+                                 , R0::dimension( src.m_offset_map.N0 , arg0 )
+                                 , R1::dimension( src.m_offset_map.N1 , arg1 )
+                                 , R2::dimension( src.m_offset_map.N2 , arg2 )
+                                 , R3::dimension( src.m_offset_map.N3 , arg3 )
+                                 , 0
+                                 , 0
+                                 , 0
+                                 , 0
+                                 );
+
+    if ( m_offset_map.capacity() ) {
+
+      m_management = src.m_management ;
+
+      if ( introduce_noncontiguity ) m_management.set_noncontiguous();
+
+      m_ptr_on_device = src.m_ptr_on_device +
+                        src.m_offset_map( R0::begin( arg0 )
+                                        , R1::begin( arg1 )
+                                        , R2::begin( arg2 )
+                                        , R3::begin( arg3 )
+                                        );
+      m_tracker = src.m_tracker ;
+    }
+  }
+}
+
+// Construct subview of a Rank 3 view
+template< class DstDataType , class DstArg1Type , class DstArg2Type , class DstArg3Type >
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type , class SubArg2_type
+        >
+KOKKOS_INLINE_FUNCTION
+View< DstDataType , DstArg1Type , DstArg2Type , DstArg3Type , Impl::ViewDefault >::
+View( const View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault > & src
+    , const SubArg0_type & arg0
+    , const SubArg1_type & arg1
+    , const SubArg2_type & arg2
+    )
+  : m_ptr_on_device( (typename traits::value_type*) NULL)
+  , m_offset_map()
+  , m_management()
+  , m_tracker()
+{
+  // This constructor can only be used to construct a subview
+  // from the source view.  This type must match the subview type
+  // deduced from the source view and subview arguments.
+
+  typedef Impl::ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                           , SubArg0_type , SubArg1_type , SubArg2_type , void , void , void , void , void >
+    ViewSubviewDeduction ;
+
+  enum { is_a_valid_subview_constructor =
+    Impl::StaticAssert<
+      Impl::is_same< View , typename ViewSubviewDeduction::type >::value
+    >::value
+  };
+
+  if ( is_a_valid_subview_constructor ) {
+
+    typedef Impl::ViewOffsetRange< SubArg0_type > R0 ;
+    typedef Impl::ViewOffsetRange< SubArg1_type > R1 ;
+    typedef Impl::ViewOffsetRange< SubArg2_type > R2 ;
+
+    // 'assign_subview' returns whether the subview offset_map
+    // introduces noncontiguity in the view.
+    const bool introduce_noncontiguity =
+      m_offset_map.assign_subview( src.m_offset_map
+                                 , R0::dimension( src.m_offset_map.N0 , arg0 )
+                                 , R1::dimension( src.m_offset_map.N1 , arg1 )
+                                 , R2::dimension( src.m_offset_map.N2 , arg2 )
+                                 , 0 , 0 , 0 , 0 , 0);
+
+    if ( m_offset_map.capacity() ) {
+
+      m_management = src.m_management ;
+
+      if ( introduce_noncontiguity ) m_management.set_noncontiguous();
+
+      m_ptr_on_device = src.m_ptr_on_device +
+                        src.m_offset_map( R0::begin( arg0 )
+                                        , R1::begin( arg1 )
+                                        , R2::begin( arg2 )
+                                        );
+      m_tracker = src.m_tracker ;
+    }
+  }
+}
+
+// Construct subview of a Rank 2 view
+template< class DstDataType , class DstArg1Type , class DstArg2Type , class DstArg3Type >
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type , class SubArg1_type
+        >
+KOKKOS_INLINE_FUNCTION
+View< DstDataType , DstArg1Type , DstArg2Type , DstArg3Type , Impl::ViewDefault >::
+View( const View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault > & src
+    , const SubArg0_type & arg0
+    , const SubArg1_type & arg1
+    )
+  : m_ptr_on_device( (typename traits::value_type*) NULL)
+  , m_offset_map()
+  , m_management()
+  , m_tracker()
+{
+  // This constructor can only be used to construct a subview
+  // from the source view.  This type must match the subview type
+  // deduced from the source view and subview arguments.
+
+  typedef Impl::ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                           , SubArg0_type , SubArg1_type , void , void , void , void , void , void >
+    ViewSubviewDeduction ;
+
+  enum { is_a_valid_subview_constructor =
+    Impl::StaticAssert<
+      Impl::is_same< View , typename ViewSubviewDeduction::type >::value
+    >::value
+  };
+
+  if ( is_a_valid_subview_constructor ) {
+
+    typedef Impl::ViewOffsetRange< SubArg0_type > R0 ;
+    typedef Impl::ViewOffsetRange< SubArg1_type > R1 ;
+
+    // 'assign_subview' returns whether the subview offset_map
+    // introduces noncontiguity in the view.
+    const bool introduce_noncontiguity =
+      m_offset_map.assign_subview( src.m_offset_map
+                                 , R0::dimension( src.m_offset_map.N0 , arg0 )
+                                 , R1::dimension( src.m_offset_map.N1 , arg1 )
+                                 , 0 , 0 , 0 , 0 , 0 , 0 );
+
+    if ( m_offset_map.capacity() ) {
+
+      m_management = src.m_management ;
+
+      if ( introduce_noncontiguity ) m_management.set_noncontiguous();
+
+      m_ptr_on_device = src.m_ptr_on_device +
+                        src.m_offset_map( R0::begin( arg0 )
+                                        , R1::begin( arg1 )
+                                        );
+      m_tracker = src.m_tracker ;
+    }
+  }
+}
+
+// Construct subview of a Rank 1 view
+template< class DstDataType , class DstArg1Type , class DstArg2Type , class DstArg3Type >
+template< class SrcDataType , class SrcArg1Type , class SrcArg2Type , class SrcArg3Type
+        , class SubArg0_type
+        >
+KOKKOS_INLINE_FUNCTION
+View< DstDataType , DstArg1Type , DstArg2Type , DstArg3Type , Impl::ViewDefault >::
+View( const View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault > & src
+    , const SubArg0_type & arg0
+    )
+  : m_ptr_on_device( (typename traits::value_type*) NULL)
+  , m_offset_map()
+  , m_management()
+  , m_tracker()
+{
+  // This constructor can only be used to construct a subview
+  // from the source view.  This type must match the subview type
+  // deduced from the source view and subview arguments.
+
+  typedef Impl::ViewSubview< View< SrcDataType , SrcArg1Type , SrcArg2Type , SrcArg3Type , Impl::ViewDefault >
+                           , SubArg0_type , void , void , void , void , void , void , void >
+    ViewSubviewDeduction ;
+
+  enum { is_a_valid_subview_constructor =
+    Impl::StaticAssert<
+      Impl::is_same< View , typename ViewSubviewDeduction::type >::value
+    >::value
+  };
+
+  if ( is_a_valid_subview_constructor ) {
+
+    typedef Impl::ViewOffsetRange< SubArg0_type > R0 ;
+
+    // 'assign_subview' returns whether the subview offset_map
+    // introduces noncontiguity in the view.
+    const bool introduce_noncontiguity =
+      m_offset_map.assign_subview( src.m_offset_map
+                                 , R0::dimension( src.m_offset_map.N0 , arg0 )
+                                 , 0 , 0 , 0 , 0 , 0 , 0 , 0 );
+
+    if ( m_offset_map.capacity() ) {
+
+      m_management = src.m_management ;
+
+      if ( introduce_noncontiguity ) m_management.set_noncontiguous();
+
+      m_ptr_on_device = src.m_ptr_on_device +
+                        src.m_offset_map( R0::begin( arg0 )
+                                        );
+      m_tracker = src.m_tracker ;
+    }
+  }
+}
+
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_VIEWDEFAULT_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_ViewOffset.hpp b/lib/kokkos/core/src/impl/Kokkos_ViewOffset.hpp
new file mode 100644
index 0000000000..5748e722c0
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_ViewOffset.hpp
@@ -0,0 +1,1341 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_VIEWOFFSET_HPP
+#define KOKKOS_VIEWOFFSET_HPP
+
+#include <Kokkos_Pair.hpp>
+#include <Kokkos_Layout.hpp>
+#include <impl/Kokkos_Traits.hpp>
+#include <impl/Kokkos_Shape.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos { namespace Impl {
+
+template < class ShapeType , class LayoutType , typename Enable = void >
+struct ViewOffset ;
+
+//----------------------------------------------------------------------------
+// LayoutLeft AND ( 1 >= rank OR 0 == rank_dynamic ) : no padding / striding
+template < class ShapeType >
+struct ViewOffset< ShapeType , LayoutLeft
+                 , typename enable_if<( 1 >= ShapeType::rank
+                                        ||
+                                        0 == ShapeType::rank_dynamic
+                                      )>::type >
+  : public ShapeType
+{
+  typedef size_t     size_type ;
+  typedef ShapeType  shape_type ;
+  typedef LayoutLeft array_layout ;
+
+  enum { has_padding = false };
+
+  template< unsigned R >
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n )
+    { assign_shape_dimension<R>( *this , n ); }
+
+  // Return whether the subview introduced noncontiguity
+  template< class S , class L >
+  KOKKOS_INLINE_FUNCTION
+  typename Impl::enable_if<( 0 == shape_type::rank &&
+                             Impl::is_same<L,LayoutLeft>::value
+                           ), bool >::type
+  assign_subview( const ViewOffset<S,L,void> &
+                , const size_t n0
+                , const size_t n1
+                , const size_t n2
+                , const size_t n3
+                , const size_t n4
+                , const size_t n5
+                , const size_t n6
+                , const size_t n7
+                )
+    {
+      return false ; // did not introduce noncontiguity
+    }
+
+  // This subview must be 1 == rank and 1 == rank_dynamic.
+  // The source dimension #0 must be non-zero and all other dimensions are zero.
+  // Return whether the subview introduced noncontiguity
+  template< class S , class L >
+  KOKKOS_INLINE_FUNCTION
+  typename Impl::enable_if<( 1 == shape_type::rank &&
+                             1 == shape_type::rank_dynamic &&
+                             1 <= S::rank &&
+                             Impl::is_same<L,LayoutLeft>::value
+                           ), bool >::type
+  assign_subview( const ViewOffset<S,L,void> &
+                , const size_t n0
+                , const size_t n1
+                , const size_t n2
+                , const size_t n3
+                , const size_t n4
+                , const size_t n5
+                , const size_t n6
+                , const size_t n7
+                )
+    {
+      // n1 .. n7 must be zero
+      shape_type::N0 = n0 ;
+      return false ; // did not introduce noncontiguity
+    }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n0 , size_t n1 , size_t n2 , size_t n3
+             , size_t n4 , size_t n5 , size_t n6 , size_t n7
+             , size_t = 0 )
+    { shape_type::assign( *this , n0, n1, n2, n3, n4, n5, n6, n7 ); }
+
+  template< class ShapeRHS >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset< ShapeRHS , LayoutLeft > & rhs
+             , typename enable_if<( int(ShapeRHS::rank) == int(shape_type::rank)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) <= int(shape_type::rank_dynamic)
+                                  )>::type * = 0 )
+    { shape_type::assign( *this , rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 ); }
+
+  template< class ShapeRHS >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset< ShapeRHS , LayoutRight > & rhs
+             , typename enable_if<( 1 == int(ShapeRHS::rank)
+                                    &&
+                                    1 == int(shape_type::rank)
+                                    &&
+                                    1 == int(shape_type::rank_dynamic)
+                                  )>::type * = 0 )
+    { shape_type::assign( *this , rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 ); }
+
+  KOKKOS_INLINE_FUNCTION
+  void set_padding() {}
+
+  KOKKOS_INLINE_FUNCTION
+  size_type cardinality() const
+    { return size_type(shape_type::N0) * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type capacity() const
+    { return size_type(shape_type::N0) * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ; }
+
+  // Stride with [ rank ] value is the total length
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      s[0] = 1 ;
+      if ( 0 < shape_type::rank ) { s[1] = shape_type::N0 ; }
+      if ( 1 < shape_type::rank ) { s[2] = s[1] * shape_type::N1 ; }
+      if ( 2 < shape_type::rank ) { s[3] = s[2] * shape_type::N2 ; }
+      if ( 3 < shape_type::rank ) { s[4] = s[3] * shape_type::N3 ; }
+      if ( 4 < shape_type::rank ) { s[5] = s[4] * shape_type::N4 ; }
+      if ( 5 < shape_type::rank ) { s[6] = s[5] * shape_type::N5 ; }
+      if ( 6 < shape_type::rank ) { s[7] = s[6] * shape_type::N6 ; }
+      if ( 7 < shape_type::rank ) { s[8] = s[7] * shape_type::N7 ; }
+    }
+
+  KOKKOS_INLINE_FUNCTION size_type stride_0() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION size_type stride_1() const { return shape_type::N0 ; }
+  KOKKOS_INLINE_FUNCTION size_type stride_2() const { return shape_type::N0 * shape_type::N1 ; }
+  KOKKOS_INLINE_FUNCTION size_type stride_3() const { return shape_type::N0 * shape_type::N1 * shape_type::N2 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_4() const
+    { return shape_type::N0 * shape_type::N1 * shape_type::N2 * shape_type::N3 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_5() const
+    { return shape_type::N0 * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_6() const
+    { return shape_type::N0 * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_7() const
+    { return shape_type::N0 * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 ; }
+
+  // rank 1
+  template< typename I0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const & i0 ) const { return i0 ; }
+
+  // rank 2
+  template < typename I0 , typename I1 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const & i0 , I1 const & i1 ) const
+    { return i0 + shape_type::N0 * i1 ; }
+
+  //rank 3
+  template <typename I0, typename I1, typename I2>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0
+                      , I1 const& i1
+                      , I2 const& i2
+                      ) const
+    {
+      return i0 + shape_type::N0 * (
+             i1 + shape_type::N1 * i2 );
+    }
+
+  //rank 4
+  template <typename I0, typename I1, typename I2, typename I3>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3 ) const
+    {
+      return i0 + shape_type::N0 * (
+             i1 + shape_type::N1 * (
+             i2 + shape_type::N2 * i3 ));
+    }
+
+  //rank 5
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4 ) const
+    {
+      return i0 + shape_type::N0 * (
+             i1 + shape_type::N1 * (
+             i2 + shape_type::N2 * (
+             i3 + shape_type::N3 * i4 )));
+    }
+
+  //rank 6
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5 ) const
+    {
+      return i0 + shape_type::N0 * (
+             i1 + shape_type::N1 * (
+             i2 + shape_type::N2 * (
+             i3 + shape_type::N3 * (
+             i4 + shape_type::N4 * i5 ))));
+    }
+
+  //rank 7
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6) const
+  {
+    return i0 + shape_type::N0 * (
+           i1 + shape_type::N1 * (
+           i2 + shape_type::N2 * (
+           i3 + shape_type::N3 * (
+           i4 + shape_type::N4 * (
+           i5 + shape_type::N5 * i6 )))));
+  }
+
+  //rank 8
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6, I7 const& i7) const
+  {
+    return i0 + shape_type::N0 * (
+           i1 + shape_type::N1 * (
+           i2 + shape_type::N2 * (
+           i3 + shape_type::N3 * (
+           i4 + shape_type::N4 * (
+           i5 + shape_type::N5 * (
+           i6 + shape_type::N6 * i7 ))))));
+  }
+};
+
+//----------------------------------------------------------------------------
+// LayoutLeft AND ( 1 < rank AND 0 < rank_dynamic ) : has padding / striding
+template < class ShapeType >
+struct ViewOffset< ShapeType , LayoutLeft
+                 , typename enable_if<( 1 < ShapeType::rank
+                                        &&
+                                        0 < ShapeType::rank_dynamic
+                                      )>::type >
+  : public ShapeType
+{
+  typedef size_t     size_type ;
+  typedef ShapeType  shape_type ;
+  typedef LayoutLeft array_layout ;
+
+  enum { has_padding = true };
+
+  size_type S0 ;
+
+  // This subview must be 2 == rank and 2 == rank_dynamic
+  // due to only having stride #0.
+  // The source dimension #0 must be non-zero for stride-one leading dimension.
+  // At most subsequent dimension can be non-zero.
+  // Return whether the subview introduced noncontiguity.
+  template< class S , class L >
+  KOKKOS_INLINE_FUNCTION
+  typename Impl::enable_if<( 2 == shape_type::rank &&
+                             2 == shape_type::rank_dynamic &&
+                             2 <= S::rank &&
+                             Impl::is_same<L,LayoutLeft>::value
+                           ), bool >::type
+  assign_subview( const ViewOffset<S,L,void> & rhs
+                , const size_t n0
+                , const size_t n1
+                , const size_t n2
+                , const size_t n3
+                , const size_t n4
+                , const size_t n5
+                , const size_t n6
+                , const size_t n7
+                )
+    {
+      // N1 = second non-zero dimension
+      // S0 = stride for second non-zero dimension
+      shape_type::N0 = n0 ;
+      shape_type::N1 = 0 ;
+      S0 = 0 ;
+
+      if      (                n1 ) { shape_type::N1 = n1 ; S0 = rhs.stride_1(); }
+      else if ( 2 < S::rank && n2 ) { shape_type::N1 = n2 ; S0 = rhs.stride_2(); }
+      else if ( 3 < S::rank && n3 ) { shape_type::N1 = n3 ; S0 = rhs.stride_3(); }
+      else if ( 4 < S::rank && n4 ) { shape_type::N1 = n4 ; S0 = rhs.stride_4(); }
+      else if ( 5 < S::rank && n5 ) { shape_type::N1 = n5 ; S0 = rhs.stride_5(); }
+      else if ( 6 < S::rank && n6 ) { shape_type::N1 = n6 ; S0 = rhs.stride_6(); }
+      else if ( 7 < S::rank && n7 ) { shape_type::N1 = n7 ; S0 = rhs.stride_7(); }
+
+      // Introduce noncontiguity if change the first dimension
+      // or took a range of a dimension after the second.
+      return ( size_t(shape_type::N0) != size_t(rhs.N0) ) || ( 0 == n1 );
+    }
+
+
+  template< unsigned R >
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n )
+    { assign_shape_dimension<R>( *this , n ); }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n0 , size_t n1 , size_t n2 , size_t n3
+             , size_t n4 , size_t n5 , size_t n6 , size_t n7
+             , size_t = 0 )
+    { shape_type::assign( *this , n0, n1, n2, n3, n4, n5, n6, n7 ); S0 = shape_type::N0 ; }
+
+  template< class ShapeRHS >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset< ShapeRHS , LayoutLeft > & rhs
+             , typename enable_if<( int(ShapeRHS::rank) == int(shape_type::rank)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) <= int(shape_type::rank_dynamic)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) == 0
+                                  )>::type * = 0 )
+    {
+      shape_type::assign( *this , rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 );
+      S0 = shape_type::N0 ; // No padding when dynamic_rank == 0
+    }
+
+  template< class ShapeRHS >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset< ShapeRHS , LayoutLeft > & rhs
+             , typename enable_if<( int(ShapeRHS::rank) == int(shape_type::rank)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) <= int(shape_type::rank_dynamic)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) > 0
+                                  )>::type * = 0 )
+    {
+      shape_type::assign( *this , rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 );
+      S0 = rhs.S0 ; // possibly padding when dynamic rank > 0
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void set_padding()
+    {
+      enum { div   = MEMORY_ALIGNMENT / shape_type::scalar_size };
+      enum { mod   = MEMORY_ALIGNMENT % shape_type::scalar_size };
+      enum { align = 0 == mod ? div : 0 };
+
+      if ( align && MEMORY_ALIGNMENT_THRESHOLD * align < S0 ) {
+
+        const size_type count_mod = S0 % ( div ? div : 1 );
+
+        if ( count_mod ) { S0 += align - count_mod ; }
+      }
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type cardinality() const
+    { return size_type(shape_type::N0) * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type capacity() const
+    { return size_type(S0) * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ; }
+
+  // Stride with [ rank ] as total length
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      s[0] = 1 ;
+      if ( 0 < shape_type::rank ) { s[1] = S0 ; }
+      if ( 1 < shape_type::rank ) { s[2] = s[1] * shape_type::N1 ; }
+      if ( 2 < shape_type::rank ) { s[3] = s[2] * shape_type::N2 ; }
+      if ( 3 < shape_type::rank ) { s[4] = s[3] * shape_type::N3 ; }
+      if ( 4 < shape_type::rank ) { s[5] = s[4] * shape_type::N4 ; }
+      if ( 5 < shape_type::rank ) { s[6] = s[5] * shape_type::N5 ; }
+      if ( 6 < shape_type::rank ) { s[7] = s[6] * shape_type::N6 ; }
+      if ( 7 < shape_type::rank ) { s[8] = s[7] * shape_type::N7 ; }
+    }
+
+  KOKKOS_INLINE_FUNCTION size_type stride_0() const { return 1 ; }
+  KOKKOS_INLINE_FUNCTION size_type stride_1() const { return S0 ; }
+  KOKKOS_INLINE_FUNCTION size_type stride_2() const { return S0 * shape_type::N1 ; }
+  KOKKOS_INLINE_FUNCTION size_type stride_3() const { return S0 * shape_type::N1 * shape_type::N2 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_4() const
+    { return S0 * shape_type::N1 * shape_type::N2 * shape_type::N3 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_5() const
+    { return S0 * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_6() const
+    { return S0 * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_7() const
+    { return S0 * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 ; }
+
+  // rank 2
+  template < typename I0 , typename I1 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const & i0 , I1 const & i1) const
+    { return i0 + S0 * i1 ; }
+
+  //rank 3
+  template <typename I0, typename I1, typename I2>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 ) const
+    {
+      return i0 + S0 * (
+             i1 + shape_type::N1 * i2 );
+    }
+
+  //rank 4
+  template <typename I0, typename I1, typename I2, typename I3>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3 ) const
+    {
+      return i0 + S0 * (
+             i1 + shape_type::N1 * (
+             i2 + shape_type::N2 * i3 ));
+    }
+
+  //rank 5
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4 ) const
+    {
+      return i0 + S0 * (
+             i1 + shape_type::N1 * (
+             i2 + shape_type::N2 * (
+             i3 + shape_type::N3 * i4 )));
+    }
+
+  //rank 6
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5 ) const
+    {
+      return i0 + S0 * (
+             i1 + shape_type::N1 * (
+             i2 + shape_type::N2 * (
+             i3 + shape_type::N3 * (
+             i4 + shape_type::N4 * i5 ))));
+    }
+
+  //rank 7
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6 ) const
+  {
+    return i0 + S0 * (
+           i1 + shape_type::N1 * (
+           i2 + shape_type::N2 * (
+           i3 + shape_type::N3 * (
+           i4 + shape_type::N4 * (
+           i5 + shape_type::N5 * i6 )))));
+  }
+
+  //rank 8
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2, I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6, I7 const& i7 ) const
+  {
+    return i0 + S0 * (
+           i1 + shape_type::N1 * (
+           i2 + shape_type::N2 * (
+           i3 + shape_type::N3 * (
+           i4 + shape_type::N4 * (
+           i5 + shape_type::N5 * (
+           i6 + shape_type::N6 * i7 ))))));
+  }
+};
+
+//----------------------------------------------------------------------------
+// LayoutRight AND ( 1 >= rank OR 1 >= rank_dynamic ) : no padding / striding
+template < class ShapeType >
+struct ViewOffset< ShapeType , LayoutRight
+                 , typename enable_if<( 1 >= ShapeType::rank
+                                        ||
+                                        1 >= ShapeType::rank_dynamic
+                                      )>::type >
+  : public ShapeType
+{
+  typedef size_t       size_type;
+  typedef ShapeType    shape_type;
+  typedef LayoutRight  array_layout ;
+
+  enum { has_padding = false };
+
+  // This subview must be 1 == rank and 1 == rank_dynamic
+  // The source view's last dimension must be non-zero
+  // Return whether the subview introduced noncontiguity
+  template< class S , class L >
+  KOKKOS_INLINE_FUNCTION
+  typename Impl::enable_if<( 0 == shape_type::rank &&
+                             Impl::is_same<L,LayoutRight>::value
+                           ), bool >::type
+  assign_subview( const ViewOffset<S,L,void> &
+                , const size_t n0
+                , const size_t n1
+                , const size_t n2
+                , const size_t n3
+                , const size_t n4
+                , const size_t n5
+                , const size_t n6
+                , const size_t n7
+                )
+    { return false ; }
+
+  // This subview must be 1 == rank and 1 == rank_dynamic
+  // The source view's last dimension must be non-zero
+  // Return whether the subview introduced noncontiguity
+  template< class S , class L >
+  KOKKOS_INLINE_FUNCTION
+  typename Impl::enable_if<( 1 == shape_type::rank &&
+                             1 == shape_type::rank_dynamic &&
+                             1 <= S::rank &&
+                             Impl::is_same<L,LayoutRight>::value
+                           ), bool >::type
+  assign_subview( const ViewOffset<S,L,void> &
+                , const size_t n0
+                , const size_t n1
+                , const size_t n2
+                , const size_t n3
+                , const size_t n4
+                , const size_t n5
+                , const size_t n6
+                , const size_t n7
+                )
+    {
+      shape_type::N0 = S::rank == 1 ? n0 : (
+                       S::rank == 2 ? n1 : (
+                       S::rank == 3 ? n2 : (
+                       S::rank == 4 ? n3 : (
+                       S::rank == 5 ? n4 : (
+                       S::rank == 6 ? n5 : (
+                       S::rank == 7 ? n6 : n7 ))))));
+      // should have n0 .. n_(rank-2) equal zero
+      return false ;
+    }
+
+  template< unsigned R >
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n )
+    { assign_shape_dimension<R>( *this , n ); }
+
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n0 , size_t n1 , size_t n2 , size_t n3
+             , size_t n4 , size_t n5 , size_t n6 , size_t n7
+             , size_t = 0 )
+    { shape_type::assign( *this , n0, n1, n2, n3, n4, n5, n6, n7 ); }
+
+  template< class ShapeRHS >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset< ShapeRHS , LayoutRight > & rhs
+             , typename enable_if<( int(ShapeRHS::rank) == int(shape_type::rank)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) <= int(shape_type::rank_dynamic)
+                                  )>::type * = 0 )
+    { shape_type::assign( *this , rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 ); }
+
+  template< class ShapeRHS >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset< ShapeRHS , LayoutLeft > & rhs
+             , typename enable_if<( 1 == int(ShapeRHS::rank)
+                                    &&
+                                    1 == int(shape_type::rank)
+                                    &&
+                                    1 == int(shape_type::rank_dynamic)
+                                  )>::type * = 0 )
+    { shape_type::assign( *this , rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 ); }
+
+  KOKKOS_INLINE_FUNCTION
+  void set_padding() {}
+
+  KOKKOS_INLINE_FUNCTION
+  size_type cardinality() const
+    { return size_type(shape_type::N0) * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type capacity() const
+    { return size_type(shape_type::N0) * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ; }
+
+  size_type stride_R() const
+    {
+      return size_type(shape_type::N1) * shape_type::N2 * shape_type::N3 *
+             shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ;
+    };
+
+  // Stride with [rank] as total length
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      size_type n = 1 ;
+      if ( 7 < shape_type::rank ) { s[7] = n ; n *= shape_type::N7 ; }
+      if ( 6 < shape_type::rank ) { s[6] = n ; n *= shape_type::N6 ; }
+      if ( 5 < shape_type::rank ) { s[5] = n ; n *= shape_type::N5 ; }
+      if ( 4 < shape_type::rank ) { s[4] = n ; n *= shape_type::N4 ; }
+      if ( 3 < shape_type::rank ) { s[3] = n ; n *= shape_type::N3 ; }
+      if ( 2 < shape_type::rank ) { s[2] = n ; n *= shape_type::N2 ; }
+      if ( 1 < shape_type::rank ) { s[1] = n ; n *= shape_type::N1 ; }
+      if ( 0 < shape_type::rank ) { s[0] = n ; }
+      s[shape_type::rank] = n * shape_type::N0 ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_7() const { return 1 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_6() const { return shape_type::N7 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_5() const { return shape_type::N7 * shape_type::N6 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_4() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_3() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 * shape_type::N4 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_2() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 * shape_type::N4 * shape_type::N3 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_1() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 * shape_type::N4 * shape_type::N3 * shape_type::N2 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_0() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 * shape_type::N4 * shape_type::N3 * shape_type::N2 * shape_type::N1 ; }
+
+  // rank 1
+  template <typename I0>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0) const
+    {
+      return i0 ;
+    }
+
+  // rank 2
+  template <typename I0, typename I1>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1 ) const
+    {
+      return i1 + shape_type::N1 * i0 ;
+    }
+
+  template <typename I0, typename I1, typename I2>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 ) const
+    {
+      return i2 + shape_type::N2 * (
+             i1 + shape_type::N1 * ( i0 ));
+    }
+
+  template <typename I0, typename I1, typename I2, typename I3>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3 ) const
+    {
+      return i3 + shape_type::N3 * (
+             i2 + shape_type::N2 * (
+             i1 + shape_type::N1 * ( i0 )));
+    }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4 ) const
+    {
+      return i4 + shape_type::N4 * (
+             i3 + shape_type::N3 * (
+             i2 + shape_type::N2 * (
+             i1 + shape_type::N1 * ( i0 ))));
+    }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5 ) const
+  {
+    return i5 + shape_type::N5 * (
+           i4 + shape_type::N4 * (
+           i3 + shape_type::N3 * (
+           i2 + shape_type::N2 * (
+           i1 + shape_type::N1 * ( i0 )))));
+  }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6 ) const
+  {
+    return i6 + shape_type::N6 * (
+           i5 + shape_type::N5 * (
+           i4 + shape_type::N4 * (
+           i3 + shape_type::N3 * (
+           i2 + shape_type::N2 * (
+           i1 + shape_type::N1 * ( i0 ))))));
+  }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6, I7 const& i7 ) const
+  {
+    return i7 + shape_type::N7 * (
+           i6 + shape_type::N6 * (
+           i5 + shape_type::N5 * (
+           i4 + shape_type::N4 * (
+           i3 + shape_type::N3 * (
+           i2 + shape_type::N2 * (
+           i1 + shape_type::N1 * ( i0 )))))));
+  }
+};
+
+//----------------------------------------------------------------------------
+// LayoutRight AND ( 1 < rank AND 1 < rank_dynamic ) : has padding / striding
+template < class ShapeType >
+struct ViewOffset< ShapeType , LayoutRight
+                 , typename enable_if<( 1 < ShapeType::rank
+                                        &&
+                                        1 < ShapeType::rank_dynamic
+                                      )>::type >
+  : public ShapeType
+{
+  typedef size_t       size_type;
+  typedef ShapeType    shape_type;
+  typedef LayoutRight  array_layout ;
+
+  enum { has_padding = true };
+
+  size_type SR ;
+
+  // This subview must be 2 == rank and 2 == rank_dynamic
+  // due to only having stride #(rank-1).
+  // The source dimension #(rank-1) must be non-zero for stride-one leading dimension.
+  // At most one prior dimension can be non-zero.
+  // Return whether the subview introduced noncontiguity.
+  template< class S , class L >
+  KOKKOS_INLINE_FUNCTION
+  typename Impl::enable_if<( 2 == shape_type::rank &&
+                             2 == shape_type::rank_dynamic &&
+                             2 <= S::rank &&
+                             Impl::is_same<L,LayoutRight>::value
+                           ), bool >::type
+  assign_subview( const ViewOffset<S,L,void> & rhs
+                , const size_t n0
+                , const size_t n1
+                , const size_t n2
+                , const size_t n3
+                , const size_t n4
+                , const size_t n5
+                , const size_t n6
+                , const size_t n7
+                )
+    {
+      const size_type nR = S::rank == 2 ? n1 : (
+                           S::rank == 3 ? n2 : (
+                           S::rank == 4 ? n3 : (
+                           S::rank == 5 ? n4 : (
+                           S::rank == 6 ? n5 : (
+                           S::rank == 7 ? n6 : n7 )))));
+
+      // N0 = first non-zero-dimension
+      // N1 = last non-zero dimension
+      // SR = stride for second non-zero dimension
+      shape_type::N0 = 0 ;
+      shape_type::N1 = nR ;
+      SR = 0 ;
+
+      if      (                n0 ) { shape_type::N0 = n0 ; SR = rhs.stride_0(); }
+      else if ( 2 < S::rank && n1 ) { shape_type::N0 = n1 ; SR = rhs.stride_1(); }
+      else if ( 3 < S::rank && n2 ) { shape_type::N0 = n2 ; SR = rhs.stride_2(); }
+      else if ( 4 < S::rank && n3 ) { shape_type::N0 = n3 ; SR = rhs.stride_3(); }
+      else if ( 5 < S::rank && n4 ) { shape_type::N0 = n4 ; SR = rhs.stride_4(); }
+      else if ( 6 < S::rank && n5 ) { shape_type::N0 = n5 ; SR = rhs.stride_5(); }
+      else if ( 7 < S::rank && n6 ) { shape_type::N0 = n6 ; SR = rhs.stride_6(); }
+
+      // Introduce noncontiguous if change the last dimension
+      // or take a range of a dimension other than the second-to-last dimension.
+
+      return 2 == S::rank ? ( size_t(shape_type::N1) != size_t(rhs.N1) || 0 == n0 ) : (
+             3 == S::rank ? ( size_t(shape_type::N1) != size_t(rhs.N2) || 0 == n1 ) : (
+             4 == S::rank ? ( size_t(shape_type::N1) != size_t(rhs.N3) || 0 == n2 ) : (
+             5 == S::rank ? ( size_t(shape_type::N1) != size_t(rhs.N4) || 0 == n3 ) : (
+             6 == S::rank ? ( size_t(shape_type::N1) != size_t(rhs.N5) || 0 == n4 ) : (
+             7 == S::rank ? ( size_t(shape_type::N1) != size_t(rhs.N6) || 0 == n5 ) : (
+                            ( size_t(shape_type::N1) != size_t(rhs.N7) || 0 == n6 ) ))))));
+    }
+
+  template< unsigned R >
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n )
+    { assign_shape_dimension<R>( *this , n ); }
+
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n0 , size_t n1 , size_t n2 , size_t n3
+             , size_t n4 , size_t n5 , size_t n6 , size_t n7
+             , size_t = 0 )
+    {
+      shape_type::assign( *this , n0, n1, n2, n3, n4, n5, n6, n7 );
+      SR = size_type(shape_type::N1) * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ;
+    }
+
+  template< class ShapeRHS >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset< ShapeRHS , LayoutRight > & rhs
+             , typename enable_if<( int(ShapeRHS::rank) == int(shape_type::rank)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) <= int(shape_type::rank_dynamic)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) <= 1
+                                  )>::type * = 0 )
+    {
+      shape_type::assign( *this , rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 );
+      SR = shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ;
+    }
+
+  template< class ShapeRHS >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset< ShapeRHS , LayoutRight > & rhs
+             , typename enable_if<( int(ShapeRHS::rank) == int(shape_type::rank)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) <= int(shape_type::rank_dynamic)
+                                    &&
+                                    int(ShapeRHS::rank_dynamic) > 1
+                                  )>::type * = 0 )
+    {
+      shape_type::assign( *this , rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 );
+      SR = rhs.SR ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void set_padding()
+    {
+      enum { div   = MEMORY_ALIGNMENT / shape_type::scalar_size };
+      enum { mod   = MEMORY_ALIGNMENT % shape_type::scalar_size };
+      enum { align = 0 == mod ? div : 0 };
+
+      if ( align && MEMORY_ALIGNMENT_THRESHOLD * align < SR ) {
+
+        const size_type count_mod = SR % ( div ? div : 1 );
+
+        if ( count_mod ) { SR += align - count_mod ; }
+      }
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type cardinality() const
+    { return size_type(shape_type::N0) * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type capacity() const { return shape_type::N0 * SR ; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    {
+      size_type n = 1 ;
+      if ( 7 < shape_type::rank ) { s[7] = n ; n *= shape_type::N7 ; }
+      if ( 6 < shape_type::rank ) { s[6] = n ; n *= shape_type::N6 ; }
+      if ( 5 < shape_type::rank ) { s[5] = n ; n *= shape_type::N5 ; }
+      if ( 4 < shape_type::rank ) { s[4] = n ; n *= shape_type::N4 ; }
+      if ( 3 < shape_type::rank ) { s[3] = n ; n *= shape_type::N3 ; }
+      if ( 2 < shape_type::rank ) { s[2] = n ; n *= shape_type::N2 ; }
+      if ( 1 < shape_type::rank ) { s[1] = n ; n *= shape_type::N1 ; }
+      if ( 0 < shape_type::rank ) { s[0] = SR ; }
+      s[shape_type::rank] = SR * shape_type::N0 ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_7() const { return 1 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_6() const { return shape_type::N7 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_5() const { return shape_type::N7 * shape_type::N6 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_4() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_3() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 * shape_type::N4 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_2() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 * shape_type::N4 * shape_type::N3 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_1() const { return shape_type::N7 * shape_type::N6 * shape_type::N5 * shape_type::N4 * shape_type::N3 * shape_type::N2 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_0() const { return SR ; }
+
+  // rank 2
+  template <typename I0, typename I1>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1 ) const
+    {
+      return i1 + i0 * SR ;
+    }
+
+  template <typename I0, typename I1, typename I2>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 ) const
+    {
+      return i2 + shape_type::N2 * ( i1 ) +
+             i0 * SR ;
+    }
+
+  template <typename I0, typename I1, typename I2, typename I3>
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3 ) const
+    {
+      return i3 + shape_type::N3 * (
+             i2 + shape_type::N2 * ( i1 )) +
+             i0 * SR ;
+    }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4 ) const
+    {
+      return i4 + shape_type::N4 * (
+             i3 + shape_type::N3 * (
+             i2 + shape_type::N2 * ( i1 ))) +
+             i0 * SR ;
+    }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5 ) const
+  {
+    return i5 + shape_type::N5 * (
+           i4 + shape_type::N4 * (
+           i3 + shape_type::N3 * (
+           i2 + shape_type::N2 * ( i1 )))) +
+           i0 * SR ;
+  }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6 ) const
+  {
+    return i6 + shape_type::N6 * (
+           i5 + shape_type::N5 * (
+           i4 + shape_type::N4 * (
+           i3 + shape_type::N3 * (
+           i2 + shape_type::N2 * ( i1 ))))) +
+           i0 * SR ;
+  }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  size_type operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6, I7 const& i7 ) const
+  {
+    return i7 + shape_type::N7 * (
+           i6 + shape_type::N6 * (
+           i5 + shape_type::N5 * (
+           i4 + shape_type::N4 * (
+           i3 + shape_type::N3 * (
+           i2 + shape_type::N2 * ( i1 )))))) +
+           i0 * SR ;
+  }
+};
+
+//----------------------------------------------------------------------------
+// LayoutStride : 
+template < class ShapeType >
+struct ViewOffset< ShapeType , LayoutStride
+                 , typename enable_if<( 0 < ShapeType::rank )>::type >
+  : public ShapeType
+{
+  typedef size_t        size_type;
+  typedef ShapeType     shape_type;
+  typedef LayoutStride  array_layout ;
+
+  size_type S[ shape_type::rank + 1 ];
+
+  template< class SType , class L >
+  KOKKOS_INLINE_FUNCTION
+  bool assign_subview( const ViewOffset<SType,L,void> & rhs
+                     , const size_type n0
+                     , const size_type n1
+                     , const size_type n2
+                     , const size_type n3
+                     , const size_type n4
+                     , const size_type n5
+                     , const size_type n6
+                     , const size_type n7
+                     )
+    {
+      shape_type::assign( *this, 0,0,0,0, 0,0,0,0 );
+
+      for ( int i = 0 ; i < int(shape_type::rank+1) ; ++i ) { S[i] = 0 ; }
+
+      // preconditions:
+      //  shape_type::rank <= rhs.rank
+      //  shape_type::rank == count of nonzero( rhs_dim[i] )
+      size_type dim[8] = { n0 , n1 , n2 , n3 , n4 , n5 , n6 , n7 };
+      size_type str[ SType::rank + 1 ];
+
+      rhs.stride( str );
+
+      // contract the zero-dimensions
+      int r = 0 ;
+      for ( int i = 0 ; i < int(SType::rank) ; ++i ) {
+        if ( 0 != dim[i] ) {
+          dim[r] = dim[i] ;
+          str[r] = str[i] ;
+          ++r ;
+        }
+      }
+
+      if ( int(shape_type::rank) == r ) {
+        // The shape is non-zero
+        for ( int i = 0 ; i < int(shape_type::rank) ; ++i ) {
+          const size_type cap = dim[i] * ( S[i] = str[i] );
+          if ( S[ shape_type::rank ] < cap ) S[ shape_type::rank ] = cap ;
+        }
+        // set the contracted nonzero dimensions
+        shape_type::assign( *this, dim[0], dim[1], dim[2], dim[3], dim[4], dim[5], dim[6], dim[7] );
+      }
+
+      return true ; // definitely noncontiguous
+    }
+
+  template< unsigned R >
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t n )
+    { assign_shape_dimension<R>( *this , n ); }
+
+  template< class ShapeRHS , class Layout >
+  KOKKOS_INLINE_FUNCTION
+  void assign( const ViewOffset<ShapeRHS,Layout> & rhs
+             , typename enable_if<( int(ShapeRHS::rank) == int(shape_type::rank) )>::type * = 0 )
+    {
+      rhs.stride(S);
+      shape_type::assign( *this, rhs.N0, rhs.N1, rhs.N2, rhs.N3, rhs.N4, rhs.N5, rhs.N6, rhs.N7 );
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void assign( const LayoutStride & layout )
+  {
+    size_type max = 0 ;
+    for ( int i = 0 ; i < shape_type::rank ; ++i ) {
+      S[i] = layout.stride[i] ;
+      const size_type m = layout.dimension[i] * S[i] ;
+      if ( max < m ) { max = m ; }
+    }
+    S[ shape_type::rank ] = max ;
+    shape_type::assign( *this, layout.dimension[0], layout.dimension[1],
+                               layout.dimension[2], layout.dimension[3],
+                               layout.dimension[4], layout.dimension[5],
+                               layout.dimension[6], layout.dimension[7] );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void assign( size_t s0 , size_t s1 , size_t s2 , size_t s3
+             , size_t s4 , size_t s5 , size_t s6 , size_t s7
+             , size_t s8 )
+    {
+      const size_t str[9] = { s0, s1, s2, s3, s4, s5, s6, s7, s8 };
+
+      // Last argument is the total length.
+      // Total length must be non-zero.
+      // All strides must be non-zero and less than total length.
+      bool ok = 0 < str[ shape_type::rank ] ;
+
+      for ( int i = 0 ; ( i < shape_type::rank ) &&
+                        ( ok = 0 < str[i] && str[i] < str[ shape_type::rank ] ); ++i );
+
+      if ( ok ) {
+        size_t dim[8] = { 1,1,1,1,1,1,1,1 }; 
+        int iorder[9] = { 0,0,0,0,0,0,0,0,0 }; 
+
+        // Ordering of strides smallest to largest.
+        for ( int i = 1 ; i < shape_type::rank ; ++i ) {
+          int j = i ;
+          for ( ; 0 < j && str[i] < str[ iorder[j-1] ] ; --j ) {
+            iorder[j] = iorder[j-1] ;
+          }
+          iorder[j] = i ;
+        }
+
+        // Last argument is the total length.
+        iorder[ shape_type::rank ] = shape_type::rank ;
+
+        // Determine dimension associated with each stride.
+        // Guarantees non-overlap by truncating dimension
+        // if ( 0 != str[ iorder[i+1] ] % str[ iorder[i] ] )
+        for ( int i = 0 ; i < shape_type::rank ; ++i ) {
+          dim[ iorder[i] ] = str[ iorder[i+1] ] / str[ iorder[i] ] ;
+        }
+
+        // Assign dimensions and strides:
+        shape_type::assign( *this, dim[0], dim[1], dim[2], dim[3], dim[4], dim[5], dim[6], dim[7] );
+        for ( int i = 0 ; i <= shape_type::rank ; ++i ) { S[i] = str[i] ; }
+      }
+      else {
+        shape_type::assign(*this,0,0,0,0,0,0,0,0);
+        for ( int i = 0 ; i <= shape_type::rank ; ++i ) { S[i] = 0 ; }
+      }
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void set_padding() {}
+
+  KOKKOS_INLINE_FUNCTION
+  size_type cardinality() const
+    { return shape_type::N0 * shape_type::N1 * shape_type::N2 * shape_type::N3 * shape_type::N4 * shape_type::N5 * shape_type::N6 * shape_type::N7 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type capacity() const { return S[ shape_type::rank ]; }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void stride( iType * const s ) const
+    { for ( int i = 0 ; i <= shape_type::rank ; ++i ) { s[i] = S[i] ; } }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_0() const { return S[0] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_1() const { return S[1] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_2() const { return S[2] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_3() const { return S[3] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_4() const { return S[4] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_5() const { return S[5] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_6() const { return S[6] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_type stride_7() const { return S[7] ; }
+
+  // rank 1
+  template <typename I0 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<I0>::value) && (shape_type::rank==1),size_type>::type
+    operator()( I0 const& i0) const
+    {
+      return i0 * S[0] ;
+    }
+
+  // rank 2
+  template <typename I0, typename I1>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<I0>::value) && (shape_type::rank==2),size_type>::type
+    operator()( I0 const& i0, I1 const& i1 ) const
+    {
+      return i0 * S[0] + i1 * S[1] ;
+    }
+
+  template <typename I0, typename I1, typename I2>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<I0>::value) && (shape_type::rank==3),size_type>::type
+    operator()( I0 const& i0, I1 const& i1, I2 const& i2 ) const
+    {
+      return i0 * S[0] + i1 * S[1] + i2 * S[2] ;
+    }
+
+  template <typename I0, typename I1, typename I2, typename I3>
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<I0>::value) && (shape_type::rank==4),size_type>::type
+    operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3 ) const
+    {
+      return i0 * S[0] + i1 * S[1] + i2 * S[2] + i3 * S[3] ;
+    }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<I0>::value) && (shape_type::rank==5),size_type>::type
+    operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4 ) const
+    {
+      return i0 * S[0] + i1 * S[1] + i2 * S[2] + i3 * S[3] + i4 * S[4] ;
+    }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<I0>::value) && (shape_type::rank==6),size_type>::type
+    operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5 ) const
+    {
+      return i0 * S[0] + i1 * S[1] + i2 * S[2] + i3 * S[3] + i4 * S[4] + i5 * S[5] ;
+    }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<I0>::value) && (shape_type::rank==7),size_type>::type
+    operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6 ) const
+    {
+      return i0 * S[0] + i1 * S[1] + i2 * S[2] + i3 * S[3] + i4 * S[4] + i5 * S[5] + i6 * S[6] ;
+    }
+
+  template < typename I0, typename I1, typename I2, typename I3
+            ,typename I4, typename I5, typename I6, typename I7 >
+  KOKKOS_FORCEINLINE_FUNCTION
+  typename std::enable_if< (std::is_integral<I0>::value) && (shape_type::rank==8),size_type>::type
+    operator()( I0 const& i0, I1 const& i1, I2 const& i2 , I3 const& i3, I4 const& i4, I5 const& i5, I6 const& i6, I7 const& i7 ) const
+    {
+      return i0 * S[0] + i1 * S[1] + i2 * S[2] + i3 * S[3] + i4 * S[4] + i5 * S[5] + i6 * S[6] + i7 * S[7] ;
+    }
+};
+
+//----------------------------------------------------------------------------
+
+template< class T >
+struct ViewOffsetRange {
+
+  enum { OK_integral_type = Impl::StaticAssert< Impl::is_integral<T>::value >::value };
+
+  enum { is_range = false };
+
+  KOKKOS_INLINE_FUNCTION static
+  size_t dimension( size_t const , T const & ) { return 0 ; }
+
+  KOKKOS_INLINE_FUNCTION static
+  size_t begin( T const & i ) { return size_t(i) ; }
+};
+
+template<>
+struct ViewOffsetRange<void> {
+  enum { is_range = false };
+};
+
+template<>
+struct ViewOffsetRange< Kokkos::ALL > {
+  enum { is_range = true };
+
+  KOKKOS_INLINE_FUNCTION static
+  size_t dimension( size_t const n , ALL const & ) { return n ; }
+
+  KOKKOS_INLINE_FUNCTION static
+  size_t begin( ALL const & ) { return 0 ; }
+};
+
+template< typename iType >
+struct ViewOffsetRange< std::pair<iType,iType> > {
+
+  enum { OK_integral_type = Impl::StaticAssert< Impl::is_integral<iType>::value >::value };
+
+  enum { is_range = true };
+
+  KOKKOS_INLINE_FUNCTION static
+  size_t dimension( size_t const n , std::pair<iType,iType> const & r )
+    { return ( size_t(r.first) < size_t(r.second) && size_t(r.second) <= n ) ? size_t(r.second) - size_t(r.first) : 0 ; }
+
+  KOKKOS_INLINE_FUNCTION static
+  size_t begin( std::pair<iType,iType> const & r ) { return size_t(r.first) ; }
+};
+
+template< typename iType >
+struct ViewOffsetRange< Kokkos::pair<iType,iType> > {
+
+  enum { OK_integral_type = Impl::StaticAssert< Impl::is_integral<iType>::value >::value };
+
+  enum { is_range = true };
+
+  KOKKOS_INLINE_FUNCTION static
+  size_t dimension( size_t const n , Kokkos::pair<iType,iType> const & r )
+    { return ( size_t(r.first) < size_t(r.second) && size_t(r.second) <= n ) ? size_t(r.second) - size_t(r.first) : 0 ; }
+
+  KOKKOS_INLINE_FUNCTION static
+  size_t begin( Kokkos::pair<iType,iType> const & r ) { return size_t(r.first) ; }
+};
+
+}} // namespace Kokkos::Impl
+
+#endif //KOKKOS_VIEWOFFSET_HPP
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_ViewSupport.hpp b/lib/kokkos/core/src/impl/Kokkos_ViewSupport.hpp
new file mode 100644
index 0000000000..8b63039f57
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_ViewSupport.hpp
@@ -0,0 +1,393 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_VIEWSUPPORT_HPP
+#define KOKKOS_VIEWSUPPORT_HPP
+
+#include <algorithm>
+#include <Kokkos_ExecPolicy.hpp>
+#include <impl/Kokkos_Shape.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+/** \brief  Evaluate if LHS = RHS view assignment is allowed. */
+template< class ViewLHS , class ViewRHS >
+struct ViewAssignable
+{
+  // Same memory space.
+  // Same value type.
+  // Compatible 'const' qualifier
+  // Cannot assign managed = unmannaged
+  enum { assignable_value =
+    ( is_same< typename ViewLHS::value_type ,
+               typename ViewRHS::value_type >::value
+      ||
+      is_same< typename ViewLHS::value_type ,
+               typename ViewRHS::const_value_type >::value )
+    &&
+    is_same< typename ViewLHS::memory_space ,
+             typename ViewRHS::memory_space >::value
+    &&
+    ( ! ( ViewLHS::is_managed && ! ViewRHS::is_managed ) )
+  };
+
+  enum { assignable_shape =
+    // Compatible shape and matching layout:
+    ( ShapeCompatible< typename ViewLHS::shape_type ,
+                       typename ViewRHS::shape_type >::value
+      &&
+      is_same< typename ViewLHS::array_layout ,
+               typename ViewRHS::array_layout >::value )
+    ||
+    // Matching layout, same rank, and LHS dynamic rank
+    ( is_same< typename ViewLHS::array_layout ,
+               typename ViewRHS::array_layout >::value
+      &&
+      int(ViewLHS::rank) == int(ViewRHS::rank)
+      &&
+      int(ViewLHS::rank) == int(ViewLHS::rank_dynamic) )
+    ||
+    // Both rank-0, any shape and layout
+    ( int(ViewLHS::rank) == 0 && int(ViewRHS::rank) == 0 )
+    ||
+    // Both rank-1 and LHS is dynamic rank-1, any shape and layout
+    ( int(ViewLHS::rank) == 1 && int(ViewRHS::rank) == 1 &&
+      int(ViewLHS::rank_dynamic) == 1 )
+    };
+
+  enum { value = assignable_value && assignable_shape };
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class ExecSpace , class Type , bool Initialize >
+struct ViewDefaultConstruct
+{ ViewDefaultConstruct( Type * , size_t ) {} };
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class OutputView , class InputView  , unsigned Rank = OutputView::Rank >
+struct ViewRemap
+{
+  typedef typename OutputView::size_type   size_type ;
+
+  const OutputView output ;
+  const InputView  input ;
+  const size_type n0 ;
+  const size_type n1 ;
+  const size_type n2 ;
+  const size_type n3 ;
+  const size_type n4 ;
+  const size_type n5 ;
+  const size_type n6 ;
+  const size_type n7 ;
+
+  ViewRemap( const OutputView & arg_out , const InputView & arg_in )
+    : output( arg_out ), input( arg_in )
+    , n0( std::min( (size_t)arg_out.dimension_0() , (size_t)arg_in.dimension_0() ) )
+    , n1( std::min( (size_t)arg_out.dimension_1() , (size_t)arg_in.dimension_1() ) )
+    , n2( std::min( (size_t)arg_out.dimension_2() , (size_t)arg_in.dimension_2() ) )
+    , n3( std::min( (size_t)arg_out.dimension_3() , (size_t)arg_in.dimension_3() ) )
+    , n4( std::min( (size_t)arg_out.dimension_4() , (size_t)arg_in.dimension_4() ) )
+    , n5( std::min( (size_t)arg_out.dimension_5() , (size_t)arg_in.dimension_5() ) )
+    , n6( std::min( (size_t)arg_out.dimension_6() , (size_t)arg_in.dimension_6() ) )
+    , n7( std::min( (size_t)arg_out.dimension_7() , (size_t)arg_in.dimension_7() ) )
+    {
+      typedef typename OutputView::execution_space execution_space ;
+      Kokkos::RangePolicy< execution_space > range( 0 , n0 );
+      parallel_for( range , *this );
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i0 ) const
+  {
+    for ( size_type i1 = 0 ; i1 < n1 ; ++i1 ) {
+    for ( size_type i2 = 0 ; i2 < n2 ; ++i2 ) {
+    for ( size_type i3 = 0 ; i3 < n3 ; ++i3 ) {
+    for ( size_type i4 = 0 ; i4 < n4 ; ++i4 ) {
+    for ( size_type i5 = 0 ; i5 < n5 ; ++i5 ) {
+    for ( size_type i6 = 0 ; i6 < n6 ; ++i6 ) {
+    for ( size_type i7 = 0 ; i7 < n7 ; ++i7 ) {
+      output.at(i0,i1,i2,i3,i4,i5,i6,i7) = input.at(i0,i1,i2,i3,i4,i5,i6,i7);
+    }}}}}}}
+  }
+};
+
+template< class OutputView , class InputView  >
+struct ViewRemap< OutputView ,  InputView , 0 >
+{
+  typedef typename OutputView::value_type   value_type ;
+  typedef typename OutputView::memory_space dst_space ;
+  typedef typename InputView ::memory_space src_space ;
+
+  ViewRemap( const OutputView & arg_out , const InputView & arg_in )
+  {
+    DeepCopy< dst_space , src_space >( arg_out.ptr_on_device() ,
+                                       arg_in.ptr_on_device() ,
+                                       sizeof(value_type) );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< class ExecSpace , class Type >
+struct ViewDefaultConstruct< ExecSpace , Type , true >
+{
+  Type * const m_ptr ;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator()( const typename ExecSpace::size_type& i ) const
+    { m_ptr[i] = Type(); }
+
+  ViewDefaultConstruct( Type * pointer , size_t capacity )
+    : m_ptr( pointer )
+    {
+      Kokkos::RangePolicy< ExecSpace > range( 0 , capacity );
+      parallel_for( range , *this );
+      ExecSpace::fence();
+    }
+};
+
+template< class OutputView , unsigned Rank = OutputView::Rank ,
+          class Enabled = void >
+struct ViewFill
+{
+  typedef typename OutputView::const_value_type  const_value_type ;
+  typedef typename OutputView::size_type         size_type ;
+
+  const OutputView output ;
+  const_value_type input ;
+
+  ViewFill( const OutputView & arg_out , const_value_type & arg_in )
+    : output( arg_out ), input( arg_in )
+    {
+      typedef typename OutputView::execution_space execution_space ;
+      Kokkos::RangePolicy< execution_space > range( 0 , output.dimension_0() );
+      parallel_for( range , *this );
+      execution_space::fence();
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i0 ) const
+  {
+    for ( size_type i1 = 0 ; i1 < output.dimension_1() ; ++i1 ) {
+    for ( size_type i2 = 0 ; i2 < output.dimension_2() ; ++i2 ) {
+    for ( size_type i3 = 0 ; i3 < output.dimension_3() ; ++i3 ) {
+    for ( size_type i4 = 0 ; i4 < output.dimension_4() ; ++i4 ) {
+    for ( size_type i5 = 0 ; i5 < output.dimension_5() ; ++i5 ) {
+    for ( size_type i6 = 0 ; i6 < output.dimension_6() ; ++i6 ) {
+    for ( size_type i7 = 0 ; i7 < output.dimension_7() ; ++i7 ) {
+      output.at(i0,i1,i2,i3,i4,i5,i6,i7) = input ;
+    }}}}}}}
+  }
+};
+
+template< class OutputView >
+struct ViewFill< OutputView , 0 >
+{
+  typedef typename OutputView::const_value_type  const_value_type ;
+  typedef typename OutputView::memory_space      dst_space ;
+
+  ViewFill( const OutputView & arg_out , const_value_type & arg_in )
+  {
+    DeepCopy< dst_space , dst_space >( arg_out.ptr_on_device() , & arg_in ,
+                                       sizeof(const_value_type) );
+  }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+struct ViewAllocateWithoutInitializing {
+
+  const std::string label ;
+
+  ViewAllocateWithoutInitializing() : label() {}
+  explicit ViewAllocateWithoutInitializing( const std::string & arg_label ) : label( arg_label ) {}
+  explicit ViewAllocateWithoutInitializing( const char * const  arg_label ) : label( arg_label ) {}
+};
+
+struct ViewAllocate {
+
+  const std::string  label ;
+
+  ViewAllocate() : label() {}
+  ViewAllocate( const std::string & arg_label ) : label( arg_label ) {}
+  ViewAllocate( const char * const  arg_label ) : label( arg_label ) {}
+};
+
+}
+
+namespace Kokkos {
+namespace Impl {
+
+template< class Traits , class AllocationProperties , class Enable = void >
+struct ViewAllocProp : public Kokkos::Impl::false_type {};
+
+template< class Traits >
+struct ViewAllocProp< Traits , Kokkos::ViewAllocate
+  , typename Kokkos::Impl::enable_if<(
+      Traits::is_managed && ! Kokkos::Impl::is_const< typename Traits::value_type >::value
+    )>::type >
+  : public Kokkos::Impl::true_type
+{
+  typedef size_t               size_type ;
+  typedef const ViewAllocate & property_type ;
+
+  enum { Initialize = true };
+  enum { AllowPadding = false };
+
+  inline
+  static const std::string & label( property_type p ) { return p.label ; }
+};
+
+template< class Traits >
+struct ViewAllocProp< Traits , std::string
+  , typename Kokkos::Impl::enable_if<(
+      Traits::is_managed && ! Kokkos::Impl::is_const< typename Traits::value_type >::value
+    )>::type >
+  : public Kokkos::Impl::true_type
+{
+  typedef size_t              size_type ;
+  typedef const std::string & property_type ;
+
+  enum { Initialize = true };
+  enum { AllowPadding = false };
+
+  inline
+  static const std::string & label( property_type s ) { return s ; }
+};
+
+template< class Traits , unsigned N >
+struct ViewAllocProp< Traits , char[N]
+  , typename Kokkos::Impl::enable_if<(
+      Traits::is_managed && ! Kokkos::Impl::is_const< typename Traits::value_type >::value
+    )>::type >
+  : public Kokkos::Impl::true_type
+{
+private:
+  typedef char label_type[N] ;
+public:
+
+  typedef size_t             size_type ;
+  typedef const label_type & property_type ;
+
+  enum { Initialize = true };
+  enum { AllowPadding = false };
+
+  inline
+  static std::string label( property_type s ) { return std::string(s) ; }
+};
+
+template< class Traits >
+struct ViewAllocProp< Traits , Kokkos::ViewAllocateWithoutInitializing
+  , typename Kokkos::Impl::enable_if<(
+      Traits::is_managed && ! Kokkos::Impl::is_const< typename Traits::value_type >::value
+    )>::type >
+  : public Kokkos::Impl::true_type
+{
+  typedef size_t size_type ;
+  typedef const Kokkos::ViewAllocateWithoutInitializing & property_type ;
+
+  enum { Initialize = false };
+  enum { AllowPadding = false };
+
+  inline
+  static std::string label( property_type s ) { return s.label ; }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class Traits , class PointerProperties , class Enable = void >
+struct ViewRawPointerProp : public Kokkos::Impl::false_type {};
+
+template< class Traits , typename T >
+struct ViewRawPointerProp< Traits , T ,
+  typename Kokkos::Impl::enable_if<(
+    Impl::is_same< T , typename Traits::value_type >::value ||
+    Impl::is_same< T , typename Traits::non_const_value_type >::value
+  )>::type >
+  : public Kokkos::Impl::true_type
+{
+  typedef size_t size_type ;
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_VIEWSUPPORT_HPP */
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_ViewTileLeft.hpp b/lib/kokkos/core/src/impl/Kokkos_ViewTileLeft.hpp
new file mode 100644
index 0000000000..61d2e35702
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_ViewTileLeft.hpp
@@ -0,0 +1,56 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_VIEWTILELEFT_HPP
+#define KOKKOS_VIEWTILELEFT_HPP
+
+#include <impl/KokkosExp_ViewTile.hpp>
+
+namespace Kokkos {
+
+using Kokkos::Experimental::tile_subview ;
+
+}
+
+#endif /* #ifndef KOKKOS_VIEWTILELEFT_HPP */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_Volatile_Load.hpp b/lib/kokkos/core/src/impl/Kokkos_Volatile_Load.hpp
new file mode 100644
index 0000000000..420ee63891
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_Volatile_Load.hpp
@@ -0,0 +1,242 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#if defined( KOKKOS_ATOMIC_HPP ) && ! defined( KOKKOS_VOLATILE_LOAD )
+#define KOKKOS_VOLATILE_LOAD
+
+#if defined( __GNUC__ ) /* GNU C   */ || \
+    defined( __GNUG__ ) /* GNU C++ */ || \
+    defined( __clang__ )
+
+#define KOKKOS_MAY_ALIAS __attribute__((__may_alias__))
+
+#else
+
+#define KOKKOS_MAY_ALIAS
+
+#endif
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+template <typename T>
+KOKKOS_FORCEINLINE_FUNCTION
+T volatile_load(T const volatile * const src_ptr)
+{
+  typedef uint64_t KOKKOS_MAY_ALIAS T64;
+  typedef uint32_t KOKKOS_MAY_ALIAS T32;
+  typedef uint16_t KOKKOS_MAY_ALIAS T16;
+  typedef uint8_t  KOKKOS_MAY_ALIAS T8;
+
+  enum {
+    NUM_8  = sizeof(T),
+    NUM_16 = NUM_8 / 2,
+    NUM_32 = NUM_8 / 4,
+    NUM_64 = NUM_8 / 8
+  };
+
+  union {
+    T   const volatile * const ptr;
+    T64 const volatile * const ptr64;
+    T32 const volatile * const ptr32;
+    T16 const volatile * const ptr16;
+    T8  const volatile * const ptr8;
+  } src = {src_ptr};
+
+  T result;
+
+  union {
+    T   * const ptr;
+    T64 * const ptr64;
+    T32 * const ptr32;
+    T16 * const ptr16;
+    T8  * const ptr8;
+  } dst = {&result};
+
+  for (int i=0; i < NUM_64; ++i) {
+    dst.ptr64[i] = src.ptr64[i];
+  }
+
+  if ( NUM_64*2 < NUM_32 ) {
+    dst.ptr32[NUM_64*2] = src.ptr32[NUM_64*2];
+  }
+
+  if ( NUM_32*2 < NUM_16 ) {
+    dst.ptr16[NUM_32*2] = src.ptr16[NUM_32*2];
+  }
+
+  if ( NUM_16*2 < NUM_8 ) {
+    dst.ptr8[NUM_16*2] = src.ptr8[NUM_16*2];
+  }
+
+  return result;
+}
+
+template <typename T>
+KOKKOS_FORCEINLINE_FUNCTION
+void volatile_store(T volatile * const dst_ptr, T const volatile * const src_ptr)
+{
+  typedef uint64_t KOKKOS_MAY_ALIAS T64;
+  typedef uint32_t KOKKOS_MAY_ALIAS T32;
+  typedef uint16_t KOKKOS_MAY_ALIAS T16;
+  typedef uint8_t  KOKKOS_MAY_ALIAS T8;
+
+  enum {
+    NUM_8  = sizeof(T),
+    NUM_16 = NUM_8 / 2,
+    NUM_32 = NUM_8 / 4,
+    NUM_64 = NUM_8 / 8
+  };
+
+  union {
+    T   const volatile * const ptr;
+    T64 const volatile * const ptr64;
+    T32 const volatile * const ptr32;
+    T16 const volatile * const ptr16;
+    T8  const volatile * const ptr8;
+  } src = {src_ptr};
+
+  union {
+    T   volatile * const ptr;
+    T64 volatile * const ptr64;
+    T32 volatile * const ptr32;
+    T16 volatile * const ptr16;
+    T8  volatile * const ptr8;
+  } dst = {dst_ptr};
+
+  for (int i=0; i < NUM_64; ++i) {
+    dst.ptr64[i] = src.ptr64[i];
+  }
+
+  if ( NUM_64*2 < NUM_32 ) {
+    dst.ptr32[NUM_64*2] = src.ptr32[NUM_64*2];
+  }
+
+  if ( NUM_32*2 < NUM_16 ) {
+    dst.ptr16[NUM_32*2] = src.ptr16[NUM_32*2];
+  }
+
+  if ( NUM_16*2 < NUM_8 ) {
+    dst.ptr8[NUM_16*2] = src.ptr8[NUM_16*2];
+  }
+}
+
+template <typename T>
+KOKKOS_FORCEINLINE_FUNCTION
+void volatile_store(T volatile * const dst_ptr, T const * const src_ptr)
+{
+  typedef uint64_t KOKKOS_MAY_ALIAS T64;
+  typedef uint32_t KOKKOS_MAY_ALIAS T32;
+  typedef uint16_t KOKKOS_MAY_ALIAS T16;
+  typedef uint8_t  KOKKOS_MAY_ALIAS T8;
+
+  enum {
+    NUM_8  = sizeof(T),
+    NUM_16 = NUM_8 / 2,
+    NUM_32 = NUM_8 / 4,
+    NUM_64 = NUM_8 / 8
+  };
+
+  union {
+    T   const * const ptr;
+    T64 const * const ptr64;
+    T32 const * const ptr32;
+    T16 const * const ptr16;
+    T8  const * const ptr8;
+  } src = {src_ptr};
+
+  union {
+    T   volatile * const ptr;
+    T64 volatile * const ptr64;
+    T32 volatile * const ptr32;
+    T16 volatile * const ptr16;
+    T8  volatile * const ptr8;
+  } dst = {dst_ptr};
+
+  for (int i=0; i < NUM_64; ++i) {
+    dst.ptr64[i] = src.ptr64[i];
+  }
+
+  if ( NUM_64*2 < NUM_32 ) {
+    dst.ptr32[NUM_64*2] = src.ptr32[NUM_64*2];
+  }
+
+  if ( NUM_32*2 < NUM_16 ) {
+    dst.ptr16[NUM_32*2] = src.ptr16[NUM_32*2];
+  }
+
+  if ( NUM_16*2 < NUM_8 ) {
+    dst.ptr8[NUM_16*2] = src.ptr8[NUM_16*2];
+  }
+}
+
+template <typename T>
+KOKKOS_FORCEINLINE_FUNCTION
+void volatile_store(T volatile * dst_ptr, T const volatile & src)
+{ volatile_store(dst_ptr, &src); }
+
+template <typename T>
+KOKKOS_FORCEINLINE_FUNCTION
+void volatile_store(T volatile * dst_ptr, T const & src)
+{ volatile_store(dst_ptr, &src); }
+
+template <typename T>
+KOKKOS_FORCEINLINE_FUNCTION
+T safe_load(T const * const ptr)
+{
+#if !defined( __MIC__ )
+  return *ptr;
+#else
+  return volatile_load(ptr);
+#endif
+}
+
+} // namespace kokkos
+
+#undef KOKKOS_MAY_ALIAS
+
+#endif
+
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_hwloc.cpp b/lib/kokkos/core/src/impl/Kokkos_hwloc.cpp
new file mode 100644
index 0000000000..cb561f711c
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_hwloc.cpp
@@ -0,0 +1,726 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#define DEBUG_PRINT 0
+
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+
+#include <Kokkos_Macros.hpp>
+#include <Kokkos_hwloc.hpp>
+#include <impl/Kokkos_Error.hpp>
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace hwloc {
+
+/* Return 0 if asynchronous, 1 if synchronous and include process. */
+unsigned thread_mapping( const char * const label ,
+                         const bool allow_async ,
+                         unsigned & thread_count ,
+                         unsigned & use_numa_count ,
+                         unsigned & use_cores_per_numa ,
+                         std::pair<unsigned,unsigned> threads_coord[] )
+{
+  const bool     hwloc_avail            = Kokkos::hwloc::available();
+  const unsigned avail_numa_count       = hwloc_avail ? hwloc::get_available_numa_count() : 1 ;
+  const unsigned avail_cores_per_numa   = hwloc_avail ? hwloc::get_available_cores_per_numa() : thread_count ;
+  const unsigned avail_threads_per_core = hwloc_avail ? hwloc::get_available_threads_per_core() : 1 ;
+
+  // (numa,core) coordinate of the process:
+  const std::pair<unsigned,unsigned> proc_coord = Kokkos::hwloc::get_this_thread_coordinate();
+
+  //------------------------------------------------------------------------
+  // Defaults for unspecified inputs:
+
+  if ( ! use_numa_count ) {
+    // Default to use all NUMA regions
+    use_numa_count = ! thread_count ? avail_numa_count : (
+                       thread_count < avail_numa_count ? thread_count : avail_numa_count );
+  }
+
+  if ( ! use_cores_per_numa ) {
+    // Default to use all but one core if asynchronous, all cores if synchronous.
+    const unsigned threads_per_numa = thread_count / use_numa_count ;
+
+    use_cores_per_numa = ! threads_per_numa ? avail_cores_per_numa - ( allow_async ? 1 : 0 ) : (
+                           threads_per_numa < avail_cores_per_numa ? threads_per_numa : avail_cores_per_numa );
+  }
+
+  if ( ! thread_count ) {
+    thread_count = use_numa_count * use_cores_per_numa * avail_threads_per_core ;
+  }
+
+  //------------------------------------------------------------------------
+  // Input verification:
+
+  const bool valid_numa      = use_numa_count <= avail_numa_count ;
+  const bool valid_cores     = use_cores_per_numa &&
+                               use_cores_per_numa <= avail_cores_per_numa ;
+  const bool valid_threads   = thread_count &&
+                               thread_count <= use_numa_count * use_cores_per_numa * avail_threads_per_core ;
+  const bool balanced_numa   = ! ( thread_count % use_numa_count );
+  const bool balanced_cores  = ! ( thread_count % ( use_numa_count * use_cores_per_numa ) );
+
+  const bool valid_input = valid_numa && valid_cores && valid_threads && balanced_numa && balanced_cores ;
+
+  if ( ! valid_input ) {
+
+    std::ostringstream msg ;
+
+    msg << label << " HWLOC ERROR(s)" ;
+
+    if ( ! valid_threads ) {
+      msg << " : thread_count(" << thread_count
+          << ") exceeds capacity("
+          << use_numa_count * use_cores_per_numa * avail_threads_per_core
+          << ")" ;
+    }
+    if ( ! valid_numa ) {
+      msg << " : use_numa_count(" << use_numa_count
+          << ") exceeds capacity(" << avail_numa_count << ")" ;
+    }
+    if ( ! valid_cores ) {
+      msg << " : use_cores_per_numa(" << use_cores_per_numa
+          << ") exceeds capacity(" << avail_cores_per_numa << ")" ;
+    }
+    if ( ! balanced_numa ) {
+      msg << " : thread_count(" << thread_count
+          << ") imbalanced among numa(" << use_numa_count << ")" ;
+    }
+    if ( ! balanced_cores ) {
+      msg << " : thread_count(" << thread_count
+          << ") imbalanced among cores(" << use_numa_count * use_cores_per_numa << ")" ;
+    }
+
+    Kokkos::Impl::throw_runtime_exception( msg.str() );
+  }
+
+  const unsigned thread_spawn_synchronous =
+    ( allow_async &&
+      1 < thread_count &&
+      ( use_numa_count     < avail_numa_count ||
+        use_cores_per_numa < avail_cores_per_numa ) )
+     ? 0 /* asyncronous */
+     : 1 /* synchronous, threads_coord[0] is process core */ ;
+
+  // Determine binding coordinates for to-be-spawned threads so that
+  // threads may be bound to cores as they are spawned.
+
+  const unsigned threads_per_core = thread_count / ( use_numa_count * use_cores_per_numa );
+
+  if ( thread_spawn_synchronous ) {
+    // Working synchronously and include process core as threads_coord[0].
+    // Swap the NUMA coordinate of the process core with 0
+    // Swap the CORE coordinate of the process core with 0
+    for ( unsigned i = 0 , inuma = avail_numa_count - use_numa_count ; inuma < avail_numa_count ; ++inuma ) {
+      const unsigned numa_coord = 0 == inuma ? proc_coord.first : ( proc_coord.first == inuma ? 0 : inuma );
+      for ( unsigned icore = avail_cores_per_numa - use_cores_per_numa ; icore < avail_cores_per_numa ; ++icore ) {
+        const unsigned core_coord = 0 == icore ? proc_coord.second : ( proc_coord.second == icore ? 0 : icore );
+        for ( unsigned ith = 0 ; ith < threads_per_core ; ++ith , ++i ) {
+          threads_coord[i].first  = numa_coord ;
+          threads_coord[i].second = core_coord ;
+        }
+      }
+    }
+  }
+  else if ( use_numa_count < avail_numa_count ) {
+    // Working asynchronously and omit the process' NUMA region from the pool.
+    // Swap the NUMA coordinate of the process core with ( ( avail_numa_count - use_numa_count ) - 1 )
+    const unsigned numa_coord_swap = ( avail_numa_count - use_numa_count ) - 1 ;
+    for ( unsigned i = 0 , inuma = avail_numa_count - use_numa_count ; inuma < avail_numa_count ; ++inuma ) {
+      const unsigned numa_coord = proc_coord.first == inuma ? numa_coord_swap : inuma ;
+      for ( unsigned icore = avail_cores_per_numa - use_cores_per_numa ; icore < avail_cores_per_numa ; ++icore ) {
+        const unsigned core_coord = icore ;
+        for ( unsigned ith = 0 ; ith < threads_per_core ; ++ith , ++i ) {
+          threads_coord[i].first  = numa_coord ;
+          threads_coord[i].second = core_coord ;
+        }
+      }
+    }
+  }
+  else if ( use_cores_per_numa < avail_cores_per_numa ) {
+    // Working asynchronously and omit the process' core from the pool.
+    // Swap the CORE coordinate of the process core with ( ( avail_cores_per_numa - use_cores_per_numa ) - 1 )
+    const unsigned core_coord_swap = ( avail_cores_per_numa - use_cores_per_numa ) - 1 ;
+    for ( unsigned i = 0 , inuma = avail_numa_count - use_numa_count ; inuma < avail_numa_count ; ++inuma ) {
+      const unsigned numa_coord = inuma ;
+      for ( unsigned icore = avail_cores_per_numa - use_cores_per_numa ; icore < avail_cores_per_numa ; ++icore ) {
+        const unsigned core_coord = proc_coord.second == icore ? core_coord_swap : icore ;
+        for ( unsigned ith = 0 ; ith < threads_per_core ; ++ith , ++i ) {
+          threads_coord[i].first  = numa_coord ;
+          threads_coord[i].second = core_coord ;
+        }
+      }
+    }
+  }
+
+  return thread_spawn_synchronous ;
+}
+
+} /* namespace hwloc */
+} /* namespace Kokkos */
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#if defined( KOKKOS_HAVE_HWLOC )
+
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+/*--------------------------------------------------------------------------*/
+/* Third Party Libraries */
+
+/* Hardware locality library: http://www.open-mpi.org/projects/hwloc/ */
+#include <hwloc.h>
+
+#define  REQUIRED_HWLOC_API_VERSION  0x000010300
+
+#if HWLOC_API_VERSION < REQUIRED_HWLOC_API_VERSION
+#error "Requires  http://www.open-mpi.org/projects/hwloc/  Version 1.3 or greater"
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace hwloc {
+namespace {
+
+#if DEBUG_PRINT
+
+inline
+void print_bitmap( std::ostream & s , const hwloc_const_bitmap_t bitmap )
+{
+  s << "{" ;
+  for ( int i = hwloc_bitmap_first( bitmap ) ;
+        -1 != i ; i = hwloc_bitmap_next( bitmap , i ) ) {
+    s << " " << i ;
+  }
+  s << " }" ;
+}
+
+#endif
+
+enum { MAX_CORE = 1024 };
+
+std::pair<unsigned,unsigned> s_core_topology(0,0);
+unsigned                     s_core_capacity(0);
+hwloc_topology_t             s_hwloc_topology(0);
+hwloc_bitmap_t               s_hwloc_location(0);
+hwloc_bitmap_t               s_process_binding(0);
+hwloc_bitmap_t               s_core[ MAX_CORE ];
+bool                         s_can_bind_threads(true);
+
+struct Sentinel {
+  ~Sentinel();
+  Sentinel();
+};
+
+bool sentinel()
+{
+  static Sentinel self ;
+
+  if ( 0 == s_hwloc_topology ) {
+    std::cerr << "Kokkos::hwloc ERROR : Called after return from main()" << std::endl ;
+    std::cerr.flush();
+  }
+
+  return 0 != s_hwloc_topology ;
+}
+
+Sentinel::~Sentinel()
+{
+  hwloc_topology_destroy( s_hwloc_topology );
+  hwloc_bitmap_free( s_process_binding );
+  hwloc_bitmap_free( s_hwloc_location );
+
+  s_core_topology.first  = 0 ;
+  s_core_topology.second = 0 ;
+  s_core_capacity   = 0 ;
+  s_hwloc_topology  = 0 ;
+  s_hwloc_location  = 0 ;
+  s_process_binding = 0 ;
+}
+
+Sentinel::Sentinel()
+{
+#if defined(__MIC__)
+  static const bool remove_core_0 = true ;
+#else
+  static const bool remove_core_0 = false ;
+#endif
+
+  s_core_topology   = std::pair<unsigned,unsigned>(0,0);
+  s_core_capacity   = 0 ;
+  s_hwloc_topology  = 0 ;
+  s_hwloc_location  = 0 ;
+  s_process_binding = 0 ;
+
+  for ( unsigned i = 0 ; i < MAX_CORE ; ++i ) s_core[i] = 0 ;
+
+  hwloc_topology_init( & s_hwloc_topology );
+  hwloc_topology_load( s_hwloc_topology );
+
+  s_hwloc_location  = hwloc_bitmap_alloc();
+  s_process_binding = hwloc_bitmap_alloc();
+
+  hwloc_get_cpubind( s_hwloc_topology , s_process_binding ,  HWLOC_CPUBIND_PROCESS );
+
+  if ( hwloc_bitmap_iszero( s_process_binding ) ) {
+    std::cerr << "WARNING: Cannot detect process binding -- ASSUMING ALL processing units" << std::endl;
+    const int pu_depth = hwloc_get_type_depth( s_hwloc_topology, HWLOC_OBJ_PU );
+    int num_pu = 1;
+    if ( pu_depth != HWLOC_TYPE_DEPTH_UNKNOWN ) {
+      num_pu = hwloc_get_nbobjs_by_depth( s_hwloc_topology, pu_depth );
+    }
+    else {
+      std::cerr << "WARNING: Cannot detect number of processing units -- ASSUMING 1 (serial)." << std::endl;
+      num_pu = 1;
+    }
+    hwloc_bitmap_set_range( s_process_binding, 0, num_pu-1);
+    s_can_bind_threads = false;
+  }
+
+
+  if ( remove_core_0 ) {
+
+    const hwloc_obj_t core = hwloc_get_obj_by_type( s_hwloc_topology , HWLOC_OBJ_CORE , 0 );
+
+    if ( hwloc_bitmap_intersects( s_process_binding , core->allowed_cpuset ) ) {
+
+      hwloc_bitmap_t s_process_no_core_zero = hwloc_bitmap_alloc();
+
+      hwloc_bitmap_andnot( s_process_no_core_zero , s_process_binding , core->allowed_cpuset );
+
+      bool ok = 0 == hwloc_set_cpubind( s_hwloc_topology ,
+                                        s_process_no_core_zero ,
+                                        HWLOC_CPUBIND_PROCESS | HWLOC_CPUBIND_STRICT );
+
+      if ( ok ) {
+        hwloc_get_cpubind( s_hwloc_topology , s_process_binding ,  HWLOC_CPUBIND_PROCESS );
+
+        ok = 0 != hwloc_bitmap_isequal( s_process_binding , s_process_no_core_zero );
+      }
+
+      hwloc_bitmap_free( s_process_no_core_zero );
+
+      if ( ! ok ) {
+        std::cerr << "WARNING: Kokkos::hwloc attempted and failed to move process off of core #0" << std::endl ;
+      }
+    }
+  }
+
+  // Choose a hwloc object type for the NUMA level, which may not exist.
+
+  hwloc_obj_type_t root_type = HWLOC_OBJ_TYPE_MAX ;
+
+  {
+    // Object types to search, in order.
+    static const hwloc_obj_type_t candidate_root_type[] =
+      { HWLOC_OBJ_NODE     /* NUMA region     */
+      , HWLOC_OBJ_SOCKET   /* hardware socket */
+      , HWLOC_OBJ_MACHINE  /* local machine   */
+      };
+
+    enum { CANDIDATE_ROOT_TYPE_COUNT =
+             sizeof(candidate_root_type) / sizeof(hwloc_obj_type_t) };
+
+    for ( int k = 0 ; k < CANDIDATE_ROOT_TYPE_COUNT && HWLOC_OBJ_TYPE_MAX == root_type ; ++k ) {
+      if ( 0 < hwloc_get_nbobjs_by_type( s_hwloc_topology , candidate_root_type[k] ) ) {
+        root_type = candidate_root_type[k] ;
+      }
+    }
+  }
+
+  // Determine which of these 'root' types are available to this process.
+  // The process may have been bound (e.g., by MPI) to a subset of these root types.
+  // Determine current location of the master (calling) process>
+
+  hwloc_bitmap_t proc_cpuset_location = hwloc_bitmap_alloc();
+
+  hwloc_get_last_cpu_location( s_hwloc_topology , proc_cpuset_location , HWLOC_CPUBIND_THREAD );
+
+  const unsigned max_root = hwloc_get_nbobjs_by_type( s_hwloc_topology , root_type );
+
+  unsigned root_base     = max_root ;
+  unsigned root_count    = 0 ;
+  unsigned core_per_root = 0 ;
+  unsigned pu_per_core   = 0 ;
+  bool     symmetric     = true ;
+
+  for ( unsigned i = 0 ; i < max_root ; ++i ) {
+
+    const hwloc_obj_t root = hwloc_get_obj_by_type( s_hwloc_topology , root_type , i );
+
+    if ( hwloc_bitmap_intersects( s_process_binding , root->allowed_cpuset ) ) {
+
+      ++root_count ;
+
+      // Remember which root (NUMA) object the master thread is running on.
+      // This will be logical NUMA rank #0 for this process.
+
+      if ( hwloc_bitmap_intersects( proc_cpuset_location, root->allowed_cpuset ) ) {
+        root_base = i ;
+      }
+
+      // Count available cores:
+
+      const unsigned max_core =
+        hwloc_get_nbobjs_inside_cpuset_by_type( s_hwloc_topology ,
+                                                root->allowed_cpuset ,
+                                                HWLOC_OBJ_CORE );
+
+      unsigned core_count = 0 ;
+
+      for ( unsigned j = 0 ; j < max_core ; ++j ) {
+
+        const hwloc_obj_t core =
+          hwloc_get_obj_inside_cpuset_by_type( s_hwloc_topology ,
+                                               root->allowed_cpuset ,
+                                               HWLOC_OBJ_CORE , j );
+
+        // If process' cpuset intersects core's cpuset then process can access this core.
+        // Must use intersection instead of inclusion because the Intel-Phi
+        // MPI may bind the process to only one of the core's hyperthreads.
+        //
+        // Assumption: if the process can access any hyperthread of the core
+        // then it has ownership of the entire core.
+        // This assumes that it would be performance-detrimental
+        // to spawn more than one MPI process per core and use nested threading.
+
+        if ( hwloc_bitmap_intersects( s_process_binding , core->allowed_cpuset ) ) {
+
+          ++core_count ;
+
+          const unsigned pu_count =
+            hwloc_get_nbobjs_inside_cpuset_by_type( s_hwloc_topology ,
+                                                    core->allowed_cpuset ,
+                                                    HWLOC_OBJ_PU );
+
+          if ( pu_per_core == 0 ) pu_per_core = pu_count ;
+
+          // Enforce symmetry by taking the minimum:
+
+          pu_per_core = std::min( pu_per_core , pu_count );
+
+          if ( pu_count != pu_per_core ) symmetric = false ;
+        }
+      }
+
+      if ( 0 == core_per_root ) core_per_root = core_count ;
+
+      // Enforce symmetry by taking the minimum:
+
+      core_per_root = std::min( core_per_root , core_count );
+
+      if ( core_count != core_per_root ) symmetric = false ;
+    }
+  }
+
+  s_core_topology.first  = root_count ;
+  s_core_topology.second = core_per_root ;
+  s_core_capacity        = pu_per_core ;
+
+  // Fill the 's_core' array for fast mapping from a core coordinate to the
+  // hwloc cpuset object required for thread location querying and binding.
+
+  for ( unsigned i = 0 ; i < max_root ; ++i ) {
+
+    const unsigned root_rank = ( i + root_base ) % max_root ;
+
+    const hwloc_obj_t root = hwloc_get_obj_by_type( s_hwloc_topology , root_type , root_rank );
+
+    if ( hwloc_bitmap_intersects( s_process_binding , root->allowed_cpuset ) ) {
+
+      const unsigned max_core =
+        hwloc_get_nbobjs_inside_cpuset_by_type( s_hwloc_topology ,
+                                                root->allowed_cpuset ,
+                                                HWLOC_OBJ_CORE );
+
+      unsigned core_count = 0 ;
+
+      for ( unsigned j = 0 ; j < max_core && core_count < core_per_root ; ++j ) {
+
+        const hwloc_obj_t core =
+          hwloc_get_obj_inside_cpuset_by_type( s_hwloc_topology ,
+                                               root->allowed_cpuset ,
+                                               HWLOC_OBJ_CORE , j );
+
+        if ( hwloc_bitmap_intersects( s_process_binding , core->allowed_cpuset ) ) {
+
+          s_core[ core_count + core_per_root * i ] = core->allowed_cpuset ;
+
+          ++core_count ;
+        }
+      }
+    }
+  }
+
+  hwloc_bitmap_free( proc_cpuset_location );
+
+  if ( ! symmetric ) {
+    std::cout << "Kokkos::hwloc WARNING: Using a symmetric subset of a non-symmetric core topology."
+              << std::endl ;
+  }
+}
+
+
+} // namespace
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+bool available()
+{ return true ; }
+
+unsigned get_available_numa_count()
+{ sentinel(); return s_core_topology.first ; }
+
+unsigned get_available_cores_per_numa()
+{ sentinel(); return s_core_topology.second ; }
+
+unsigned get_available_threads_per_core()
+{ sentinel(); return s_core_capacity ; }
+
+bool can_bind_threads()
+{ sentinel(); return s_can_bind_threads; }
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+unsigned bind_this_thread(
+  const unsigned               coordinate_count ,
+  std::pair<unsigned,unsigned> coordinate[] )
+{
+  unsigned i = 0 ;
+
+  try {
+    const std::pair<unsigned,unsigned> current = get_this_thread_coordinate();
+
+    // Match one of the requests:
+    for ( i = 0 ; i < coordinate_count && current != coordinate[i] ; ++i );
+
+    if ( coordinate_count == i ) {
+      // Match the first request (typically NUMA):
+      for ( i = 0 ; i < coordinate_count && current.first != coordinate[i].first ; ++i );
+    }
+
+    if ( coordinate_count == i ) {
+      // Match any unclaimed request:
+      for ( i = 0 ; i < coordinate_count && ~0u == coordinate[i].first  ; ++i );
+    }
+
+    if ( coordinate_count == i || ! bind_this_thread( coordinate[i] ) ) {
+       // Failed to bind:
+       i = ~0u ;
+    }
+
+    if ( i < coordinate_count ) {
+
+#if DEBUG_PRINT
+      if ( current != coordinate[i] ) {
+        std::cout << "  bind_this_thread: rebinding from ("
+                  << current.first << ","
+                  << current.second
+                  << ") to ("
+                  << coordinate[i].first << ","
+                  << coordinate[i].second
+                  << ")" << std::endl ;
+      }
+#endif
+
+      coordinate[i].first  = ~0u ;
+      coordinate[i].second = ~0u ;
+    }
+  }
+  catch( ... ) {
+    i = ~0u ;
+  }
+
+  return i ;
+}
+
+
+bool bind_this_thread( const std::pair<unsigned,unsigned> coord )
+{
+  if ( ! sentinel() ) return false ;
+
+#if DEBUG_PRINT
+
+  std::cout << "Kokkos::bind_this_thread() at " ;
+
+  hwloc_get_last_cpu_location( s_hwloc_topology ,
+                               s_hwloc_location , HWLOC_CPUBIND_THREAD );
+
+  print_bitmap( std::cout , s_hwloc_location );
+
+  std::cout << " to " ;
+
+  print_bitmap( std::cout , s_core[ coord.second + coord.first * s_core_topology.second ] );
+
+  std::cout << std::endl ;
+
+#endif
+
+  // As safe and fast as possible.
+  // Fast-lookup by caching the coordinate -> hwloc cpuset mapping in 's_core'.
+  return coord.first  < s_core_topology.first &&
+         coord.second < s_core_topology.second &&
+         0 == hwloc_set_cpubind( s_hwloc_topology ,
+                                 s_core[ coord.second + coord.first * s_core_topology.second ] ,
+                                 HWLOC_CPUBIND_THREAD | HWLOC_CPUBIND_STRICT );
+}
+
+bool unbind_this_thread()
+{
+  if ( ! sentinel() ) return false ;
+
+#define HWLOC_DEBUG_PRINT 0
+
+#if HWLOC_DEBUG_PRINT
+
+  std::cout << "Kokkos::unbind_this_thread() from " ;
+
+  hwloc_get_cpubind( s_hwloc_topology , s_hwloc_location , HWLOC_CPUBIND_THREAD );
+
+  print_bitmap( std::cout , s_hwloc_location );
+
+#endif
+
+  const bool result =
+    s_hwloc_topology &&
+    0 == hwloc_set_cpubind( s_hwloc_topology ,
+                            s_process_binding ,
+                            HWLOC_CPUBIND_THREAD | HWLOC_CPUBIND_STRICT );
+
+#if HWLOC_DEBUG_PRINT
+
+  std::cout << " to " ;
+
+  hwloc_get_cpubind( s_hwloc_topology , s_hwloc_location , HWLOC_CPUBIND_THREAD );
+
+  print_bitmap( std::cout , s_hwloc_location );
+
+  std::cout << std::endl ;
+
+#endif
+
+  return result ;
+
+#undef HWLOC_DEBUG_PRINT
+
+}
+
+//----------------------------------------------------------------------------
+
+std::pair<unsigned,unsigned> get_this_thread_coordinate()
+{
+  std::pair<unsigned,unsigned> coord(0u,0u);
+
+  if ( ! sentinel() ) return coord ;
+
+  const unsigned n = s_core_topology.first * s_core_topology.second ;
+
+  // Using the pre-allocated 's_hwloc_location' to avoid memory
+  // allocation by this thread.  This call is NOT thread-safe.
+  hwloc_get_last_cpu_location( s_hwloc_topology ,
+                               s_hwloc_location , HWLOC_CPUBIND_THREAD );
+
+  unsigned i = 0 ;
+
+  while ( i < n && ! hwloc_bitmap_intersects( s_hwloc_location , s_core[ i ] ) ) ++i ;
+
+  if ( i < n ) {
+    coord.first  = i / s_core_topology.second ;
+    coord.second = i % s_core_topology.second ;
+  }
+
+  return coord ;
+}
+
+//----------------------------------------------------------------------------
+
+} /* namespace hwloc */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#else /* ! defined( KOKKOS_HAVE_HWLOC ) */
+
+namespace Kokkos {
+namespace hwloc {
+
+bool available() { return false ; }
+bool can_bind_threads() { return false ; }
+
+unsigned get_available_numa_count() { return 1 ; }
+unsigned get_available_cores_per_numa() { return 1 ; }
+unsigned get_available_threads_per_core() { return 1 ; }
+
+unsigned bind_this_thread( const unsigned , std::pair<unsigned,unsigned>[] )
+{ return ~0 ; }
+
+bool bind_this_thread( const std::pair<unsigned,unsigned> )
+{ return false ; }
+
+bool unbind_this_thread()
+{ return true ; }
+
+std::pair<unsigned,unsigned> get_this_thread_coordinate()
+{ return std::pair<unsigned,unsigned>(0,0); }
+
+} // namespace hwloc
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif
+
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_spinwait.cpp b/lib/kokkos/core/src/impl/Kokkos_spinwait.cpp
new file mode 100644
index 0000000000..aff7f29f89
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_spinwait.cpp
@@ -0,0 +1,89 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Macros.hpp>
+#include <impl/Kokkos_spinwait.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+#if ( KOKKOS_ENABLE_ASM )
+  #if defined( __arm__ ) || defined( __aarch64__ )
+    /* No-operation instruction to idle the thread. */
+    #define YIELD   asm volatile("nop")
+  #else
+    /* Pause instruction to prevent excess processor bus usage */
+    #define YIELD   asm volatile("pause\n":::"memory")
+  #endif
+#elif defined ( KOKKOS_HAVE_WINTHREAD )
+  #include <process.h>
+  #define YIELD  Sleep(0)
+#elif defined ( _WIN32)  && defined (_MSC_VER)
+  /* Windows w/ Visual Studio */
+  #define NOMINMAX
+  #include <winsock2.h>
+  #include <windows.h>
+#define YIELD YieldProcessor();
+#elif defined ( _WIN32 )
+  /* Windows w/ Intel*/
+  #define YIELD __asm__ __volatile__("pause\n":::"memory")
+#else
+  #include <sched.h>
+  #define YIELD  sched_yield()
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+namespace Kokkos {
+namespace Impl {
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+void spinwait( volatile int & flag , const int value )
+{
+  while ( value == flag ) {
+    YIELD ;
+  }
+}
+#endif
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
diff --git a/lib/kokkos/core/src/impl/Kokkos_spinwait.hpp b/lib/kokkos/core/src/impl/Kokkos_spinwait.hpp
new file mode 100644
index 0000000000..cc87771fae
--- /dev/null
+++ b/lib/kokkos/core/src/impl/Kokkos_spinwait.hpp
@@ -0,0 +1,64 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+
+#ifndef KOKKOS_SPINWAIT_HPP
+#define KOKKOS_SPINWAIT_HPP
+
+#include <Kokkos_Macros.hpp>
+
+namespace Kokkos {
+namespace Impl {
+
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+void spinwait( volatile int & flag , const int value );
+#else
+KOKKOS_INLINE_FUNCTION
+void spinwait( volatile int & , const int ) {}
+#endif
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_SPINWAIT_HPP */
+
diff --git a/lib/kokkos/core/unit_test/CMakeLists.txt b/lib/kokkos/core/unit_test/CMakeLists.txt
new file mode 100644
index 0000000000..5bb2b672e1
--- /dev/null
+++ b/lib/kokkos/core/unit_test/CMakeLists.txt
@@ -0,0 +1,105 @@
+#
+# Add test-only library for gtest to be reused by all the subpackages
+#
+
+SET(GTEST_SOURCE_DIR ${${PARENT_PACKAGE_NAME}_SOURCE_DIR}/tpls/gtest)
+
+INCLUDE_DIRECTORIES(${GTEST_SOURCE_DIR})
+TRIBITS_ADD_LIBRARY(
+  kokkos_gtest
+  HEADERS ${GTEST_SOURCE_DIR}/gtest/gtest.h
+  SOURCES ${GTEST_SOURCE_DIR}/gtest/gtest-all.cc
+  TESTONLY
+  )
+
+#
+# Define the tests
+#
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+IF(Kokkos_ENABLE_Serial)
+  TRIBITS_ADD_EXECUTABLE_AND_TEST(
+    UnitTest_Serial
+    SOURCES UnitTestMain.cpp TestSerial.cpp
+    COMM serial mpi
+    NUM_MPI_PROCS 1
+    FAIL_REGULAR_EXPRESSION "  FAILED  "
+    TESTONLYLIBS kokkos_gtest
+  )
+ENDIF()
+
+IF(Kokkos_ENABLE_Pthread)
+  TRIBITS_ADD_EXECUTABLE_AND_TEST(
+    UnitTest_Threads
+    SOURCES UnitTestMain.cpp TestThreads.cpp
+    COMM serial mpi
+    NUM_MPI_PROCS 1
+    FAIL_REGULAR_EXPRESSION "  FAILED  "
+    TESTONLYLIBS kokkos_gtest
+  )
+ENDIF()
+
+IF(Kokkos_ENABLE_OpenMP)
+  TRIBITS_ADD_EXECUTABLE_AND_TEST(
+    UnitTest_OpenMP
+    SOURCES UnitTestMain.cpp TestOpenMP.cpp TestOpenMP_a.cpp TestOpenMP_b.cpp TestOpenMP_c.cpp
+    COMM serial mpi
+    NUM_MPI_PROCS 1
+    FAIL_REGULAR_EXPRESSION "  FAILED  "
+    TESTONLYLIBS kokkos_gtest
+  )
+ENDIF()
+
+IF(Kokkos_ENABLE_QTHREAD)
+  TRIBITS_ADD_EXECUTABLE_AND_TEST(
+    UnitTest_Qthread
+    SOURCES UnitTestMain.cpp TestQthread.cpp
+    COMM serial mpi
+    NUM_MPI_PROCS 1
+    FAIL_REGULAR_EXPRESSION "  FAILED  "
+    TESTONLYLIBS kokkos_gtest
+  )
+ENDIF()
+
+IF(Kokkos_ENABLE_Cuda)
+  TRIBITS_ADD_EXECUTABLE_AND_TEST(
+    UnitTest_Cuda
+    SOURCES UnitTestMain.cpp TestCuda.cpp TestCuda_a.cpp TestCuda_b.cpp TestCuda_c.cpp
+    COMM serial mpi
+    NUM_MPI_PROCS 1
+    FAIL_REGULAR_EXPRESSION "  FAILED  "
+    TESTONLYLIBS kokkos_gtest
+  )
+ENDIF()
+
+TRIBITS_ADD_EXECUTABLE_AND_TEST(
+  UnitTest_Default
+  SOURCES UnitTestMain.cpp TestDefaultDeviceType.cpp TestDefaultDeviceType_a.cpp
+  COMM serial mpi
+  NUM_MPI_PROCS 1
+  FAIL_REGULAR_EXPRESSION "  FAILED  "
+    TESTONLYLIBS kokkos_gtest
+)
+
+foreach(INITTESTS_NUM RANGE 1 16)
+TRIBITS_ADD_EXECUTABLE_AND_TEST(
+  UnitTest_DefaultInit_${INITTESTS_NUM}
+  SOURCES UnitTestMain.cpp TestDefaultDeviceTypeInit_${INITTESTS_NUM}.cpp
+  COMM serial mpi
+  NUM_MPI_PROCS 1
+  FAIL_REGULAR_EXPRESSION "  FAILED  "
+    TESTONLYLIBS kokkos_gtest
+)
+endforeach(INITTESTS_NUM)
+
+TRIBITS_ADD_EXECUTABLE_AND_TEST(
+  UnitTest_HWLOC
+  SOURCES UnitTestMain.cpp  TestHWLOC.cpp
+  COMM serial mpi
+  NUM_MPI_PROCS 1
+  FAIL_REGULAR_EXPRESSION "  FAILED  "
+    TESTONLYLIBS kokkos_gtest
+)
+
diff --git a/lib/kokkos/core/unit_test/Makefile b/lib/kokkos/core/unit_test/Makefile
new file mode 100644
index 0000000000..3d9d212c1e
--- /dev/null
+++ b/lib/kokkos/core/unit_test/Makefile
@@ -0,0 +1,153 @@
+KOKKOS_PATH = ../..
+
+GTEST_PATH = ../../tpls/gtest
+
+vpath %.cpp ${KOKKOS_PATH}/core/unit_test
+TEST_HEADERS = $(wildcard $(KOKKOS_PATH)/core/unit_test/*.hpp)
+
+default: build_all
+	echo "End Build"
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?= -lpthread
+endif
+
+KOKKOS_CXXFLAGS += -I$(GTEST_PATH) -I${KOKKOS_PATH}/core/unit_test
+
+TEST_TARGETS =
+TARGETS =
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	OBJ_CUDA = TestCuda_c.o TestCuda_b.o TestCuda_a.o TestCuda.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosCore_UnitTest_Cuda
+	TEST_TARGETS += test-cuda
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+	OBJ_THREADS = TestThreads.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosCore_UnitTest_Threads
+	TEST_TARGETS += test-threads
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+	OBJ_OPENMP = TestOpenMP_c.o TestOpenMP_b.o TestOpenMP_a.o TestOpenMP.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosCore_UnitTest_OpenMP
+	TEST_TARGETS += test-openmp
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_SERIAL), 1)
+	OBJ_SERIAL = TestSerial.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosCore_UnitTest_Serial
+	TEST_TARGETS += test-serial
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_QTHREAD), 1)
+	OBJ_QTHREAD = TestQthread.o UnitTestMain.o gtest-all.o
+	TARGETS += KokkosCore_UnitTest_Qthread
+	TEST_TARGETS += test-qthread
+endif
+
+OBJ_HWLOC = TestHWLOC.o UnitTestMain.o gtest-all.o
+TARGETS += KokkosCore_UnitTest_HWLOC
+TEST_TARGETS += test-hwloc
+
+OBJ_DEFAULT = TestDefaultDeviceType.o TestDefaultDeviceType_a.o UnitTestMain.o gtest-all.o
+TARGETS += KokkosCore_UnitTest_Default
+TEST_TARGETS += test-default
+
+NUM_INITTESTS = 16
+INITTESTS_NUMBERS := $(shell seq 1 ${NUM_INITTESTS})
+INITTESTS_TARGETS := $(addprefix KokkosCore_UnitTest_DefaultDeviceTypeInit_,${INITTESTS_NUMBERS})
+TARGETS += ${INITTESTS_TARGETS}
+INITTESTS_TEST_TARGETS := $(addprefix test-default-init-,${INITTESTS_NUMBERS})
+TEST_TARGETS += ${INITTESTS_TEST_TARGETS}
+
+OBJ_SYNCHRONIC = TestSynchronic.o UnitTestMain.o gtest-all.o
+TARGETS += KokkosCore_UnitTest_Synchronic
+TEST_TARGETS += test-synchronic
+
+KokkosCore_UnitTest_Cuda: $(OBJ_CUDA) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_CUDA) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_Cuda
+
+KokkosCore_UnitTest_Threads: $(OBJ_THREADS) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_THREADS) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_Threads
+
+KokkosCore_UnitTest_OpenMP: $(OBJ_OPENMP) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_OPENMP) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_OpenMP
+
+KokkosCore_UnitTest_Serial: $(OBJ_SERIAL) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_SERIAL) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_Serial
+
+KokkosCore_UnitTest_Qthread: $(OBJ_QTHREAD) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_QTHREAD) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_Qthread
+
+KokkosCore_UnitTest_HWLOC: $(OBJ_HWLOC) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_HWLOC) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_HWLOC
+
+KokkosCore_UnitTest_AllocationTracker: $(OBJ_ALLOCATIONTRACKER) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_ALLOCATIONTRACKER) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_AllocationTracker
+
+KokkosCore_UnitTest_Default: $(OBJ_DEFAULT) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_DEFAULT) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_Default
+
+${INITTESTS_TARGETS}: KokkosCore_UnitTest_DefaultDeviceTypeInit_%: TestDefaultDeviceTypeInit_%.o UnitTestMain.o gtest-all.o $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) TestDefaultDeviceTypeInit_$*.o UnitTestMain.o gtest-all.o $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_DefaultDeviceTypeInit_$*
+
+KokkosCore_UnitTest_Synchronic: $(OBJ_SYNCHRONIC) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_SYNCHRONIC) $(KOKKOS_LIBS) $(LIB) -o KokkosCore_UnitTest_Synchronic
+
+test-cuda: KokkosCore_UnitTest_Cuda
+	./KokkosCore_UnitTest_Cuda
+
+test-threads: KokkosCore_UnitTest_Threads
+	./KokkosCore_UnitTest_Threads
+
+test-openmp: KokkosCore_UnitTest_OpenMP
+	./KokkosCore_UnitTest_OpenMP
+
+test-serial: KokkosCore_UnitTest_Serial
+	./KokkosCore_UnitTest_Serial
+
+test-qthread: KokkosCore_UnitTest_Qthread
+	./KokkosCore_UnitTest_Qthread
+
+test-hwloc: KokkosCore_UnitTest_HWLOC
+	./KokkosCore_UnitTest_HWLOC
+
+test-allocationtracker: KokkosCore_UnitTest_AllocationTracker
+	./KokkosCore_UnitTest_AllocationTracker
+
+test-default: KokkosCore_UnitTest_Default
+	./KokkosCore_UnitTest_Default
+
+${INITTESTS_TEST_TARGETS}: test-default-init-%: KokkosCore_UnitTest_DefaultDeviceTypeInit_%
+	./KokkosCore_UnitTest_DefaultDeviceTypeInit_$*
+
+test-synchronic: KokkosCore_UnitTest_Synchronic
+	./KokkosCore_UnitTest_Synchronic
+
+build_all: $(TARGETS)
+
+test: $(TEST_TARGETS)
+
+clean: kokkos-clean
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS) $(TEST_HEADERS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
+gtest-all.o:$(GTEST_PATH)/gtest/gtest-all.cc
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $(GTEST_PATH)/gtest/gtest-all.cc
+
diff --git a/lib/kokkos/core/unit_test/TestAggregate.hpp b/lib/kokkos/core/unit_test/TestAggregate.hpp
new file mode 100644
index 0000000000..5388a60787
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestAggregate.hpp
@@ -0,0 +1,109 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef TEST_AGGREGATE_HPP
+#define TEST_AGGREGATE_HPP
+
+#include <gtest/gtest.h>
+
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+/*--------------------------------------------------------------------------*/
+
+#include <impl/KokkosExp_ViewArray.hpp>
+
+namespace Test {
+
+template< class DeviceType >
+void TestViewAggregate()
+{
+  typedef Kokkos::Array<double,32>  value_type ;
+
+  typedef Kokkos::Experimental::Impl::
+    ViewDataAnalysis< value_type * , Kokkos::LayoutLeft , value_type >
+      analysis_1d ;
+
+  static_assert( std::is_same< typename analysis_1d::specialize , Kokkos::Array<> >::value , "" );
+
+
+  typedef Kokkos::ViewTraits< value_type ** , DeviceType > a32_traits ;
+  typedef Kokkos::ViewTraits< typename a32_traits::scalar_array_type , DeviceType > flat_traits ;
+
+  static_assert( std::is_same< typename a32_traits::specialize , Kokkos::Array<> >::value , "" );
+  static_assert( std::is_same< typename a32_traits::value_type , value_type >::value , "" );
+  static_assert( a32_traits::rank == 2 , "" );
+  static_assert( a32_traits::rank_dynamic == 2 , "" );
+
+  static_assert( std::is_same< typename flat_traits::specialize , void >::value , "" );
+  static_assert( flat_traits::rank == 3 , "" );
+  static_assert( flat_traits::rank_dynamic == 2 , "" );
+  static_assert( flat_traits::dimension::N2 == 32 , "" );
+
+
+  typedef Kokkos::View< Kokkos::Array<double,32> ** , DeviceType > a32_type ;
+
+  typedef typename a32_type::array_type  a32_flat_type ;
+
+  static_assert( std::is_same< typename a32_type::value_type , value_type >::value , "" );
+  static_assert( std::is_same< typename a32_type::pointer_type , double * >::value , "" );
+  static_assert( a32_type::Rank == 2 , "" );
+  static_assert( a32_flat_type::Rank == 3 , "" );
+
+  a32_type x("test",4,5);
+  a32_flat_type y( x );
+
+  ASSERT_EQ( x.extent(0) , 4 );
+  ASSERT_EQ( x.extent(1) , 5 );
+  ASSERT_EQ( y.extent(0) , 4 );
+  ASSERT_EQ( y.extent(1) , 5 );
+  ASSERT_EQ( y.extent(2) , 32 );
+}
+
+}
+
+/*--------------------------------------------------------------------------*/
+/*--------------------------------------------------------------------------*/
+
+#endif /* #ifndef TEST_AGGREGATE_HPP */
diff --git a/lib/kokkos/core/unit_test/TestAggregateReduction.hpp b/lib/kokkos/core/unit_test/TestAggregateReduction.hpp
new file mode 100644
index 0000000000..bd05cd347b
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestAggregateReduction.hpp
@@ -0,0 +1,191 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef TEST_AGGREGATE_REDUCTION_HPP
+#define TEST_AGGREGATE_REDUCTION_HPP
+
+#include <gtest/gtest.h>
+
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+namespace Test {
+
+template< typename T , unsigned N >
+struct StaticArray {
+  T value[N] ;
+
+  KOKKOS_INLINE_FUNCTION
+  StaticArray() = default;
+
+  KOKKOS_INLINE_FUNCTION
+  StaticArray( const StaticArray & rhs ) = default;
+
+  KOKKOS_INLINE_FUNCTION
+  operator T () { return value[0]; }
+
+  KOKKOS_INLINE_FUNCTION
+  StaticArray & operator = ( const T & rhs )
+    {
+      for ( unsigned i = 0 ; i < N ; ++i ) value[i] = rhs ;
+      return *this ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  StaticArray & operator = ( const StaticArray & rhs ) = default;
+
+  KOKKOS_INLINE_FUNCTION
+  StaticArray operator * ( const StaticArray & rhs )
+    {
+      StaticArray tmp ;
+      for ( unsigned i = 0 ; i < N ; ++i ) tmp.value[i] = value[i] * rhs.value[i] ;
+      return tmp ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  StaticArray operator + ( const StaticArray & rhs )
+    {
+      StaticArray tmp ;
+      for ( unsigned i = 0 ; i < N ; ++i ) tmp.value[i] = value[i] + rhs.value[i] ;
+      return tmp ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  StaticArray & operator += ( const StaticArray & rhs )
+    {
+      for ( unsigned i = 0 ; i < N ; ++i ) value[i] += rhs.value[i] ;
+      return *this ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator += ( const volatile StaticArray & rhs ) volatile
+    {
+      for ( unsigned i = 0 ; i < N ; ++i ) value[i] += rhs.value[i] ;
+    }
+};
+
+static_assert(std::is_trivial<StaticArray<int, 4>>::value, "Not trivial");
+
+template< typename T , class Space >
+struct DOT {
+  typedef T      value_type ;
+  typedef Space  execution_space ;
+
+  Kokkos::View< value_type * , Space > a ;
+  Kokkos::View< value_type * , Space > b ;
+
+  DOT( const Kokkos::View< value_type * , Space > arg_a
+     , const Kokkos::View< value_type * , Space > arg_b
+     )
+    : a( arg_a ), b( arg_b ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int i , value_type & update ) const
+    {
+      update += a(i) * b(i);
+    }
+};
+
+template< typename T , class Space >
+struct FILL {
+  typedef T      value_type ;
+  typedef Space  execution_space ;
+
+  Kokkos::View< value_type * , Space > a ;
+  Kokkos::View< value_type * , Space > b ;
+
+  FILL( const Kokkos::View< value_type * , Space > & arg_a
+      , const Kokkos::View< value_type * , Space > & arg_b
+      )
+    : a( arg_a ), b( arg_b ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int i ) const
+    {
+      a(i) = i % 2 ? i + 1 : 1 ;
+      b(i) = i % 2 ? 1 : i + 1 ;
+    }
+};
+
+template< class Space >
+void TestViewAggregateReduction()
+{
+
+#if ! KOKKOS_USING_EXP_VIEW
+
+  const int count = 2 ;
+  const long result = count % 2 ? ( count * ( ( count + 1 ) / 2 ) )
+                                : ( ( count / 2 ) * ( count + 1 ) );
+
+  Kokkos::View< long * , Space > a("a",count);
+  Kokkos::View< long * , Space > b("b",count);
+  Kokkos::View< StaticArray<long,4> * , Space > a4("a4",count);
+  Kokkos::View< StaticArray<long,4> * , Space > b4("b4",count);
+  Kokkos::View< StaticArray<long,10> * , Space > a10("a10",count);
+  Kokkos::View< StaticArray<long,10> * , Space > b10("b10",count);
+
+  Kokkos::parallel_for( count , FILL<long,Space>(a,b) );
+  Kokkos::parallel_for( count , FILL< StaticArray<long,4> , Space >(a4,b4) );
+  Kokkos::parallel_for( count , FILL< StaticArray<long,10> , Space >(a10,b10) );
+
+  long r = 0;
+  StaticArray<long,4> r4 ;
+  StaticArray<long,10> r10 ;
+
+  Kokkos::parallel_reduce( count , DOT<long,Space>(a,b) , r );
+  Kokkos::parallel_reduce( count , DOT< StaticArray<long,4> , Space >(a4,b4) , r4 );
+  Kokkos::parallel_reduce( count , DOT< StaticArray<long,10> , Space >(a10,b10) , r10 );
+
+  ASSERT_EQ( result , r );
+  for ( int i = 0 ; i < 10 ; ++i ) { ASSERT_EQ( result , r10.value[i] ); }
+  for ( int i = 0 ; i < 4 ; ++i ) { ASSERT_EQ( result , r4.value[i] ); }
+
+#endif
+
+}
+
+}
+
+#endif /* #ifndef TEST_AGGREGATE_REDUCTION_HPP */
+
diff --git a/lib/kokkos/core/unit_test/TestAtomic.hpp b/lib/kokkos/core/unit_test/TestAtomic.hpp
new file mode 100644
index 0000000000..e948723574
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestAtomic.hpp
@@ -0,0 +1,402 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+namespace TestAtomic {
+
+// Struct for testing arbitrary size atomics
+
+template<int N>
+struct SuperScalar {
+  double val[N];
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar() {
+    for(int i=0; i<N; i++)
+      val[i] = 0.0;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar(const SuperScalar& src) {
+    for(int i=0; i<N; i++)
+      val[i] = src.val[i];
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar(const volatile SuperScalar& src) {
+    for(int i=0; i<N; i++)
+      val[i] = src.val[i];
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar& operator = (const SuperScalar& src) {
+    for(int i=0; i<N; i++)
+      val[i] = src.val[i];
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar& operator = (const volatile SuperScalar& src) {
+    for(int i=0; i<N; i++)
+      val[i] = src.val[i];
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator = (const SuperScalar& src) volatile  {
+    for(int i=0; i<N; i++)
+      val[i] = src.val[i];
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar operator + (const SuperScalar& src) {
+    SuperScalar tmp = *this;
+    for(int i=0; i<N; i++)
+      tmp.val[i] += src.val[i];
+    return tmp;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar& operator += (const double& src) {
+    for(int i=0; i<N; i++)
+      val[i] += 1.0*(i+1)*src;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar& operator += (const SuperScalar& src) {
+    for(int i=0; i<N; i++)
+      val[i] += src.val[i];
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool operator == (const SuperScalar& src) {
+    bool compare = true;
+    for(int i=0; i<N; i++)
+      compare = compare && ( val[i] == src.val[i]);
+    return compare;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  bool operator != (const SuperScalar& src) {
+    bool compare = true;
+    for(int i=0; i<N; i++)
+      compare = compare && ( val[i] == src.val[i]);
+    return !compare;
+  }
+
+
+
+  KOKKOS_INLINE_FUNCTION
+  SuperScalar(const double& src) {
+    for(int i=0; i<N; i++)
+      val[i] = 1.0 * (i+1) * src;
+  }
+
+};
+
+template<int N>
+std::ostream& operator<<(std::ostream& os, const SuperScalar<N>& dt)
+{
+    os << "{ ";
+    for(int i=0;i<N-1;i++)
+       os << dt.val[i] << ", ";
+    os << dt.val[N-1] << "}";
+    return os;
+}
+
+template<class T,class DEVICE_TYPE>
+struct ZeroFunctor {
+  typedef DEVICE_TYPE execution_space;
+  typedef typename Kokkos::View<T,execution_space> type;
+  typedef typename Kokkos::View<T,execution_space>::HostMirror h_type;
+  type data;
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    data() = 0;
+  }
+};
+
+//---------------------------------------------------
+//--------------atomic_fetch_add---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct AddFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_add(&data(),(T)1);
+  }
+};
+
+template<class T, class execution_space >
+T AddLoop(int loop) {
+  struct ZeroFunctor<T,execution_space> f_zero;
+  typename ZeroFunctor<T,execution_space>::type data("Data");
+  typename ZeroFunctor<T,execution_space>::h_type h_data("HData");
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  execution_space::fence();
+
+  struct AddFunctor<T,execution_space> f_add;
+  f_add.data = data;
+  Kokkos::parallel_for(loop,f_add);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T AddLoopSerial(int loop) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  for(int i=0;i<loop;i++)
+  *data+=(T)1;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+//------------------------------------------------------
+//--------------atomic_compare_exchange-----------------
+//------------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct CASFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+	  T old = data();
+	  T newval, assumed;
+	  do {
+	    assumed = old;
+	    newval = assumed + (T)1;
+	    old = Kokkos::atomic_compare_exchange(&data(), assumed, newval);
+	  }
+	  while( old != assumed );
+  }
+};
+
+template<class T, class execution_space >
+T CASLoop(int loop) {
+  struct ZeroFunctor<T,execution_space> f_zero;
+  typename ZeroFunctor<T,execution_space>::type data("Data");
+  typename ZeroFunctor<T,execution_space>::h_type h_data("HData");
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  execution_space::fence();
+
+  struct CASFunctor<T,execution_space> f_cas;
+  f_cas.data = data;
+  Kokkos::parallel_for(loop,f_cas);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+
+  return val;
+}
+
+template<class T>
+T CASLoopSerial(int loop) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  for(int i=0;i<loop;i++) {
+	  T assumed;
+	  T newval;
+	  T old;
+	  do {
+	    assumed = *data;
+	    newval = assumed + (T)1;
+	    old = *data;
+	    *data = newval;
+	  }
+	  while(!(assumed==old));
+  }
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+//----------------------------------------------
+//--------------atomic_exchange-----------------
+//----------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct ExchFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data, data2;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+    T old = Kokkos::atomic_exchange(&data(),(T)i);
+    Kokkos::atomic_fetch_add(&data2(),old);
+  }
+};
+
+template<class T, class execution_space >
+T ExchLoop(int loop) {
+  struct ZeroFunctor<T,execution_space> f_zero;
+  typename ZeroFunctor<T,execution_space>::type data("Data");
+  typename ZeroFunctor<T,execution_space>::h_type h_data("HData");
+  f_zero.data = data;
+  Kokkos::parallel_for(1,f_zero);
+  execution_space::fence();
+
+  typename ZeroFunctor<T,execution_space>::type data2("Data");
+  typename ZeroFunctor<T,execution_space>::h_type h_data2("HData");
+  f_zero.data = data2;
+  Kokkos::parallel_for(1,f_zero);
+  execution_space::fence();
+
+  struct ExchFunctor<T,execution_space> f_exch;
+  f_exch.data = data;
+  f_exch.data2 = data2;
+  Kokkos::parallel_for(loop,f_exch);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  Kokkos::deep_copy(h_data2,data2);
+  T val = h_data() + h_data2();
+
+  return val;
+}
+
+template<class T>
+T ExchLoopSerial(typename std::conditional<!std::is_same<T,Kokkos::complex<double> >::value,int,void>::type loop) {
+  T* data = new T[1];
+  T* data2 = new T[1];
+  data[0] = 0;
+  data2[0] = 0;
+  for(int i=0;i<loop;i++) {
+	T old = *data;
+	*data=(T) i;
+	*data2+=old;
+  }
+
+  T val = *data2 + *data;
+  delete [] data;
+  delete [] data2;
+  return val;
+}
+
+template<class T>
+T ExchLoopSerial(typename std::conditional<std::is_same<T,Kokkos::complex<double> >::value,int,void>::type loop) {
+  T* data = new T[1];
+  T* data2 = new T[1];
+  data[0] = 0;
+  data2[0] = 0;
+  for(int i=0;i<loop;i++) {
+  T old = *data;
+  data->real() = (static_cast<double>(i));
+  data->imag() = 0;
+  *data2+=old;
+  }
+
+  T val = *data2 + *data;
+  delete [] data;
+  delete [] data2;
+  return val;
+}
+
+template<class T, class DeviceType >
+T LoopVariant(int loop, int test) {
+  switch (test) {
+    case 1: return AddLoop<T,DeviceType>(loop);
+    case 2: return CASLoop<T,DeviceType>(loop);
+    case 3: return ExchLoop<T,DeviceType>(loop);
+  }
+  return 0;
+}
+
+template<class T>
+T LoopVariantSerial(int loop, int test) {
+  switch (test) {
+    case 1: return AddLoopSerial<T>(loop);
+    case 2: return CASLoopSerial<T>(loop);
+    case 3: return ExchLoopSerial<T>(loop);
+  }
+  return 0;
+}
+
+template<class T,class DeviceType>
+bool Loop(int loop, int test)
+{
+  T res       = LoopVariant<T,DeviceType>(loop,test);
+  T resSerial = LoopVariantSerial<T>(loop,test);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = "
+              << test << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+
+  return passed ;
+}
+
+}
+
diff --git a/lib/kokkos/core/unit_test/TestAtomicOperations.hpp b/lib/kokkos/core/unit_test/TestAtomicOperations.hpp
new file mode 100644
index 0000000000..aee4bda06c
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestAtomicOperations.hpp
@@ -0,0 +1,841 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+namespace TestAtomicOperations {
+
+//-----------------------------------------------
+//--------------zero_functor---------------------
+//-----------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct ZeroFunctor {
+  typedef DEVICE_TYPE execution_space;
+  typedef typename Kokkos::View<T,execution_space> type;
+  typedef typename Kokkos::View<T,execution_space>::HostMirror h_type;
+  type data;
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    data() = 0;
+  }
+};
+
+//-----------------------------------------------
+//--------------init_functor---------------------
+//-----------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct InitFunctor {
+  typedef DEVICE_TYPE execution_space;
+  typedef typename Kokkos::View<T,execution_space> type;
+  typedef typename Kokkos::View<T,execution_space>::HostMirror h_type;
+  type data;
+  T init_value ;
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    data() = init_value;
+  }
+
+  InitFunctor(T _init_value) : init_value(_init_value) {}
+};
+
+
+//---------------------------------------------------
+//--------------atomic_fetch_max---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct MaxFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    //Kokkos::atomic_fetch_max(&data(),(T)1);
+    Kokkos::atomic_fetch_max(&data(),(T)i1);
+  }
+  MaxFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T MaxAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct MaxFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T MaxAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = (i0 > i1 ? i0 : i1) ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool MaxAtomicTest(T i0, T i1)
+{
+  T res       = MaxAtomic<T,DeviceType>(i0,i1);
+  T resSerial = MaxAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = MaxAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_min---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct MinFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_min(&data(),(T)i1);
+  }
+  MinFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T MinAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct MinFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T MinAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = (i0 < i1 ? i0 : i1) ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool MinAtomicTest(T i0, T i1)
+{
+  T res       = MinAtomic<T,DeviceType>(i0,i1);
+  T resSerial = MinAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = MinAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_mul---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct MulFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_mul(&data(),(T)i1);
+  }
+  MulFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T MulAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct MulFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T MulAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = i0*i1 ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool MulAtomicTest(T i0, T i1)
+{
+  T res       = MulAtomic<T,DeviceType>(i0,i1);
+  T resSerial = MulAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = MulAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_div---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct DivFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_div(&data(),(T)i1);
+  }
+  DivFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T DivAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct DivFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T DivAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = i0/i1 ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool DivAtomicTest(T i0, T i1)
+{
+  T res       = DivAtomic<T,DeviceType>(i0,i1);
+  T resSerial = DivAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = DivAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_mod---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct ModFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_mod(&data(),(T)i1);
+  }
+  ModFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T ModAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct ModFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T ModAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = i0%i1 ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool ModAtomicTest(T i0, T i1)
+{
+  T res       = ModAtomic<T,DeviceType>(i0,i1);
+  T resSerial = ModAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = ModAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_and---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct AndFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_and(&data(),(T)i1);
+  }
+  AndFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T AndAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct AndFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T AndAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = i0&i1 ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool AndAtomicTest(T i0, T i1)
+{
+  T res       = AndAtomic<T,DeviceType>(i0,i1);
+  T resSerial = AndAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = AndAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_or----------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct OrFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_or(&data(),(T)i1);
+  }
+  OrFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T OrAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct OrFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T OrAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = i0|i1 ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool OrAtomicTest(T i0, T i1)
+{
+  T res       = OrAtomic<T,DeviceType>(i0,i1);
+  T resSerial = OrAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = OrAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_xor---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct XorFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_xor(&data(),(T)i1);
+  }
+  XorFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T XorAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct XorFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T XorAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = i0^i1 ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool XorAtomicTest(T i0, T i1)
+{
+  T res       = XorAtomic<T,DeviceType>(i0,i1);
+  T resSerial = XorAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = XorAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_lshift---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct LShiftFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_lshift(&data(),(T)i1);
+  }
+  LShiftFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T LShiftAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct LShiftFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T LShiftAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = i0<<i1 ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool LShiftAtomicTest(T i0, T i1)
+{
+  T res       = LShiftAtomic<T,DeviceType>(i0,i1);
+  T resSerial = LShiftAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = LShiftAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+//---------------------------------------------------
+//--------------atomic_fetch_rshift---------------------
+//---------------------------------------------------
+
+template<class T,class DEVICE_TYPE>
+struct RShiftFunctor{
+  typedef DEVICE_TYPE execution_space;
+  typedef Kokkos::View<T,execution_space> type;
+  type data;
+  T i0;
+  T i1;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int) const {
+    Kokkos::atomic_fetch_rshift(&data(),(T)i1);
+  }
+  RShiftFunctor( T _i0 , T _i1 ) : i0(_i0) , i1(_i1) {}
+};
+
+template<class T, class execution_space >
+T RShiftAtomic(T i0 , T i1) {
+  struct InitFunctor<T,execution_space> f_init(i0);
+  typename InitFunctor<T,execution_space>::type data("Data");
+  typename InitFunctor<T,execution_space>::h_type h_data("HData");
+  f_init.data = data;
+  Kokkos::parallel_for(1,f_init);
+  execution_space::fence();
+
+  struct RShiftFunctor<T,execution_space> f(i0,i1);
+  f.data = data;
+  Kokkos::parallel_for(1,f);
+  execution_space::fence();
+
+  Kokkos::deep_copy(h_data,data);
+  T val = h_data();
+  return val;
+}
+
+template<class T>
+T RShiftAtomicCheck(T i0 , T i1) {
+  T* data = new T[1];
+  data[0] = 0;
+
+  *data = i0>>i1 ;
+
+  T val = *data;
+  delete [] data;
+  return val;
+}
+
+template<class T,class DeviceType>
+bool RShiftAtomicTest(T i0, T i1)
+{
+  T res       = RShiftAtomic<T,DeviceType>(i0,i1);
+  T resSerial = RShiftAtomicCheck<T>(i0,i1);
+
+  bool passed = true;
+
+  if ( resSerial != res ) {
+    passed = false;
+
+    std::cout << "Loop<"
+              << typeid(T).name()
+              << ">( test = RShiftAtomicTest"
+              << " FAILED : "
+              << resSerial << " != " << res
+              << std::endl ;
+  }
+
+  return passed ;
+}
+
+
+//---------------------------------------------------
+//--------------atomic_test_control------------------
+//---------------------------------------------------
+
+template<class T,class DeviceType>
+bool AtomicOperationsTestIntegralType( int i0 , int i1 , int test )
+{
+  switch (test) {
+    case 1: return MaxAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 2: return MinAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 3: return MulAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 4: return DivAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 5: return ModAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 6: return AndAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 7: return OrAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 8: return XorAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 9: return LShiftAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 10: return RShiftAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+  }
+  return 0;
+}
+
+template<class T,class DeviceType>
+bool AtomicOperationsTestNonIntegralType( int i0 , int i1 , int test )
+{
+  switch (test) {
+    case 1: return MaxAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 2: return MinAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 3: return MulAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+    case 4: return DivAtomicTest<T,DeviceType>( (T)i0 , (T)i1 );
+  }
+  return 0;
+}
+
+} // namespace
+
diff --git a/lib/kokkos/core/unit_test/TestCXX11.hpp b/lib/kokkos/core/unit_test/TestCXX11.hpp
new file mode 100644
index 0000000000..2d6349776b
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestCXX11.hpp
@@ -0,0 +1,334 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+#include <Kokkos_Core.hpp>
+
+namespace TestCXX11 {
+
+template<class DeviceType>
+struct FunctorAddTest{
+  typedef Kokkos::View<double**,DeviceType> view_type;
+  view_type a_, b_;
+  typedef DeviceType execution_space;
+  FunctorAddTest(view_type & a, view_type &b):a_(a),b_(b) {}
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i) const {
+    b_(i,0) = a_(i,1) + a_(i,2);
+    b_(i,1) = a_(i,0) - a_(i,3);
+    b_(i,2) = a_(i,4) + a_(i,0);
+    b_(i,3) = a_(i,2) - a_(i,1);
+    b_(i,4) = a_(i,3) + a_(i,4);
+  }
+
+  typedef typename Kokkos::TeamPolicy< execution_space >::member_type  team_member ;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_member & dev) const {
+    const int begin = dev.league_rank() * 4 ;
+    const int end   = begin + 4 ;
+    for ( int i = begin + dev.team_rank() ; i < end ; i += dev.team_size() ) {
+      b_(i,0) = a_(i,1) + a_(i,2);
+      b_(i,1) = a_(i,0) - a_(i,3);
+      b_(i,2) = a_(i,4) + a_(i,0);
+      b_(i,3) = a_(i,2) - a_(i,1);
+      b_(i,4) = a_(i,3) + a_(i,4);
+    }
+  }
+};
+
+template<class DeviceType, bool PWRTest>
+double AddTestFunctor() {
+
+  typedef Kokkos::TeamPolicy<DeviceType> policy_type ;
+
+  Kokkos::View<double**,DeviceType> a("A",100,5);
+  Kokkos::View<double**,DeviceType> b("B",100,5);
+  typename Kokkos::View<double**,DeviceType>::HostMirror h_a = Kokkos::create_mirror_view(a);
+  typename Kokkos::View<double**,DeviceType>::HostMirror h_b = Kokkos::create_mirror_view(b);
+
+  for(int i=0;i<100;i++) {
+    for(int j=0;j<5;j++)
+       h_a(i,j) = 0.1*i/(1.1*j+1.0) + 0.5*j;
+  }
+  Kokkos::deep_copy(a,h_a);
+
+  if(PWRTest==false)
+    Kokkos::parallel_for(100,FunctorAddTest<DeviceType>(a,b));
+  else
+    Kokkos::parallel_for(policy_type(25,Kokkos::AUTO),FunctorAddTest<DeviceType>(a,b));
+  Kokkos::deep_copy(h_b,b);
+
+  double result = 0;
+  for(int i=0;i<100;i++) {
+      for(int j=0;j<5;j++)
+         result += h_b(i,j);
+    }
+
+  return result;
+}
+
+
+#if defined (KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+template<class DeviceType, bool PWRTest>
+double AddTestLambda() {
+
+  Kokkos::View<double**,DeviceType> a("A",100,5);
+  Kokkos::View<double**,DeviceType> b("B",100,5);
+  typename Kokkos::View<double**,DeviceType>::HostMirror h_a = Kokkos::create_mirror_view(a);
+  typename Kokkos::View<double**,DeviceType>::HostMirror h_b = Kokkos::create_mirror_view(b);
+
+  for(int i=0;i<100;i++) {
+    for(int j=0;j<5;j++)
+       h_a(i,j) = 0.1*i/(1.1*j+1.0) + 0.5*j;
+  }
+  Kokkos::deep_copy(a,h_a);
+
+  if(PWRTest==false) {
+    Kokkos::parallel_for(100,KOKKOS_LAMBDA(const int& i)  {
+      b(i,0) = a(i,1) + a(i,2);
+      b(i,1) = a(i,0) - a(i,3);
+      b(i,2) = a(i,4) + a(i,0);
+      b(i,3) = a(i,2) - a(i,1);
+      b(i,4) = a(i,3) + a(i,4);
+    });
+  } else {
+    typedef Kokkos::TeamPolicy<DeviceType> policy_type ;
+    typedef typename policy_type::member_type team_member ;
+
+    policy_type policy(25,Kokkos::AUTO);
+
+    Kokkos::parallel_for(policy,KOKKOS_LAMBDA(const team_member & dev)  {
+      const int begin = dev.league_rank() * 4 ;
+      const int end   = begin + 4 ;
+      for ( int i = begin + dev.team_rank() ; i < end ; i += dev.team_size() ) {
+        b(i,0) = a(i,1) + a(i,2);
+        b(i,1) = a(i,0) - a(i,3);
+        b(i,2) = a(i,4) + a(i,0);
+        b(i,3) = a(i,2) - a(i,1);
+        b(i,4) = a(i,3) + a(i,4);
+      }
+    });
+  }
+  Kokkos::deep_copy(h_b,b);
+
+  double result = 0;
+  for(int i=0;i<100;i++) {
+      for(int j=0;j<5;j++)
+         result += h_b(i,j);
+    }
+
+  return result;
+}
+
+#else
+template<class DeviceType, bool PWRTest>
+double AddTestLambda() {
+  return AddTestFunctor<DeviceType,PWRTest>();
+}
+#endif
+
+
+template<class DeviceType>
+struct FunctorReduceTest{
+  typedef Kokkos::View<double**,DeviceType> view_type;
+  view_type a_;
+  typedef DeviceType execution_space;
+  typedef double value_type;
+  FunctorReduceTest(view_type & a):a_(a) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i, value_type& sum) const {
+    sum += a_(i,1) + a_(i,2);
+    sum += a_(i,0) - a_(i,3);
+    sum += a_(i,4) + a_(i,0);
+    sum += a_(i,2) - a_(i,1);
+    sum += a_(i,3) + a_(i,4);
+  }
+
+  typedef typename Kokkos::TeamPolicy< execution_space >::member_type  team_member ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_member & dev, value_type& sum) const {
+    const int begin = dev.league_rank() * 4 ;
+    const int end   = begin + 4 ;
+    for ( int i = begin + dev.team_rank() ; i < end ; i += dev.team_size() ) {
+      sum += a_(i,1) + a_(i,2);
+      sum += a_(i,0) - a_(i,3);
+      sum += a_(i,4) + a_(i,0);
+      sum += a_(i,2) - a_(i,1);
+      sum += a_(i,3) + a_(i,4);
+    }
+  }
+  KOKKOS_INLINE_FUNCTION
+  void init(value_type& update) const {update = 0.0;}
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& update, volatile value_type const& input) const {update += input;}
+};
+
+template<class DeviceType, bool PWRTest>
+double ReduceTestFunctor() {
+
+  typedef Kokkos::TeamPolicy<DeviceType> policy_type ;
+  typedef Kokkos::View<double**,DeviceType> view_type ;
+  typedef Kokkos::View<double,typename view_type::host_mirror_space,Kokkos::MemoryUnmanaged> unmanaged_result ;
+
+  view_type a("A",100,5);
+  typename view_type::HostMirror h_a = Kokkos::create_mirror_view(a);
+
+  for(int i=0;i<100;i++) {
+    for(int j=0;j<5;j++)
+       h_a(i,j) = 0.1*i/(1.1*j+1.0) + 0.5*j;
+  }
+  Kokkos::deep_copy(a,h_a);
+
+  double result = 0.0;
+  if(PWRTest==false)
+    Kokkos::parallel_reduce(100,FunctorReduceTest<DeviceType>(a), unmanaged_result( & result ));
+  else
+    Kokkos::parallel_reduce(policy_type(25,Kokkos::AUTO),FunctorReduceTest<DeviceType>(a), unmanaged_result( & result ));
+
+  return result;
+}
+
+#if defined (KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+template<class DeviceType, bool PWRTest>
+double ReduceTestLambda() {
+
+  typedef Kokkos::TeamPolicy<DeviceType> policy_type ;
+  typedef Kokkos::View<double**,DeviceType> view_type ;
+  typedef Kokkos::View<double,typename view_type::host_mirror_space,Kokkos::MemoryUnmanaged> unmanaged_result ;
+
+  view_type a("A",100,5);
+  typename view_type::HostMirror h_a = Kokkos::create_mirror_view(a);
+
+  for(int i=0;i<100;i++) {
+    for(int j=0;j<5;j++)
+       h_a(i,j) = 0.1*i/(1.1*j+1.0) + 0.5*j;
+  }
+  Kokkos::deep_copy(a,h_a);
+
+  double result = 0.0;
+
+  if(PWRTest==false) {
+    Kokkos::parallel_reduce(100,KOKKOS_LAMBDA(const int& i, double& sum)  {
+      sum += a(i,1) + a(i,2);
+      sum += a(i,0) - a(i,3);
+      sum += a(i,4) + a(i,0);
+      sum += a(i,2) - a(i,1);
+      sum += a(i,3) + a(i,4);
+    }, unmanaged_result( & result ) );
+  } else {
+    typedef typename policy_type::member_type team_member ;
+    Kokkos::parallel_reduce(policy_type(25,Kokkos::AUTO),KOKKOS_LAMBDA(const team_member & dev, double& sum)  {
+      const int begin = dev.league_rank() * 4 ;
+      const int end   = begin + 4 ;
+      for ( int i = begin + dev.team_rank() ; i < end ; i += dev.team_size() ) {
+        sum += a(i,1) + a(i,2);
+        sum += a(i,0) - a(i,3);
+        sum += a(i,4) + a(i,0);
+        sum += a(i,2) - a(i,1);
+        sum += a(i,3) + a(i,4);
+      }
+    }, unmanaged_result( & result ) );
+  }
+
+  return result;
+}
+
+#else
+template<class DeviceType, bool PWRTest>
+double ReduceTestLambda() {
+  return ReduceTestFunctor<DeviceType,PWRTest>();
+}
+#endif
+
+template<class DeviceType>
+double TestVariantLambda(int test) {
+  switch (test) {
+    case 1: return AddTestLambda<DeviceType,false>();
+    case 2: return AddTestLambda<DeviceType,true>();
+    case 3: return ReduceTestLambda<DeviceType,false>();
+    case 4: return ReduceTestLambda<DeviceType,true>();
+  }
+  return 0;
+}
+
+
+template<class DeviceType>
+double TestVariantFunctor(int test) {
+  switch (test) {
+    case 1: return AddTestFunctor<DeviceType,false>();
+    case 2: return AddTestFunctor<DeviceType,true>();
+    case 3: return ReduceTestFunctor<DeviceType,false>();
+    case 4: return ReduceTestFunctor<DeviceType,true>();
+  }
+  return 0;
+}
+
+template<class DeviceType>
+bool Test(int test) {
+
+#ifdef KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA
+  double res_functor = TestVariantFunctor<DeviceType>(test);
+  double res_lambda = TestVariantLambda<DeviceType>(test);
+
+  char testnames[5][256] = {" "
+                            ,"AddTest","AddTest TeamPolicy"
+                            ,"ReduceTest","ReduceTest TeamPolicy"
+                           };
+  bool passed = true;
+
+  if ( res_functor != res_lambda ) {
+    passed = false;
+
+    std::cout << "CXX11 ( test = '"
+              << testnames[test] << "' FAILED : "
+              << res_functor << " != " << res_lambda
+              << std::endl ;
+  }
+
+  return passed ;
+#else
+  return true;
+#endif
+}
+
+}
diff --git a/lib/kokkos/core/unit_test/TestCXX11Deduction.hpp b/lib/kokkos/core/unit_test/TestCXX11Deduction.hpp
new file mode 100644
index 0000000000..359e17a44f
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestCXX11Deduction.hpp
@@ -0,0 +1,94 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+#include <Kokkos_Core.hpp>
+
+#ifndef TESTCXX11DEDUCTION_HPP
+#define TESTCXX11DEDUCTION_HPP
+
+namespace TestCXX11 {
+
+struct TestReductionDeductionTagA {};
+struct TestReductionDeductionTagB {};
+
+template < class ExecSpace >
+struct TestReductionDeductionFunctor {
+
+  // KOKKOS_INLINE_FUNCTION
+  // void operator()( long i , long & value ) const
+  // { value += i + 1 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( TestReductionDeductionTagA , long i , long & value ) const
+  { value += ( 2 * i + 1 ) + ( 2 * i + 2 ); }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TestReductionDeductionTagB & , const long i , long & value ) const
+  { value += ( 3 * i + 1 ) + ( 3 * i + 2 ) + ( 3 * i + 3 ) ; }
+
+};
+
+template< class ExecSpace >
+void test_reduction_deduction()
+{
+  typedef TestReductionDeductionFunctor< ExecSpace > Functor ;
+
+  const long N = 50 ;
+  // const long answer  = N % 2 ? ( N * ((N+1)/2 )) : ( (N/2) * (N+1) );
+  const long answerA = N % 2 ? ( (2*N) * (((2*N)+1)/2 )) : ( ((2*N)/2) * ((2*N)+1) );
+  const long answerB = N % 2 ? ( (3*N) * (((3*N)+1)/2 )) : ( ((3*N)/2) * ((3*N)+1) );
+  long result = 0 ;
+
+  // Kokkos::parallel_reduce( Kokkos::RangePolicy<ExecSpace>(0,N) , Functor() , result );
+  // ASSERT_EQ( answer , result );
+  
+  Kokkos::parallel_reduce( Kokkos::RangePolicy<ExecSpace,TestReductionDeductionTagA>(0,N) , Functor() , result );
+  ASSERT_EQ( answerA , result );
+  
+  Kokkos::parallel_reduce( Kokkos::RangePolicy<ExecSpace,TestReductionDeductionTagB>(0,N) , Functor() , result );
+  ASSERT_EQ( answerB , result );
+}
+
+}
+
+#endif
+
diff --git a/lib/kokkos/core/unit_test/TestCompilerMacros.hpp b/lib/kokkos/core/unit_test/TestCompilerMacros.hpp
new file mode 100644
index 0000000000..dfa2250c04
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestCompilerMacros.hpp
@@ -0,0 +1,93 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#define KOKKOS_PRAGMA_UNROLL(a)
+
+namespace TestCompilerMacros {
+
+template<class DEVICE_TYPE>
+struct AddFunctor {
+  typedef DEVICE_TYPE execution_space;
+  typedef typename Kokkos::View<int**,execution_space> type;
+  type a,b;
+  int length;
+
+  AddFunctor(type a_, type b_):a(a_),b(b_),length(a.dimension_1()) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int i) const {
+#ifdef KOKKOS_HAVE_PRAGMA_UNROLL
+    #pragma unroll
+#endif
+#ifdef KOKKOS_HAVE_PRAGMA_IVDEP
+    #pragma ivdep
+#endif
+#ifdef KOKKOS_HAVE_PRAGMA_VECTOR
+    #pragma vector always
+#endif
+#ifdef KOKKOS_HAVE_PRAGMA_LOOPCOUNT
+    #pragma loop count(128)
+#endif
+#ifdef KOKKOS_HAVE_PRAGMA_SIMD
+    #pragma simd
+#endif
+    for(int j=0;j<length;j++)
+      a(i,j) += b(i,j);
+  }
+};
+
+template<class DeviceType>
+bool Test() {
+  typedef typename Kokkos::View<int**,DeviceType> type;
+  type a("A",1024,128);
+  type b("B",1024,128);
+
+  AddFunctor<DeviceType> f(a,b);
+  Kokkos::parallel_for(1024,f);
+  DeviceType::fence();
+  return true;
+}
+
+}
diff --git a/lib/kokkos/core/unit_test/TestCuda.cpp b/lib/kokkos/core/unit_test/TestCuda.cpp
new file mode 100644
index 0000000000..e615566252
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestCuda.cpp
@@ -0,0 +1,290 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <Cuda/Kokkos_Cuda_TaskPolicy.hpp>
+#include <impl/Kokkos_ViewTileLeft.hpp>
+#include <TestTile.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestMemoryPool.hpp>
+#include <TestTeamVector.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+#include <TestCXX11Deduction.hpp>
+
+#include <TestTaskPolicy.hpp>
+#include <TestPolicyConstruction.hpp>
+
+#include <TestMDRange.hpp>
+
+//----------------------------------------------------------------------------
+
+class cuda : public ::testing::Test {
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+void cuda::SetUpTestCase()
+  {
+    Kokkos::Cuda::print_configuration( std::cout );
+    Kokkos::HostSpace::execution_space::initialize();
+    Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice(0) );
+  }
+
+void cuda::TearDownTestCase()
+  {
+    Kokkos::Cuda::finalize();
+    Kokkos::HostSpace::execution_space::finalize();
+  }
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Test {
+
+__global__
+void test_abort()
+{
+  Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<
+    Kokkos::CudaSpace ,
+    Kokkos::HostSpace >::verify();
+}
+
+__global__
+void test_cuda_spaces_int_value( int * ptr )
+{
+  if ( *ptr == 42 ) { *ptr = 2 * 42 ; }
+}
+
+TEST_F( cuda , md_range ) {
+  TestMDRange_2D< Kokkos::Cuda >::test_for2(100,100);
+
+  TestMDRange_3D< Kokkos::Cuda >::test_for3(100,100,100);
+}
+
+TEST_F( cuda , compiler_macros )
+{
+  ASSERT_TRUE( ( TestCompilerMacros::Test< Kokkos::Cuda >() ) );
+}
+
+TEST_F( cuda , memory_space )
+{
+  TestMemorySpace< Kokkos::Cuda >();
+}
+
+TEST_F( cuda, uvm )
+{
+  if ( Kokkos::CudaUVMSpace::available() ) {
+
+    int * uvm_ptr = (int*) Kokkos::kokkos_malloc< Kokkos::CudaUVMSpace >("uvm_ptr",sizeof(int));
+
+    *uvm_ptr = 42 ;
+
+    Kokkos::Cuda::fence();
+    test_cuda_spaces_int_value<<<1,1>>>(uvm_ptr);
+    Kokkos::Cuda::fence();
+
+    EXPECT_EQ( *uvm_ptr, int(2*42) );
+
+    Kokkos::kokkos_free< Kokkos::CudaUVMSpace >(uvm_ptr );
+  }
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( cuda , impl_shared_alloc )
+{
+  test_shared_alloc< Kokkos::CudaSpace , Kokkos::HostSpace::execution_space >();
+  test_shared_alloc< Kokkos::CudaUVMSpace , Kokkos::HostSpace::execution_space >();
+  test_shared_alloc< Kokkos::CudaHostPinnedSpace , Kokkos::HostSpace::execution_space >();
+}
+
+TEST_F( cuda, policy_construction) {
+  TestRangePolicyConstruction< Kokkos::Cuda >();
+  TestTeamPolicyConstruction< Kokkos::Cuda >();
+}
+
+TEST_F( cuda , impl_view_mapping )
+{
+  test_view_mapping< Kokkos::Cuda >();
+  test_view_mapping< Kokkos::CudaUVMSpace >();
+  test_view_mapping_subview< Kokkos::Cuda >();
+  test_view_mapping_subview< Kokkos::CudaUVMSpace >();
+  test_view_mapping_operator< Kokkos::Cuda >();
+  test_view_mapping_operator< Kokkos::CudaUVMSpace >();
+  TestViewMappingAtomic< Kokkos::Cuda >::run();
+}
+
+TEST_F( cuda , view_of_class )
+{
+  TestViewMappingClassValue< Kokkos::CudaSpace >::run();
+  TestViewMappingClassValue< Kokkos::CudaUVMSpace >::run();
+}
+
+template< class MemSpace >
+struct TestViewCudaTexture {
+
+  enum { N = 1000 };
+
+  using V = Kokkos::Experimental::View<double*,MemSpace> ;
+  using T = Kokkos::Experimental::View<const double*, MemSpace, Kokkos::MemoryRandomAccess > ;
+
+  V m_base ;
+  T m_tex ;
+
+  struct TagInit {};
+  struct TagTest {};
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TagInit & , const int i ) const { m_base[i] = i + 1 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TagTest & , const int i , long & error_count ) const
+    { if ( m_tex[i] != i + 1 ) ++error_count ; }
+
+  TestViewCudaTexture()
+    : m_base("base",N)
+    , m_tex( m_base )
+    {}
+
+  static void run()
+    {
+      EXPECT_TRUE( ( std::is_same< typename V::reference_type
+                                 , double &
+                                 >::value ) );
+
+      EXPECT_TRUE( ( std::is_same< typename T::reference_type
+                                 , const double
+                                 >::value ) );
+
+      EXPECT_TRUE(  V::reference_type_is_lvalue_reference ); // An ordinary view
+      EXPECT_FALSE( T::reference_type_is_lvalue_reference ); // Texture fetch returns by value
+
+      TestViewCudaTexture self ;
+      Kokkos::parallel_for( Kokkos::RangePolicy< Kokkos::Cuda , TagInit >(0,N) , self );
+      long error_count = -1 ;
+      Kokkos::parallel_reduce( Kokkos::RangePolicy< Kokkos::Cuda , TagTest >(0,N) , self , error_count );
+      EXPECT_EQ( error_count , 0 );
+    }
+};
+
+TEST_F( cuda , impl_view_texture )
+{
+  TestViewCudaTexture< Kokkos::CudaSpace >::run();
+  TestViewCudaTexture< Kokkos::CudaUVMSpace >::run();
+}
+
+template< class MemSpace , class ExecSpace >
+struct TestViewCudaAccessible {
+
+  enum { N = 1000 };
+
+  using V = Kokkos::Experimental::View<double*,MemSpace> ;
+
+  V m_base ;
+
+  struct TagInit {};
+  struct TagTest {};
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TagInit & , const int i ) const { m_base[i] = i + 1 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TagTest & , const int i , long & error_count ) const
+    { if ( m_base[i] != i + 1 ) ++error_count ; }
+
+  TestViewCudaAccessible()
+    : m_base("base",N)
+    {}
+
+  static void run()
+    {
+      TestViewCudaAccessible self ;
+      Kokkos::parallel_for( Kokkos::RangePolicy< typename MemSpace::execution_space , TagInit >(0,N) , self );
+      MemSpace::execution_space::fence();
+      // Next access is a different execution space, must complete prior kernel.
+      long error_count = -1 ;
+      Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , TagTest >(0,N) , self , error_count );
+      EXPECT_EQ( error_count , 0 );
+    }
+};
+
+TEST_F( cuda , impl_view_accessible )
+{
+  TestViewCudaAccessible< Kokkos::CudaSpace , Kokkos::Cuda >::run();
+
+  TestViewCudaAccessible< Kokkos::CudaUVMSpace , Kokkos::Cuda >::run();
+  TestViewCudaAccessible< Kokkos::CudaUVMSpace , Kokkos::HostSpace::execution_space >::run();
+
+  TestViewCudaAccessible< Kokkos::CudaHostPinnedSpace , Kokkos::Cuda >::run();
+  TestViewCudaAccessible< Kokkos::CudaHostPinnedSpace , Kokkos::HostSpace::execution_space >::run();
+}
+
+}
diff --git a/lib/kokkos/core/unit_test/TestCuda_a.cpp b/lib/kokkos/core/unit_test/TestCuda_a.cpp
new file mode 100644
index 0000000000..4680c33386
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestCuda_a.cpp
@@ -0,0 +1,182 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <Cuda/Kokkos_Cuda_TaskPolicy.hpp>
+#include <impl/Kokkos_ViewTileLeft.hpp>
+#include <TestTile.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestMemoryPool.hpp>
+#include <TestTeamVector.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+#include <TestCXX11Deduction.hpp>
+
+#include <TestTaskPolicy.hpp>
+#include <TestPolicyConstruction.hpp>
+
+//----------------------------------------------------------------------------
+
+class cuda : public ::testing::Test {
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+//----------------------------------------------------------------------------
+
+namespace Test {
+
+TEST_F( cuda, view_impl )
+{
+  // test_abort<<<32,32>>>(); // Aborts the kernel with CUDA version 4.1 or greater
+
+  test_view_impl< Kokkos::Cuda >();
+}
+
+TEST_F( cuda, view_api )
+{
+  typedef Kokkos::View< const int * , Kokkos::Cuda , Kokkos::MemoryTraits< Kokkos::RandomAccess > > view_texture_managed ;
+  typedef Kokkos::View< const int * , Kokkos::Cuda , Kokkos::MemoryTraits< Kokkos::RandomAccess | Kokkos::Unmanaged > > view_texture_unmanaged ;
+
+  TestViewAPI< double , Kokkos::Cuda >();
+  TestViewAPI< double , Kokkos::CudaUVMSpace >();
+
+#if 0
+  Kokkos::View<double, Kokkos::Cuda > x("x");
+  Kokkos::View<double[1], Kokkos::Cuda > y("y");
+  // *x = 10 ;
+  // x() = 10 ;
+  // y[0] = 10 ;
+  // y(0) = 10 ;
+#endif
+}
+
+TEST_F( cuda , view_nested_view )
+{
+  ::Test::view_nested_view< Kokkos::Cuda >();
+}
+
+TEST_F( cuda, view_subview_auto_1d_left ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutLeft,Kokkos::Cuda >();
+}
+
+TEST_F( cuda, view_subview_auto_1d_right ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutRight,Kokkos::Cuda >();
+}
+
+TEST_F( cuda, view_subview_auto_1d_stride ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutStride,Kokkos::Cuda >();
+}
+
+TEST_F( cuda, view_subview_assign_strided ) {
+  TestViewSubview::test_1d_strided_assignment< Kokkos::Cuda >();
+}
+
+TEST_F( cuda, view_subview_left_0 ) {
+  TestViewSubview::test_left_0< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_left_1 ) {
+  TestViewSubview::test_left_1< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_left_2 ) {
+  TestViewSubview::test_left_2< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_left_3 ) {
+  TestViewSubview::test_left_3< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_right_0 ) {
+  TestViewSubview::test_right_0< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_right_1 ) {
+  TestViewSubview::test_right_1< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_right_3 ) {
+  TestViewSubview::test_right_3< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_1d_assign ) {
+  TestViewSubview::test_1d_assign< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_2d_from_3d ) {
+  TestViewSubview::test_2d_subview_3d< Kokkos::CudaUVMSpace >();
+}
+
+TEST_F( cuda, view_subview_2d_from_5d ) {
+  TestViewSubview::test_2d_subview_5d< Kokkos::CudaUVMSpace >();
+}
+
+}
diff --git a/lib/kokkos/core/unit_test/TestCuda_b.cpp b/lib/kokkos/core/unit_test/TestCuda_b.cpp
new file mode 100644
index 0000000000..d4ca949e57
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestCuda_b.cpp
@@ -0,0 +1,191 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <Cuda/Kokkos_Cuda_TaskPolicy.hpp>
+#include <impl/Kokkos_ViewTileLeft.hpp>
+#include <TestTile.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestMemoryPool.hpp>
+#include <TestTeamVector.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+#include <TestCXX11Deduction.hpp>
+
+#include <TestTaskPolicy.hpp>
+#include <TestPolicyConstruction.hpp>
+
+//----------------------------------------------------------------------------
+
+class cuda : public ::testing::Test {
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+//----------------------------------------------------------------------------
+
+namespace Test {
+
+TEST_F( cuda, range_tag )
+{
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_for(3);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_reduce(3);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_scan(3);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(3);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(3);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_scan(3);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_scan(1000);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(1001);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(1001);
+  TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_scan(1001);
+  //TestRange< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_dynamic_policy(1000);
+}
+
+TEST_F( cuda, team_tag )
+{
+  TestTeamPolicy< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_for(3);
+  TestTeamPolicy< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_reduce(3);
+  TestTeamPolicy< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(3);
+  TestTeamPolicy< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(3);
+  TestTeamPolicy< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestTeamPolicy< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestTeamPolicy< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(1000);
+  TestTeamPolicy< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(1000);
+}
+
+TEST_F( cuda, reduce )
+{
+  TestReduce< long ,   Kokkos::Cuda >( 10000000 );
+  TestReduce< double , Kokkos::Cuda >( 1000000 );
+  TestReduce< int , Kokkos::Cuda >( 0 );
+}
+
+TEST_F( cuda , reducers )
+{
+  TestReducers<int, Kokkos::Cuda>::execute_integer();
+  TestReducers<size_t, Kokkos::Cuda>::execute_integer();
+  TestReducers<double, Kokkos::Cuda>::execute_float();
+  TestReducers<Kokkos::complex<double>, Kokkos::Cuda>::execute_basic();
+}
+
+TEST_F( cuda, reduce_team )
+{
+  TestReduceTeam< long ,   Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >( 3 );
+  TestReduceTeam< long ,   Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >( 3 );
+  TestReduceTeam< long ,   Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >( 100000 );
+  TestReduceTeam< long ,   Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >( 100000 );
+  TestReduceTeam< double ,   Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >( 3 );
+  TestReduceTeam< double ,   Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >( 3 );
+  TestReduceTeam< double ,   Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >( 100000 );
+  TestReduceTeam< double ,   Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >( 100000 );
+}
+
+TEST_F( cuda, shared_team )
+{
+  TestSharedTeam< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >();
+  TestSharedTeam< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+
+#if defined (KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+TEST_F( cuda, lambda_shared_team )
+{
+  TestLambdaSharedTeam< Kokkos::CudaSpace, Kokkos::Cuda, Kokkos::Schedule<Kokkos::Static> >();
+  TestLambdaSharedTeam< Kokkos::CudaUVMSpace, Kokkos::Cuda, Kokkos::Schedule<Kokkos::Static> >();
+  TestLambdaSharedTeam< Kokkos::CudaHostPinnedSpace, Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static>  >();
+  TestLambdaSharedTeam< Kokkos::CudaSpace, Kokkos::Cuda, Kokkos::Schedule<Kokkos::Dynamic> >();
+  TestLambdaSharedTeam< Kokkos::CudaUVMSpace, Kokkos::Cuda, Kokkos::Schedule<Kokkos::Dynamic> >();
+  TestLambdaSharedTeam< Kokkos::CudaHostPinnedSpace, Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic>  >();
+}
+#endif
+
+TEST_F( cuda, shmem_size) {
+  TestShmemSize< Kokkos::Cuda >();
+}
+
+TEST_F( cuda, multi_level_scratch) {
+  TestMultiLevelScratchTeam< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >();
+  TestMultiLevelScratchTeam< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+
+TEST_F( cuda, reduce_dynamic )
+{
+  TestReduceDynamic< long ,   Kokkos::Cuda >( 10000000 );
+  TestReduceDynamic< double , Kokkos::Cuda >( 1000000 );
+}
+
+TEST_F( cuda, reduce_dynamic_view )
+{
+  TestReduceDynamicView< long ,   Kokkos::Cuda >( 10000000 );
+  TestReduceDynamicView< double , Kokkos::Cuda >( 1000000 );
+}
+
+}
diff --git a/lib/kokkos/core/unit_test/TestCuda_c.cpp b/lib/kokkos/core/unit_test/TestCuda_c.cpp
new file mode 100644
index 0000000000..70584cead1
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestCuda_c.cpp
@@ -0,0 +1,375 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <Cuda/Kokkos_Cuda_TaskPolicy.hpp>
+#include <impl/Kokkos_ViewTileLeft.hpp>
+#include <TestTile.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+#include <TestAtomicOperations.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestMemoryPool.hpp>
+#include <TestTeamVector.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+#include <TestCXX11Deduction.hpp>
+
+#include <TestTaskPolicy.hpp>
+#include <TestPolicyConstruction.hpp>
+
+//----------------------------------------------------------------------------
+
+class cuda : public ::testing::Test {
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+//----------------------------------------------------------------------------
+
+namespace Test {
+
+TEST_F( cuda, atomic )
+{
+  const int loop_count = 1e3 ;
+
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Cuda>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Cuda>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Cuda>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Cuda>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Cuda>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Cuda>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Cuda>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Cuda>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Cuda>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Cuda>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Cuda>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Cuda>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Cuda>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Cuda>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Cuda>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Cuda>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Cuda>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Cuda>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Cuda>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Cuda>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Cuda>(100,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Cuda>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Cuda>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Cuda>(100,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::Cuda>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::Cuda>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::Cuda>(100,3) ) );
+
+}
+
+TEST_F( cuda , atomic_operations )
+{
+  const int start = 1; //Avoid zero for division
+  const int end = 11;
+  for (int i = start; i < end; ++i)
+  {
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Cuda>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Cuda>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Cuda>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Cuda>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Cuda>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Cuda>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Cuda>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Cuda>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Cuda>(start, end-i, 4 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Cuda>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Cuda>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Cuda>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Cuda>(start, end-i, 4 ) ) );
+  }
+
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( cuda, tile_layout)
+{
+  TestTile::test< Kokkos::Cuda , 1 , 1 >( 1 , 1 );
+  TestTile::test< Kokkos::Cuda , 1 , 1 >( 2 , 3 );
+  TestTile::test< Kokkos::Cuda , 1 , 1 >( 9 , 10 );
+
+  TestTile::test< Kokkos::Cuda , 2 , 2 >( 1 , 1 );
+  TestTile::test< Kokkos::Cuda , 2 , 2 >( 2 , 3 );
+  TestTile::test< Kokkos::Cuda , 2 , 2 >( 4 , 4 );
+  TestTile::test< Kokkos::Cuda , 2 , 2 >( 9 , 9 );
+
+  TestTile::test< Kokkos::Cuda , 2 , 4 >( 9 , 9 );
+  TestTile::test< Kokkos::Cuda , 4 , 4 >( 9 , 9 );
+
+  TestTile::test< Kokkos::Cuda , 4 , 4 >( 1 , 1 );
+  TestTile::test< Kokkos::Cuda , 4 , 4 >( 4 , 4 );
+  TestTile::test< Kokkos::Cuda , 4 , 4 >( 9 , 9 );
+  TestTile::test< Kokkos::Cuda , 4 , 4 >( 9 , 11 );
+
+  TestTile::test< Kokkos::Cuda , 8 , 8 >( 1 , 1 );
+  TestTile::test< Kokkos::Cuda , 8 , 8 >( 4 , 4 );
+  TestTile::test< Kokkos::Cuda , 8 , 8 >( 9 , 9 );
+  TestTile::test< Kokkos::Cuda , 8 , 8 >( 9 , 11 );
+}
+
+TEST_F( cuda , view_aggregate )
+{
+  TestViewAggregate< Kokkos::Cuda >();
+  TestViewAggregateReduction< Kokkos::Cuda >();
+}
+
+TEST_F( cuda , scan )
+{
+  TestScan< Kokkos::Cuda >::test_range( 1 , 1000 );
+  TestScan< Kokkos::Cuda >( 1000000 );
+  TestScan< Kokkos::Cuda >( 10000000 );
+
+  TestScan< Kokkos::Cuda >( 0 );
+  TestScan< Kokkos::Cuda >( 0 , 0 );
+
+  Kokkos::Cuda::fence();
+}
+
+TEST_F( cuda , team_scan )
+{
+  TestScanTeam< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >( 10 );
+  TestScanTeam< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >( 10 );
+  TestScanTeam< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Static> >( 10000 );
+  TestScanTeam< Kokkos::Cuda , Kokkos::Schedule<Kokkos::Dynamic> >( 10000 );
+}
+
+TEST_F( cuda , memory_pool )
+{
+//  typedef Kokkos::CudaUVMSpace  device_type;
+  typedef Kokkos::Cuda          device_type;
+
+  bool val = TestMemoryPool::test_mempool< device_type >( 128, 128000000 );
+  ASSERT_TRUE( val );
+
+  Kokkos::Cuda::fence();
+
+  TestMemoryPool::test_mempool2< device_type >( 64, 4, 100000, 200000 );
+
+  Kokkos::Cuda::fence();
+
+  TestMemoryPool::test_memory_exhaustion< Kokkos::Cuda >();
+
+  Kokkos::Cuda::fence();
+}
+
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( cuda , template_meta_functions )
+{
+  TestTemplateMetaFunctions<int, Kokkos::Cuda >();
+}
+
+//----------------------------------------------------------------------------
+
+namespace Test {
+
+TEST_F( cuda , reduction_deduction )
+{
+  TestCXX11::test_reduction_deduction< Kokkos::Cuda >();
+}
+
+TEST_F( cuda , team_vector )
+{
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(0) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(1) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(2) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(3) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(4) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(5) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(6) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(7) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(8) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(9) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Cuda >(10) ) );
+}
+
+TEST_F( cuda, triple_nested_parallelism )
+{
+  TestTripleNestedReduce< double, Kokkos::Cuda >( 8192, 2048 , 32 , 32 );
+  TestTripleNestedReduce< double, Kokkos::Cuda >( 8192, 2048 , 32 , 16 );
+  TestTripleNestedReduce< double, Kokkos::Cuda >( 8192, 2048 , 16 , 16 );
+}
+
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+TEST_F( cuda , task_fib )
+{
+  for ( int i = 0 ; i < 25 ; ++i ) {
+    TestTaskPolicy::TestFib< Kokkos::Cuda >::run(i, (i+1)*1000000 );
+  }
+}
+
+TEST_F( cuda , task_depend )
+{
+  for ( int i = 0 ; i < 25 ; ++i ) {
+    TestTaskPolicy::TestTaskDependence< Kokkos::Cuda >::run(i);
+  }
+}
+
+TEST_F( cuda , task_team )
+{
+  //TestTaskPolicy::TestTaskTeam< Kokkos::Cuda >::run(1000);
+  TestTaskPolicy::TestTaskTeam< Kokkos::Cuda >::run(104);
+  TestTaskPolicy::TestTaskTeamValue< Kokkos::Cuda >::run(1000);
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( cuda , old_task_policy )
+{
+  TestTaskPolicy::test_task_dep< Kokkos::Cuda >( 10 );
+
+  for ( long i = 0 ; i < 15 ; ++i ) {
+      // printf("TestTaskPolicy::test_fib< Kokkos::Cuda >(%d);\n",i);
+    TestTaskPolicy::test_fib< Kokkos::Cuda >(i,4096);
+  }
+  for ( long i = 0 ; i < 35 ; ++i ) {
+      // printf("TestTaskPolicy::test_fib2< Kokkos::Cuda >(%d);\n",i);
+    TestTaskPolicy::test_fib2< Kokkos::Cuda >(i,4096);
+  }
+}
+
+TEST_F( cuda , old_task_team )
+{
+  TestTaskPolicy::test_task_team< Kokkos::Cuda >(1000);
+}
+
+TEST_F( cuda , old_task_latch )
+{
+  TestTaskPolicy::test_latch< Kokkos::Cuda >(10);
+  TestTaskPolicy::test_latch< Kokkos::Cuda >(1000);
+}
+
+#endif // #if defined( KOKKOS_ENABLE_TASKPOLICY )
+
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceType.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceType.cpp
new file mode 100644
index 0000000000..1b1e0e6736
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceType.cpp
@@ -0,0 +1,242 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#if !defined(KOKKOS_HAVE_CUDA) || defined(__CUDACC__)
+//----------------------------------------------------------------------------
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+
+#include <TestViewAPI.hpp>
+
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestTeam.hpp>
+#include <TestAggregate.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestCXX11.hpp>
+#include <TestTeamVector.hpp>
+
+namespace Test {
+
+class defaultdevicetype : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    Kokkos::initialize();
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::finalize();
+  }
+};
+
+
+TEST_F( defaultdevicetype, view_impl) {
+  test_view_impl< Kokkos::DefaultExecutionSpace >();
+}
+
+TEST_F( defaultdevicetype, view_api) {
+  TestViewAPI< double , Kokkos::DefaultExecutionSpace >();
+}
+
+TEST_F( defaultdevicetype, long_reduce) {
+  TestReduce< long ,   Kokkos::DefaultExecutionSpace >( 100000 );
+}
+
+TEST_F( defaultdevicetype, double_reduce) {
+  TestReduce< double ,   Kokkos::DefaultExecutionSpace >( 100000 );
+}
+
+TEST_F( defaultdevicetype, long_reduce_dynamic ) {
+  TestReduceDynamic< long ,   Kokkos::DefaultExecutionSpace >( 100000 );
+}
+
+TEST_F( defaultdevicetype, double_reduce_dynamic ) {
+  TestReduceDynamic< double ,   Kokkos::DefaultExecutionSpace >( 100000 );
+}
+
+TEST_F( defaultdevicetype, long_reduce_dynamic_view ) {
+  TestReduceDynamicView< long ,   Kokkos::DefaultExecutionSpace >( 100000 );
+}
+
+
+TEST_F( defaultdevicetype , atomics )
+{
+  const int loop_count = 1e4 ;
+
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::DefaultExecutionSpace>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::DefaultExecutionSpace>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::DefaultExecutionSpace>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::DefaultExecutionSpace>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::DefaultExecutionSpace>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::DefaultExecutionSpace>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::DefaultExecutionSpace>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::DefaultExecutionSpace>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::DefaultExecutionSpace>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::DefaultExecutionSpace>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::DefaultExecutionSpace>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::DefaultExecutionSpace>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::DefaultExecutionSpace>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::DefaultExecutionSpace>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::DefaultExecutionSpace>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::DefaultExecutionSpace>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::DefaultExecutionSpace>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::DefaultExecutionSpace>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::DefaultExecutionSpace>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::DefaultExecutionSpace>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::DefaultExecutionSpace>(100,3) ) );
+}
+
+/*TEST_F( defaultdevicetype , view_remap )
+{
+  enum { N0 = 3 , N1 = 2 , N2 = 8 , N3 = 9 };
+
+  typedef Kokkos::View< double*[N1][N2][N3] ,
+                             Kokkos::LayoutRight ,
+                             Kokkos::DefaultExecutionSpace > output_type ;
+
+  typedef Kokkos::View< int**[N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::DefaultExecutionSpace > input_type ;
+
+  typedef Kokkos::View< int*[N0][N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::DefaultExecutionSpace > diff_type ;
+
+  output_type output( "output" , N0 );
+  input_type  input ( "input" , N0 , N1 );
+  diff_type   diff  ( "diff" , N0 );
+
+  int value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    input(i0,i1,i2,i3) = ++value ;
+  }}}}
+
+  // Kokkos::deep_copy( diff , input ); // throw with incompatible shape
+  Kokkos::deep_copy( output , input );
+
+  value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    ++value ;
+    ASSERT_EQ( value , ((int) output(i0,i1,i2,i3) ) );
+  }}}}
+}*/
+
+//----------------------------------------------------------------------------
+
+
+TEST_F( defaultdevicetype , view_aggregate )
+{
+  TestViewAggregate< Kokkos::DefaultExecutionSpace >();
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( defaultdevicetype , scan )
+{
+  TestScan< Kokkos::DefaultExecutionSpace >::test_range( 1 , 1000 );
+  TestScan< Kokkos::DefaultExecutionSpace >( 1000000 );
+  TestScan< Kokkos::DefaultExecutionSpace >( 10000000 );
+  Kokkos::DefaultExecutionSpace::fence();
+}
+
+
+//----------------------------------------------------------------------------
+
+TEST_F( defaultdevicetype , compiler_macros )
+{
+  ASSERT_TRUE( ( TestCompilerMacros::Test< Kokkos::DefaultExecutionSpace >() ) );
+}
+
+
+//----------------------------------------------------------------------------
+TEST_F( defaultdevicetype , cxx11 )
+{
+  ASSERT_TRUE( ( TestCXX11::Test< Kokkos::DefaultExecutionSpace >(1) ) );
+  ASSERT_TRUE( ( TestCXX11::Test< Kokkos::DefaultExecutionSpace >(2) ) );
+  ASSERT_TRUE( ( TestCXX11::Test< Kokkos::DefaultExecutionSpace >(3) ) );
+  ASSERT_TRUE( ( TestCXX11::Test< Kokkos::DefaultExecutionSpace >(4) ) );
+}
+
+TEST_F( defaultdevicetype , team_vector )
+{
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::DefaultExecutionSpace >(0) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::DefaultExecutionSpace >(1) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::DefaultExecutionSpace >(2) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::DefaultExecutionSpace >(3) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::DefaultExecutionSpace >(4) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::DefaultExecutionSpace >(5) ) );
+}
+
+TEST_F( defaultdevicetype , malloc )
+{
+  int* data = (int*) Kokkos::kokkos_malloc(100*sizeof(int));
+  ASSERT_NO_THROW(data = (int*) Kokkos::kokkos_realloc(data,120*sizeof(int)));
+  Kokkos::kokkos_free(data);
+
+  int* data2 = (int*) Kokkos::kokkos_malloc(0);
+  ASSERT_TRUE(data2==NULL);
+  Kokkos::kokkos_free(data2);
+}
+
+} // namespace test
+
+#endif
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit.hpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit.hpp
new file mode 100644
index 0000000000..a17ed97a9f
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit.hpp
@@ -0,0 +1,419 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+#ifdef KOKKOS_HAVE_OPENMP
+#include <omp.h>
+#endif
+
+#if !defined(KOKKOS_HAVE_CUDA) || defined(__CUDACC__)
+//----------------------------------------------------------------------------
+
+namespace Test {
+
+namespace Impl {
+
+  char** init_kokkos_args(bool do_threads,bool do_numa,bool do_device,bool do_other, int& nargs, Kokkos::InitArguments& init_args) {
+    nargs = (do_threads?1:0) +
+            (do_numa?1:0) +
+            (do_device?1:0) +
+            (do_other?4:0);
+    char** args_kokkos = new char*[nargs];
+    for(int i = 0; i < nargs; i++)
+      args_kokkos[i] = new char[20];
+
+    int threads_idx = do_other?1:0;
+    int numa_idx = (do_other?3:0) + (do_threads?1:0);
+    int device_idx = (do_other?3:0) + (do_threads?1:0) + (do_numa?1:0);
+
+
+    if(do_threads) {
+      int nthreads = 3;
+
+#ifdef KOKKOS_HAVE_OPENMP
+      if(omp_get_max_threads() < 3)
+        nthreads = omp_get_max_threads();
+#endif
+
+      if(Kokkos::hwloc::available())  {
+        if(Kokkos::hwloc::get_available_threads_per_core()<3)
+            nthreads =   Kokkos::hwloc::get_available_threads_per_core()
+                       * Kokkos::hwloc::get_available_numa_count();
+      }
+
+#ifdef KOKKOS_HAVE_SERIAL
+      if(Kokkos::Impl::is_same<Kokkos::Serial,Kokkos::DefaultExecutionSpace>::value ||
+         Kokkos::Impl::is_same<Kokkos::Serial,Kokkos::DefaultHostExecutionSpace>::value ) {
+        nthreads = 1;
+      }
+#endif
+      init_args.num_threads = nthreads;
+      sprintf(args_kokkos[threads_idx],"--threads=%i",nthreads);
+    }
+
+    if(do_numa) {
+      int numa = 1;
+      if(Kokkos::hwloc::available())
+        numa = Kokkos::hwloc::get_available_numa_count();
+#ifdef KOKKOS_HAVE_SERIAL
+      if(Kokkos::Impl::is_same<Kokkos::Serial,Kokkos::DefaultExecutionSpace>::value ||
+         Kokkos::Impl::is_same<Kokkos::Serial,Kokkos::DefaultHostExecutionSpace>::value ) {
+        numa = 1;
+      }
+#endif
+
+      init_args.num_numa = numa;
+      sprintf(args_kokkos[numa_idx],"--numa=%i",numa);
+    }
+
+    if(do_device) {
+
+      init_args.device_id = 0;
+      sprintf(args_kokkos[device_idx],"--device=%i",0);
+    }
+
+    if(do_other) {
+      sprintf(args_kokkos[0],"--dummyarg=1");
+      sprintf(args_kokkos[threads_idx+(do_threads?1:0)],"--dummy2arg");
+      sprintf(args_kokkos[threads_idx+(do_threads?1:0)+1],"dummy3arg");
+      sprintf(args_kokkos[device_idx+(do_device?1:0)],"dummy4arg=1");
+    }
+
+
+    return args_kokkos;
+  }
+
+  Kokkos::InitArguments init_initstruct(bool do_threads, bool do_numa, bool do_device) {
+    Kokkos::InitArguments args;
+
+    if(do_threads) {
+      int nthreads = 3;
+
+#ifdef KOKKOS_HAVE_OPENMP
+      if(omp_get_max_threads() < 3)
+        nthreads = omp_get_max_threads();
+#endif
+
+      if(Kokkos::hwloc::available())  {
+        if(Kokkos::hwloc::get_available_threads_per_core()<3)
+            nthreads =   Kokkos::hwloc::get_available_threads_per_core()
+                       * Kokkos::hwloc::get_available_numa_count();
+      }
+#ifdef KOKKOS_HAVE_SERIAL
+      if(Kokkos::Impl::is_same<Kokkos::Serial,Kokkos::DefaultExecutionSpace>::value ||
+         Kokkos::Impl::is_same<Kokkos::Serial,Kokkos::DefaultHostExecutionSpace>::value ) {
+        nthreads = 1;
+      }
+#endif
+
+      args.num_threads = nthreads;
+    }
+
+    if(do_numa) {
+      int numa = 1;
+      if(Kokkos::hwloc::available())
+        numa = Kokkos::hwloc::get_available_numa_count();
+#ifdef KOKKOS_HAVE_SERIAL
+      if(Kokkos::Impl::is_same<Kokkos::Serial,Kokkos::DefaultExecutionSpace>::value ||
+         Kokkos::Impl::is_same<Kokkos::Serial,Kokkos::DefaultHostExecutionSpace>::value ) {
+        numa = 1;
+      }
+#endif
+      args.num_numa = numa;
+    }
+
+    if(do_device) {
+      args.device_id = 0;
+    }
+
+    return args;
+  }
+
+  void check_correct_initialization(const Kokkos::InitArguments& argstruct) {
+    ASSERT_EQ( Kokkos::DefaultExecutionSpace::is_initialized(), 1);
+    ASSERT_EQ( Kokkos::HostSpace::execution_space::is_initialized(), 1);
+
+    //Figure out the number of threads the HostSpace ExecutionSpace should have initialized to
+    int expected_nthreads = argstruct.num_threads;
+    if(expected_nthreads<1) {
+      if(Kokkos::hwloc::available()) {
+        expected_nthreads = Kokkos::hwloc::get_available_numa_count()
+                          * Kokkos::hwloc::get_available_cores_per_numa()
+                          * Kokkos::hwloc::get_available_threads_per_core();
+      } else {
+        #ifdef KOKKOS_HAVE_OPENMP
+        if(Kokkos::Impl::is_same<Kokkos::HostSpace::execution_space,Kokkos::OpenMP>::value) {
+          expected_nthreads = omp_get_max_threads();
+        } else
+        #endif
+          expected_nthreads = 1;
+
+      }
+      #ifdef KOKKOS_HAVE_SERIAL
+      if(Kokkos::Impl::is_same<Kokkos::DefaultExecutionSpace,Kokkos::Serial>::value ||
+         Kokkos::Impl::is_same<Kokkos::DefaultHostExecutionSpace,Kokkos::Serial>::value ) 
+        expected_nthreads = 1;
+      #endif
+    }
+
+    int expected_numa = argstruct.num_numa;
+    if(expected_numa<1) {
+      if(Kokkos::hwloc::available()) {
+        expected_numa = Kokkos::hwloc::get_available_numa_count();
+      } else {
+        expected_numa = 1;
+      }
+      #ifdef KOKKOS_HAVE_SERIAL
+      if(Kokkos::Impl::is_same<Kokkos::DefaultExecutionSpace,Kokkos::Serial>::value ||
+         Kokkos::Impl::is_same<Kokkos::DefaultHostExecutionSpace,Kokkos::Serial>::value )
+        expected_numa = 1;
+      #endif
+    }
+    ASSERT_EQ(Kokkos::HostSpace::execution_space::thread_pool_size(),expected_nthreads);
+
+#ifdef KOKKOS_HAVE_CUDA
+    if(Kokkos::Impl::is_same<Kokkos::DefaultExecutionSpace,Kokkos::Cuda>::value) {
+      int device;
+      cudaGetDevice( &device );
+      int expected_device = argstruct.device_id;
+      if(argstruct.device_id<0) {
+        expected_device = 0;
+      }
+      ASSERT_EQ(expected_device,device);
+    }
+#endif
+  }
+
+  //ToDo: Add check whether correct number of threads are actually started
+  void test_no_arguments() {
+    Kokkos::initialize();
+    check_correct_initialization(Kokkos::InitArguments());
+    Kokkos::finalize();
+  }
+
+  void test_commandline_args(int nargs, char** args, const Kokkos::InitArguments& argstruct) {
+    Kokkos::initialize(nargs,args);
+    check_correct_initialization(argstruct);
+    Kokkos::finalize();
+  }
+
+  void test_initstruct_args(const Kokkos::InitArguments& args) {
+    Kokkos::initialize(args);
+    check_correct_initialization(args);
+    Kokkos::finalize();
+  }
+}
+
+class defaultdevicetypeinit : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+  }
+
+  static void TearDownTestCase()
+  {
+  }
+};
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_01
+TEST_F( defaultdevicetypeinit, no_args) {
+  Impl::test_no_arguments();
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_02
+TEST_F( defaultdevicetypeinit, commandline_args_empty) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(false,false,false,false,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_03
+TEST_F( defaultdevicetypeinit, commandline_args_other) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(false,false,false,true,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_04
+TEST_F( defaultdevicetypeinit, commandline_args_nthreads) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(true,false,false,false,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_05
+TEST_F( defaultdevicetypeinit, commandline_args_nthreads_numa) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(true,true,false,false,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_06
+TEST_F( defaultdevicetypeinit, commandline_args_nthreads_numa_device) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(true,true,true,false,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_07
+TEST_F( defaultdevicetypeinit, commandline_args_nthreads_device) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(true,false,true,false,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_08
+TEST_F( defaultdevicetypeinit, commandline_args_numa_device) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(false,true,true,false,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_09
+TEST_F( defaultdevicetypeinit, commandline_args_device) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(false,false,true,false,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_10
+TEST_F( defaultdevicetypeinit, commandline_args_nthreads_numa_device_other) {
+  Kokkos::InitArguments argstruct;
+  int nargs = 0;
+  char** args = Impl::init_kokkos_args(true,true,true,true,nargs, argstruct);
+  Impl::test_commandline_args(nargs,args,argstruct);
+  for(int i = 0; i < nargs; i++)
+    delete [] args[i];
+  delete [] args;
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_11
+TEST_F( defaultdevicetypeinit, initstruct_default) {
+  Kokkos::InitArguments args;
+  Impl::test_initstruct_args(args);
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_12
+TEST_F( defaultdevicetypeinit, initstruct_nthreads) {
+  Kokkos::InitArguments args = Impl::init_initstruct(true,false,false);
+  Impl::test_initstruct_args(args);
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_13
+TEST_F( defaultdevicetypeinit, initstruct_nthreads_numa) {
+  Kokkos::InitArguments args = Impl::init_initstruct(true,true,false);
+  Impl::test_initstruct_args(args);
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_14
+TEST_F( defaultdevicetypeinit, initstruct_device) {
+  Kokkos::InitArguments args = Impl::init_initstruct(false,false,true);
+  Impl::test_initstruct_args(args);
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_15
+TEST_F( defaultdevicetypeinit, initstruct_nthreads_device) {
+  Kokkos::InitArguments args = Impl::init_initstruct(true,false,true);
+  Impl::test_initstruct_args(args);
+}
+#endif
+
+#ifdef KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_16
+TEST_F( defaultdevicetypeinit, initstruct_nthreads_numa_device) {
+  Kokkos::InitArguments args = Impl::init_initstruct(true,true,true);
+  Impl::test_initstruct_args(args);
+}
+#endif
+
+
+} // namespace test
+
+#endif
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_1.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_1.cpp
new file mode 100644
index 0000000000..40a773b3b8
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_1.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_01
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_10.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_10.cpp
new file mode 100644
index 0000000000..f12c4f62b2
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_10.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_10
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_11.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_11.cpp
new file mode 100644
index 0000000000..c7ffd7b94e
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_11.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_11
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_12.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_12.cpp
new file mode 100644
index 0000000000..24e2b15201
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_12.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_12
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_13.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_13.cpp
new file mode 100644
index 0000000000..7968c13b66
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_13.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_13
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_14.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_14.cpp
new file mode 100644
index 0000000000..ab0563c6dc
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_14.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_14
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_15.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_15.cpp
new file mode 100644
index 0000000000..70a8ca1727
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_15.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_15
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_16.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_16.cpp
new file mode 100644
index 0000000000..727c7a95eb
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_16.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_16
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_2.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_2.cpp
new file mode 100644
index 0000000000..88fba34c50
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_2.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_02
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_3.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_3.cpp
new file mode 100644
index 0000000000..b3562cc53d
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_3.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_03
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_4.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_4.cpp
new file mode 100644
index 0000000000..0d4983319c
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_4.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_04
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_5.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_5.cpp
new file mode 100644
index 0000000000..026fb01f88
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_5.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_05
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_6.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_6.cpp
new file mode 100644
index 0000000000..937a13160e
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_6.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_06
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_7.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_7.cpp
new file mode 100644
index 0000000000..992c854c1a
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_7.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_07
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_8.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_8.cpp
new file mode 100644
index 0000000000..07a8b1cb7c
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_8.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_08
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_9.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_9.cpp
new file mode 100644
index 0000000000..4d8c05be2d
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceTypeInit_9.cpp
@@ -0,0 +1,2 @@
+#define KOKKOS_DEFAULTDEVICETYPE_INIT_TEST_09
+#include<TestDefaultDeviceTypeInit.hpp>
diff --git a/lib/kokkos/core/unit_test/TestDefaultDeviceType_a.cpp b/lib/kokkos/core/unit_test/TestDefaultDeviceType_a.cpp
new file mode 100644
index 0000000000..c15f812233
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestDefaultDeviceType_a.cpp
@@ -0,0 +1,76 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+#if !defined(KOKKOS_HAVE_CUDA) || defined(__CUDACC__)
+//----------------------------------------------------------------------------
+
+#include <TestReduce.hpp>
+
+
+namespace Test {
+
+class defaultdevicetype : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    Kokkos::initialize();
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::finalize();
+  }
+};
+
+
+TEST_F( defaultdevicetype, reduce_instantiation) {
+  TestReduceCombinatoricalInstantiation<>::execute();
+}
+
+} // namespace test
+
+#endif
diff --git a/lib/kokkos/core/unit_test/TestHWLOC.cpp b/lib/kokkos/core/unit_test/TestHWLOC.cpp
new file mode 100644
index 0000000000..1637dec5de
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestHWLOC.cpp
@@ -0,0 +1,69 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+#include <Kokkos_hwloc.hpp>
+
+namespace Test {
+
+class hwloc : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {}
+
+  static void TearDownTestCase()
+  {}
+};
+
+TEST_F( hwloc, query)
+{
+  std::cout << " NUMA[" << Kokkos::hwloc::get_available_numa_count() << "]"
+            << " CORE[" << Kokkos::hwloc::get_available_cores_per_numa() << "]"
+            << " PU[" << Kokkos::hwloc::get_available_threads_per_core()  << "]"
+            << std::endl ;
+}
+
+}
+
diff --git a/lib/kokkos/core/unit_test/TestMDRange.hpp b/lib/kokkos/core/unit_test/TestMDRange.hpp
new file mode 100644
index 0000000000..9894d1ce69
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestMDRange.hpp
@@ -0,0 +1,555 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdio.h>
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+namespace {
+
+template <typename ExecSpace >
+struct TestMDRange_2D {
+
+  using DataType     = int ;
+  using ViewType     = typename Kokkos::View< DataType** ,  ExecSpace > ;
+  using HostViewType = typename ViewType::HostMirror ;
+
+  ViewType input_view ;
+
+  TestMDRange_2D( const DataType N0, const DataType N1 ) : input_view("input_view", N0, N1) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int i , const int j ) const
+  {
+    input_view(i,j) = 1;
+  }
+
+
+  static void test_for2( const int64_t N0, const int64_t N1 )
+  {
+
+    using namespace Kokkos::Experimental;
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2>, Kokkos::IndexType<int> >;
+      range_type range( {0,0}, {N0,N1} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2, Iterate::Default, Iterate::Default >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0}, {N0,N1} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2, Iterate::Default, Iterate::Flat >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0}, {N0,N1} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2, Iterate::Right, Iterate::Flat >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0}, {N0,N1} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2, Iterate::Left, Iterate::Flat >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0}, {N0,N1} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2, Iterate::Left , Iterate::Left >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0}, {N0,N1}, {3,3} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2, Iterate::Left , Iterate::Right >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0}, {N0,N1}, {7,7} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2, Iterate::Right, Iterate::Left >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0}, {N0,N1}, {16,16} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<2, Iterate::Right, Iterate::Right >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0}, {N0,N1}, {5,16} );
+      TestMDRange_2D functor(N0,N1);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          if ( h_view(i,j) != 1 ) {
+            ++counter;
+          }
+        }}
+      if ( counter != 0 )
+        printf(" Errors in test_for2; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+  } //end test_for2
+}; //MDRange_2D
+
+template <typename ExecSpace >
+struct TestMDRange_3D {
+
+  using DataType = int ;
+  using ViewType     = typename Kokkos::View< DataType*** ,  ExecSpace > ;
+  using HostViewType = typename ViewType::HostMirror ;
+
+  ViewType input_view ;
+
+  TestMDRange_3D( const DataType N0, const DataType N1, const DataType N2 ) : input_view("input_view", N0, N1, N2) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int i , const int j , const int k ) const
+  {
+    input_view(i,j,k) = 1;
+  }
+
+  static void test_for3( const int64_t N0, const int64_t N1, const int64_t N2 )
+  {
+    using namespace Kokkos::Experimental;
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3>, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Default, Iterate::Default >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Flat, Iterate::Default>, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Flat, Iterate::Flat >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Left, Iterate::Flat >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Right, Iterate::Flat >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Left, Iterate::Left >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2}, {2,4,2} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Left, Iterate::Right >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2}, {3,5,7} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Right, Iterate::Left >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2}, {8,8,8} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+    {
+      using range_type = MDRangePolicy< ExecSpace, Rank<3, Iterate::Right, Iterate::Right >, Kokkos::IndexType<int> >;
+
+      range_type range( {0,0,0}, {N0,N1,N2}, {2,4,2} );
+      TestMDRange_3D functor(N0,N1,N2);
+
+      md_parallel_for( range, functor );
+
+      HostViewType h_view = Kokkos::create_mirror_view( functor.input_view );
+      Kokkos::deep_copy( h_view , functor.input_view );
+
+      int counter = 0;
+      for ( int i=0; i<N0; ++i ) {
+        for ( int j=0; j<N1; ++j ) {
+          for ( int k=0; k<N2; ++k ) {
+          if ( h_view(i,j,k) != 1 ) {
+            ++counter;
+          }
+        }}}
+      if ( counter != 0 )
+        printf(" Errors in test_for3; mismatches = %d\n\n",counter);
+      ASSERT_EQ( counter , 0 );
+    }
+
+  } //end test_for3
+};
+
+} /* namespace */
+} /* namespace Test */
+
+/*--------------------------------------------------------------------------*/
+
diff --git a/lib/kokkos/core/unit_test/TestMemoryPool.hpp b/lib/kokkos/core/unit_test/TestMemoryPool.hpp
new file mode 100644
index 0000000000..cf650b0bc8
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestMemoryPool.hpp
@@ -0,0 +1,820 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+
+#ifndef KOKKOS_UNITTEST_MEMPOOL_HPP
+#define KOKKOS_UNITTEST_MEMPOOL_HPP
+
+#include <stdio.h>
+#include <iostream>
+#include <cmath>
+#include <algorithm>
+
+#include <impl/Kokkos_Timer.hpp>
+
+//#define TESTMEMORYPOOL_PRINT
+//#define TESTMEMORYPOOL_PRINT_STATUS
+
+#ifdef KOKKOS_HAVE_CUDA
+#define STRIDE 32
+#else
+#define STRIDE 1
+#endif
+
+namespace TestMemoryPool {
+
+struct pointer_obj {
+  uint64_t *  ptr;
+};
+
+struct pointer_obj2 {
+  void *  ptr;
+  size_t  size;
+};
+
+template < typename PointerView, typename Allocator >
+struct allocate_memory {
+  typedef typename PointerView::execution_space  execution_space;
+  typedef typename execution_space::size_type    size_type;
+
+  PointerView  m_pointers;
+  size_t       m_chunk_size;
+  Allocator    m_mempool;
+
+  allocate_memory( PointerView & ptrs, size_t num_ptrs,
+                   size_t cs, Allocator & m )
+    : m_pointers( ptrs ), m_chunk_size( cs ), m_mempool( m )
+  {
+    // Initialize the view with the out degree of each vertex.
+    Kokkos::parallel_for( num_ptrs * STRIDE, *this );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const
+  {
+    if ( i % STRIDE == 0 ) {
+      m_pointers[i / STRIDE].ptr =
+        static_cast< uint64_t * >( m_mempool.allocate( m_chunk_size ) );
+    }
+  }
+};
+
+template < typename PointerView >
+struct count_invalid_memory {
+  typedef typename PointerView::execution_space  execution_space;
+  typedef typename execution_space::size_type    size_type;
+  typedef uint64_t                               value_type;
+
+  PointerView  m_pointers;
+  uint64_t &   m_result;
+
+  count_invalid_memory( PointerView & ptrs, size_t num_ptrs, uint64_t & res )
+    : m_pointers( ptrs ), m_result( res )
+  {
+    // Initialize the view with the out degree of each vertex.
+    Kokkos::parallel_reduce( num_ptrs * STRIDE, *this, m_result );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & v ) const
+  { v = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst, volatile value_type const & src ) const
+  { dst += src; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i, value_type & r ) const
+  {
+    if ( i % STRIDE == 0 ) {
+      r += ( m_pointers[i / STRIDE].ptr == 0 );
+    }
+  }
+};
+
+template < typename PointerView >
+struct fill_memory {
+  typedef typename PointerView::execution_space  execution_space;
+  typedef typename execution_space::size_type    size_type;
+
+  PointerView m_pointers;
+
+  fill_memory( PointerView & ptrs, size_t num_ptrs ) : m_pointers( ptrs )
+  {
+    // Initialize the view with the out degree of each vertex.
+    Kokkos::parallel_for( num_ptrs * STRIDE, *this );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const
+  {
+    if ( i % STRIDE == 0 ) {
+      *m_pointers[i / STRIDE].ptr = i / STRIDE ;
+    }
+  }
+};
+
+template < typename PointerView >
+struct sum_memory {
+  typedef typename PointerView::execution_space  execution_space;
+  typedef typename execution_space::size_type    size_type;
+  typedef uint64_t                               value_type;
+
+  PointerView  m_pointers;
+  uint64_t &   m_result;
+
+  sum_memory( PointerView & ptrs, size_t num_ptrs, uint64_t & res )
+    : m_pointers( ptrs ), m_result( res )
+  {
+    // Initialize the view with the out degree of each vertex.
+    Kokkos::parallel_reduce( num_ptrs * STRIDE, *this, m_result );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & v ) const
+  { v = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst, volatile value_type const & src ) const
+  { dst += src; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i, value_type & r ) const
+  {
+    if ( i % STRIDE == 0 ) {
+      r += *m_pointers[i / STRIDE].ptr;
+    }
+  }
+};
+
+template < typename PointerView, typename Allocator >
+struct deallocate_memory {
+  typedef typename PointerView::execution_space  execution_space;
+  typedef typename execution_space::size_type    size_type;
+
+  PointerView  m_pointers;
+  size_t       m_chunk_size;
+  Allocator    m_mempool;
+
+  deallocate_memory( PointerView & ptrs, size_t num_ptrs,
+                     size_t cs, Allocator & m )
+    : m_pointers( ptrs ), m_chunk_size( cs ), m_mempool( m )
+  {
+    // Initialize the view with the out degree of each vertex.
+    Kokkos::parallel_for( num_ptrs * STRIDE, *this );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const
+  {
+    if ( i % STRIDE == 0 ) {
+      m_mempool.deallocate( m_pointers[i / STRIDE].ptr, m_chunk_size );
+    }
+  }
+};
+
+template < typename WorkView, typename PointerView, typename ScalarView,
+           typename Allocator >
+struct allocate_deallocate_memory {
+  typedef typename WorkView::execution_space   execution_space;
+  typedef typename execution_space::size_type  size_type;
+
+  WorkView     m_work;
+  PointerView  m_pointers;
+  ScalarView   m_ptrs_front;
+  ScalarView   m_ptrs_back;
+  Allocator    m_mempool;
+
+  allocate_deallocate_memory( WorkView & w, size_t work_size, PointerView & p,
+                              ScalarView pf, ScalarView pb, Allocator & m )
+    : m_work( w ), m_pointers( p ), m_ptrs_front( pf ), m_ptrs_back( pb ),
+      m_mempool( m )
+  {
+    // Initialize the view with the out degree of each vertex.
+    Kokkos::parallel_for( work_size * STRIDE, *this );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type i ) const
+  {
+    if ( i % STRIDE == 0 ) {
+      unsigned my_work = m_work[i / STRIDE];
+
+      if ( ( my_work & 1 ) == 0 ) {
+        // Allocation.
+        size_t pos = Kokkos::atomic_fetch_add( &m_ptrs_back(), 1 );
+        size_t alloc_size = my_work >> 1;
+        m_pointers[pos].ptr = m_mempool.allocate( alloc_size );
+        m_pointers[pos].size = alloc_size;
+      }
+      else {
+        // Deallocation.
+        size_t pos = Kokkos::atomic_fetch_add( &m_ptrs_front(), 1 );
+        m_mempool.deallocate( m_pointers[pos].ptr, m_pointers[pos].size );
+      }
+    }
+  }
+};
+
+#define PRECISION 6
+#define SHIFTW 24
+#define SHIFTW2 12
+
+template < typename F >
+void print_results( const std::string & text, F elapsed_time )
+{
+  std::cout << std::setw( SHIFTW ) << text << std::setw( SHIFTW2 )
+            << std::fixed << std::setprecision( PRECISION ) << elapsed_time
+            << std::endl;
+}
+
+template < typename F, typename T >
+void print_results( const std::string & text, unsigned long long width,
+                    F elapsed_time, T result )
+{
+  std::cout << std::setw( SHIFTW ) << text << std::setw( SHIFTW2 )
+            << std::fixed << std::setprecision( PRECISION ) << elapsed_time
+            << "     " << std::setw( width ) << result << std::endl;
+}
+
+template < typename F >
+void print_results( const std::string & text, unsigned long long width,
+                    F elapsed_time, const std::string & result )
+{
+  std::cout << std::setw( SHIFTW ) << text << std::setw( SHIFTW2 )
+            << std::fixed << std::setprecision( PRECISION ) << elapsed_time
+            << "     " << std::setw( width ) << result << std::endl;
+}
+
+// This test slams allocation and deallocation in a worse than real-world usage
+// scenario to see how bad the thread-safety really is by having a loop where
+// all threads allocate and a subsequent loop where all threads deallocate.
+// All of the allocation requests are for equal-sized chunks that are the base
+// chunk size of the memory pool.  It also tests initialization of the memory
+// pool and breaking large chunks into smaller chunks to fulfill allocation
+// requests.  It verifies that MemoryPool(), allocate(), and deallocate() work
+// correctly.
+template < class Device >
+bool test_mempool( size_t chunk_size, size_t total_size )
+{
+  typedef typename Device::execution_space                 execution_space;
+  typedef typename Device::memory_space                    memory_space;
+  typedef Device                                           device_type;
+  typedef Kokkos::View< pointer_obj *, device_type >       pointer_view;
+  typedef Kokkos::Experimental::MemoryPool< device_type >  pool_memory_space;
+
+  uint64_t result;
+  size_t num_chunks = total_size / chunk_size;
+  bool return_val = true;
+
+  pointer_view pointers( "pointers", num_chunks );
+
+#ifdef TESTMEMORYPOOL_PRINT
+  std::cout << "*** test_mempool() ***" << std::endl
+            << std::setw( SHIFTW ) << "chunk_size: " << std::setw( 12 )
+            << chunk_size << std::endl
+            << std::setw( SHIFTW ) << "total_size: " << std::setw( 12 )
+            << total_size << std::endl
+            << std::setw( SHIFTW ) << "num_chunks: " << std::setw( 12 )
+            << num_chunks << std::endl;
+
+  double elapsed_time = 0;
+  Kokkos::Timer timer;
+#endif
+
+  pool_memory_space mempool( memory_space(), total_size * 1.2, 20 );
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "initialize mempool: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+  timer.reset();
+#endif
+
+  {
+    allocate_memory< pointer_view, pool_memory_space >
+      am( pointers, num_chunks, chunk_size, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "allocate chunks: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+  timer.reset();
+#endif
+
+  {
+    count_invalid_memory< pointer_view > sm( pointers, num_chunks, result );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "invalid chunks: ", 16, elapsed_time, result );
+  timer.reset();
+#endif
+
+  {
+    fill_memory< pointer_view > fm( pointers, num_chunks );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "fill chunks: ", elapsed_time );
+  timer.reset();
+#endif
+
+  {
+    sum_memory< pointer_view > sm( pointers, num_chunks, result );
+  }
+
+  execution_space::fence();
+
+#ifdef TESTMEMORYPOOL_PRINT
+  elapsed_time = timer.seconds();
+  print_results( "sum chunks: ", 16, elapsed_time, result );
+#endif
+
+  if ( result != ( num_chunks * ( num_chunks - 1 ) ) / 2 ) {
+    std::cerr << "Invalid sum value in memory." << std::endl;
+    return_val = false;
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  timer.reset();
+#endif
+
+  {
+    deallocate_memory< pointer_view, pool_memory_space >
+      dm( pointers, num_chunks, chunk_size, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "deallocate chunks: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+  timer.reset();
+#endif
+
+  {
+    allocate_memory< pointer_view, pool_memory_space >
+      am( pointers, num_chunks, chunk_size, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "allocate chunks: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+  timer.reset();
+#endif
+
+  {
+    count_invalid_memory< pointer_view > sm( pointers, num_chunks, result );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "invalid chunks: ", 16, elapsed_time, result );
+  timer.reset();
+#endif
+
+  {
+    fill_memory< pointer_view > fm( pointers, num_chunks );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "fill chunks: ", elapsed_time );
+  timer.reset();
+#endif
+
+  {
+    sum_memory< pointer_view > sm( pointers, num_chunks, result );
+  }
+
+  execution_space::fence();
+
+#ifdef TESTMEMORYPOOL_PRINT
+  elapsed_time = timer.seconds();
+  print_results( "sum chunks: ", 16, elapsed_time, result );
+#endif
+
+  if ( result != ( num_chunks * ( num_chunks - 1 ) ) / 2 ) {
+    std::cerr << "Invalid sum value in memory." << std::endl;
+    return_val = false;
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  timer.reset();
+#endif
+
+  {
+    deallocate_memory< pointer_view, pool_memory_space >
+      dm( pointers, num_chunks, chunk_size, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "deallocate chunks: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+#endif
+
+  return return_val;
+}
+
+template < typename T >
+T smallest_power2_ge( T val )
+{
+  // Find the most significant nonzero bit.
+  int first_nonzero_bit = Kokkos::Impl::bit_scan_reverse( val );
+
+  // If val is an integral power of 2, ceil( log2(val) ) is equal to the
+  // most significant nonzero bit.  Otherwise, you need to add 1.
+  int lg2_size = first_nonzero_bit +
+                 !Kokkos::Impl::is_integral_power_of_two( val );
+
+  return T(1) << T(lg2_size);
+}
+
+// This test makes allocation requests for multiple sizes and interleaves
+// allocation and deallocation.
+//
+// There are 3 phases.  The first phase does only allocations to build up a
+// working state for the allocator.  The second phase interleaves allocations
+// and deletions.  The third phase does only deallocations to undo all the
+// allocations from the first phase.  By building first to a working state,
+// allocations and deallocations can happen in any order for the second phase.
+// Each phase performs on multiple chunk sizes.
+template < class Device >
+void test_mempool2( unsigned base_chunk_size, size_t num_chunk_sizes,
+                    size_t phase1_size, size_t phase2_size )
+{
+#ifdef TESTMEMORYPOOL_PRINT
+  typedef typename Device::execution_space                 execution_space;
+#endif
+  typedef typename Device::memory_space                    memory_space;
+  typedef Device                                           device_type;
+  typedef Kokkos::View< unsigned *, device_type >          work_view;
+  typedef Kokkos::View< size_t, device_type >              scalar_view;
+  typedef Kokkos::View< pointer_obj2 *, device_type >      pointer_view;
+  typedef Kokkos::Experimental::MemoryPool< device_type >  pool_memory_space;
+
+  enum {
+    MIN_CHUNK_SIZE      = 64,
+    MIN_BASE_CHUNK_SIZE = MIN_CHUNK_SIZE / 2 + 1
+  };
+
+  // Make sure the base chunk size is at least MIN_BASE_CHUNK_SIZE bytes, so
+  // all the different chunk sizes translate to different block sizes for the
+  // allocator.
+  if ( base_chunk_size < MIN_BASE_CHUNK_SIZE ) {
+    base_chunk_size = MIN_BASE_CHUNK_SIZE;
+  }
+
+  // Get the smallest power of 2 >= the base chunk size.  The size must be
+  // >= MIN_CHUNK_SIZE, though.
+  unsigned ceil_base_chunk_size = smallest_power2_ge( base_chunk_size );
+  if ( ceil_base_chunk_size < MIN_CHUNK_SIZE ) {
+    ceil_base_chunk_size = MIN_CHUNK_SIZE;
+  }
+
+  // Make sure the phase 1 size is multiples of num_chunk_sizes.
+  phase1_size = ( ( phase1_size + num_chunk_sizes - 1 ) / num_chunk_sizes ) *
+                num_chunk_sizes;
+
+  // Make sure the phase 2 size is multiples of (2 * num_chunk_sizes).
+  phase2_size =
+    ( ( phase2_size + 2 * num_chunk_sizes - 1 ) / ( 2 * num_chunk_sizes ) ) *
+    2 * num_chunk_sizes;
+
+  // The phase2 size must be <= twice the phase1 size so that deallocations
+  // can't happen before allocations.
+  if ( phase2_size > 2 * phase1_size ) phase2_size = 2 * phase1_size;
+
+  size_t phase3_size = phase1_size;
+  size_t half_phase2_size = phase2_size / 2;
+
+  // Each entry in the work views has the following format.  The least
+  // significant bit indicates allocation (0) vs. deallocation (1).  For
+  // allocation, the other bits indicate the desired allocation size.
+
+  // Initialize the phase 1 work view with an equal number of allocations for
+  // each chunk size.
+  work_view phase1_work( "Phase 1 Work", phase1_size );
+  typename work_view::HostMirror host_phase1_work =
+    create_mirror_view(phase1_work);
+
+  size_t inner_size = phase1_size / num_chunk_sizes;
+  unsigned chunk_size = base_chunk_size;
+
+  for ( size_t i = 0; i < num_chunk_sizes; ++i ) {
+    for ( size_t j = 0; j < inner_size; ++j ) {
+      host_phase1_work[i * inner_size + j] = chunk_size << 1;
+    }
+
+    chunk_size *= 2;
+  }
+
+  std::random_shuffle( host_phase1_work.ptr_on_device(),
+                       host_phase1_work.ptr_on_device() + phase1_size );
+
+  deep_copy( phase1_work, host_phase1_work );
+
+  // Initialize the phase 2 work view with half allocations and half
+  // deallocations with an equal number of allocations for each chunk size.
+  work_view phase2_work( "Phase 2 Work", phase2_size );
+  typename work_view::HostMirror host_phase2_work =
+    create_mirror_view(phase2_work);
+
+  inner_size = half_phase2_size / num_chunk_sizes;
+  chunk_size = base_chunk_size;
+
+  for ( size_t i = 0; i < num_chunk_sizes; ++i ) {
+    for ( size_t j = 0; j < inner_size; ++j ) {
+      host_phase2_work[i * inner_size + j] = chunk_size << 1;
+    }
+
+    chunk_size *= 2;
+  }
+
+  for ( size_t i = half_phase2_size; i < phase2_size; ++i ) {
+    host_phase2_work[i] = 1;
+  }
+
+  std::random_shuffle( host_phase2_work.ptr_on_device(),
+                       host_phase2_work.ptr_on_device() + phase2_size );
+
+  deep_copy( phase2_work, host_phase2_work );
+
+  // Initialize the phase 3 work view with all deallocations.
+  work_view phase3_work( "Phase 3 Work", phase3_size );
+  typename work_view::HostMirror host_phase3_work =
+    create_mirror_view(phase3_work);
+
+  inner_size = phase3_size / num_chunk_sizes;
+
+  for ( size_t i = 0; i < phase3_size; ++i ) host_phase3_work[i] = 1;
+
+  deep_copy( phase3_work, host_phase3_work );
+
+  // Calculate the amount of memory needed for the allocator.  We need to know
+  // the number of superblocks required for each chunk size and use that to
+  // calculate the amount of memory for each chunk size.
+  size_t lg_sb_size = 18;
+  size_t sb_size = 1 << lg_sb_size;
+  size_t total_size = 0;
+  size_t allocs_per_size = phase1_size / num_chunk_sizes +
+                           half_phase2_size / num_chunk_sizes;
+
+  chunk_size = ceil_base_chunk_size;
+  for ( size_t i = 0; i < num_chunk_sizes; ++i ) {
+    size_t my_size = allocs_per_size * chunk_size;
+    total_size += ( my_size + sb_size - 1 ) / sb_size * sb_size;
+    chunk_size *= 2;
+  }
+
+  // Declare the queue to hold the records for allocated memory.  An allocation
+  // adds a record to the back of the queue, and a deallocation removes a
+  // record from the front of the queue.
+  size_t num_allocations = phase1_size + half_phase2_size;
+  scalar_view ptrs_front( "Pointers front" );
+  scalar_view ptrs_back( "Pointers back" );
+
+  pointer_view pointers( "pointers", num_allocations );
+
+#ifdef TESTMEMORYPOOL_PRINT
+  printf( "\n*** test_mempool2() ***\n" );
+  printf( "       num_chunk_sizes: %12zu\n", num_chunk_sizes );
+  printf( "       base_chunk_size: %12u\n", base_chunk_size );
+  printf( "  ceil_base_chunk_size: %12u\n", ceil_base_chunk_size );
+  printf( "           phase1_size: %12zu\n", phase1_size );
+  printf( "           phase2_size: %12zu\n", phase2_size );
+  printf( "           phase3_size: %12zu\n", phase3_size );
+  printf( "       allocs_per_size: %12zu\n", allocs_per_size );
+  printf( "       num_allocations: %12zu\n", num_allocations );
+  printf( "            total_size: %12zu\n", total_size );
+  fflush( stdout );
+
+  double elapsed_time = 0;
+  Kokkos::Timer timer;
+#endif
+
+  pool_memory_space mempool( memory_space(), total_size * 1.2, lg_sb_size );
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "initialize mempool: ", elapsed_time );
+
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+
+  timer.reset();
+#endif
+
+  {
+    allocate_deallocate_memory< work_view, pointer_view, scalar_view,
+                                pool_memory_space >
+      adm( phase1_work, phase1_size, pointers, ptrs_front, ptrs_back, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "phase1: ", elapsed_time );
+
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+
+  timer.reset();
+#endif
+
+  {
+    allocate_deallocate_memory< work_view, pointer_view, scalar_view,
+                                pool_memory_space >
+      adm( phase2_work, phase2_size, pointers, ptrs_front, ptrs_back, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "phase2: ", elapsed_time );
+
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+
+  timer.reset();
+#endif
+
+  {
+    allocate_deallocate_memory< work_view, pointer_view, scalar_view,
+                                pool_memory_space >
+      adm( phase3_work, phase3_size, pointers, ptrs_front, ptrs_back, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "phase3: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+#endif
+}
+
+// Tests for correct behavior when the allocator is out of memory.
+template < class Device >
+void test_memory_exhaustion()
+{
+#ifdef TESTMEMORYPOOL_PRINT
+  typedef typename Device::execution_space                 execution_space;
+#endif
+  typedef typename Device::memory_space                    memory_space;
+  typedef Device                                           device_type;
+  typedef Kokkos::View< pointer_obj *, device_type >       pointer_view;
+  typedef Kokkos::Experimental::MemoryPool< device_type >  pool_memory_space;
+
+  // The allocator will have a single superblock, and allocations will all be
+  // of the same chunk size.  The allocation loop will attempt to allocate
+  // twice the number of chunks as are available in the allocator.  The
+  // deallocation loop will only free the successfully allocated chunks.
+
+  size_t chunk_size = 128;
+  size_t num_chunks = 128;
+  size_t half_num_chunks = num_chunks / 2;
+  size_t superblock_size = chunk_size * half_num_chunks;
+  size_t lg_superblock_size =
+    Kokkos::Impl::integral_power_of_two( superblock_size );
+
+  pointer_view pointers( "pointers", num_chunks );
+
+#ifdef TESTMEMORYPOOL_PRINT
+  std::cout << "\n*** test_memory_exhaustion() ***" << std::endl;
+
+  double elapsed_time = 0;
+  Kokkos::Timer timer;
+#endif
+
+  pool_memory_space mempool( memory_space(), superblock_size,
+                             lg_superblock_size );
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "initialize mempool: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+  timer.reset();
+#endif
+
+  {
+    allocate_memory< pointer_view, pool_memory_space >
+      am( pointers, num_chunks, chunk_size, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "allocate chunks: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+  timer.reset();
+#endif
+
+  {
+    // In parallel, the allocations that succeeded were not put contiguously
+    // into the pointers View.  The whole View can still be looped over and
+    // have deallocate called because deallocate will just do nothing for NULL
+    // pointers.
+    deallocate_memory< pointer_view, pool_memory_space >
+      dm( pointers, num_chunks, chunk_size, mempool );
+  }
+
+#ifdef TESTMEMORYPOOL_PRINT
+  execution_space::fence();
+  elapsed_time = timer.seconds();
+  print_results( "deallocate chunks: ", elapsed_time );
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+  mempool.print_status();
+#endif
+#endif
+}
+
+}
+
+#ifdef TESTMEMORYPOOL_PRINT
+#undef TESTMEMORYPOOL_PRINT
+#endif
+
+#ifdef TESTMEMORYPOOL_PRINT_STATUS
+#undef TESTMEMORYPOOL_PRINT_STATUS
+#endif
+
+#ifdef STRIDE
+#undef STRIDE
+#endif
+
+#endif
diff --git a/lib/kokkos/core/unit_test/TestMemorySpaceTracking.hpp b/lib/kokkos/core/unit_test/TestMemorySpaceTracking.hpp
new file mode 100644
index 0000000000..575f2f2c25
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestMemorySpaceTracking.hpp
@@ -0,0 +1,100 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <iostream>
+#include <Kokkos_Core.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace {
+
+template<class Arg1>
+class TestMemorySpace {
+public:
+
+  typedef typename Arg1::memory_space MemorySpace;
+  TestMemorySpace() { run_test(); }
+
+  void run_test()
+  {
+
+#if ! KOKKOS_USING_EXP_VIEW
+
+    Kokkos::View<int* ,Arg1> invalid;
+    ASSERT_EQ(0u, invalid.tracker().ref_count() );
+
+    {
+      Kokkos::View<int* ,Arg1> a("A",10);
+
+      ASSERT_EQ(1u, a.tracker().ref_count() );
+
+      {
+        Kokkos::View<int* ,Arg1> b = a;
+        ASSERT_EQ(2u, b.tracker().ref_count() );
+
+        Kokkos::View<int* ,Arg1> D("D",10);
+        ASSERT_EQ(1u, D.tracker().ref_count() );
+
+        {
+          Kokkos::View<int* ,Arg1> E("E",10);
+          ASSERT_EQ(1u, E.tracker().ref_count() );
+        }
+
+        ASSERT_EQ(2u, b.tracker().ref_count() );
+      }
+      ASSERT_EQ(1u, a.tracker().ref_count() );
+    }
+
+#endif
+
+  }
+};
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+
+
diff --git a/lib/kokkos/core/unit_test/TestOpenMP.cpp b/lib/kokkos/core/unit_test/TestOpenMP.cpp
new file mode 100644
index 0000000000..6e8fc45179
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestOpenMP.cpp
@@ -0,0 +1,262 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Macros.hpp>
+#ifdef KOKKOS_LAMBDA
+#undef KOKKOS_LAMBDA
+#endif
+#define KOKKOS_LAMBDA [=]
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+#include <TestAtomicOperations.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestMemoryPool.hpp>
+
+
+#include <TestCXX11.hpp>
+#include <TestCXX11Deduction.hpp>
+#include <TestTeamVector.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+
+#include <TestPolicyConstruction.hpp>
+
+#include <TestMDRange.hpp>
+
+namespace Test {
+
+class openmp : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    const unsigned numa_count       = Kokkos::hwloc::get_available_numa_count();
+    const unsigned cores_per_numa   = Kokkos::hwloc::get_available_cores_per_numa();
+    const unsigned threads_per_core = Kokkos::hwloc::get_available_threads_per_core();
+
+    const unsigned threads_count = std::max( 1u , numa_count ) *
+                                   std::max( 2u , ( cores_per_numa * threads_per_core ) / 2 );
+
+    Kokkos::OpenMP::initialize( threads_count );
+    Kokkos::OpenMP::print_configuration( std::cout , true );
+    srand(10231);
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::OpenMP::finalize();
+
+    omp_set_num_threads(1);
+
+    ASSERT_EQ( 1 , omp_get_max_threads() );
+  }
+};
+
+
+TEST_F( openmp , md_range ) {
+  TestMDRange_2D< Kokkos::OpenMP >::test_for2(100,100);
+
+  TestMDRange_3D< Kokkos::OpenMP >::test_for3(100,100,100);
+}
+
+TEST_F( openmp , impl_shared_alloc ) {
+  test_shared_alloc< Kokkos::HostSpace , Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, policy_construction) {
+  TestRangePolicyConstruction< Kokkos::OpenMP >();
+  TestTeamPolicyConstruction< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp , impl_view_mapping ) {
+  test_view_mapping< Kokkos::OpenMP >();
+  test_view_mapping_subview< Kokkos::OpenMP >();
+  test_view_mapping_operator< Kokkos::OpenMP >();
+  TestViewMappingAtomic< Kokkos::OpenMP >::run();
+}
+
+TEST_F( openmp, view_impl) {
+  test_view_impl< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_api) {
+  TestViewAPI< double , Kokkos::OpenMP >();
+}
+
+TEST_F( openmp , view_nested_view )
+{
+  ::Test::view_nested_view< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp , atomics )
+{
+  const int loop_count = 1e4 ;
+
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::OpenMP>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::OpenMP>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::OpenMP>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::OpenMP>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::OpenMP>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::OpenMP>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::OpenMP>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::OpenMP>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::OpenMP>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::OpenMP>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::OpenMP>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::OpenMP>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::OpenMP>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::OpenMP>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::OpenMP>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::OpenMP>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::OpenMP>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::OpenMP>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::OpenMP>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::OpenMP>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::OpenMP>(100,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::OpenMP>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::OpenMP>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::OpenMP>(100,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::OpenMP>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::OpenMP>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::OpenMP>(100,3) ) );
+}
+
+TEST_F( openmp , atomic_operations )
+{
+  const int start = 1; //Avoid zero for division
+  const int end = 11;
+  for (int i = start; i < end; ++i)
+  {
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::OpenMP>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::OpenMP>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::OpenMP>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::OpenMP>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::OpenMP>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::OpenMP>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::OpenMP>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::OpenMP>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::OpenMP>(start, end-i, 4 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::OpenMP>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::OpenMP>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::OpenMP>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::OpenMP>(start, end-i, 4 ) ) );
+  }
+
+}
+
+} // namespace test
+
diff --git a/lib/kokkos/core/unit_test/TestOpenMP_a.cpp b/lib/kokkos/core/unit_test/TestOpenMP_a.cpp
new file mode 100644
index 0000000000..64eac66804
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestOpenMP_a.cpp
@@ -0,0 +1,150 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Macros.hpp>
+#ifdef KOKKOS_LAMBDA
+#undef KOKKOS_LAMBDA
+#endif
+#define KOKKOS_LAMBDA [=]
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestMemoryPool.hpp>
+
+
+#include <TestCXX11.hpp>
+#include <TestCXX11Deduction.hpp>
+#include <TestTeamVector.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+
+#include <TestPolicyConstruction.hpp>
+
+
+namespace Test {
+
+class openmp : public ::testing::Test {
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+TEST_F( openmp, view_subview_auto_1d_left ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutLeft,Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_auto_1d_right ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutRight,Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_auto_1d_stride ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutStride,Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_assign_strided ) {
+  TestViewSubview::test_1d_strided_assignment< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_left_0 ) {
+  TestViewSubview::test_left_0< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_left_1 ) {
+  TestViewSubview::test_left_1< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_left_2 ) {
+  TestViewSubview::test_left_2< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_left_3 ) {
+  TestViewSubview::test_left_3< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_right_0 ) {
+  TestViewSubview::test_right_0< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_right_1 ) {
+  TestViewSubview::test_right_1< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_right_3 ) {
+  TestViewSubview::test_right_3< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_1d_assign ) {
+  TestViewSubview::test_1d_assign< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_2d_from_3d ) {
+  TestViewSubview::test_2d_subview_3d< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, view_subview_2d_from_5d ) {
+  TestViewSubview::test_2d_subview_5d< Kokkos::OpenMP >();
+}
+
+} // namespace test
+
diff --git a/lib/kokkos/core/unit_test/TestOpenMP_b.cpp b/lib/kokkos/core/unit_test/TestOpenMP_b.cpp
new file mode 100644
index 0000000000..6cc2476014
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestOpenMP_b.cpp
@@ -0,0 +1,185 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Macros.hpp>
+#ifdef KOKKOS_LAMBDA
+#undef KOKKOS_LAMBDA
+#endif
+#define KOKKOS_LAMBDA [=]
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestMemoryPool.hpp>
+
+
+#include <TestCXX11.hpp>
+#include <TestCXX11Deduction.hpp>
+#include <TestTeamVector.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+
+#include <TestPolicyConstruction.hpp>
+
+
+namespace Test {
+
+class openmp : public ::testing::Test {
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+TEST_F( openmp , range_tag )
+{
+  TestRange< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestRange< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestRange< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >::test_scan(1000);
+  TestRange< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(1001);
+  TestRange< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(1001);
+  TestRange< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >::test_scan(1001);
+  TestRange< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >::test_dynamic_policy(1000);
+}
+
+TEST_F( openmp , team_tag )
+{
+  TestTeamPolicy< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >::test_for(2);
+  TestTeamPolicy< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >::test_reduce(2);
+  TestTeamPolicy< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(2);
+  TestTeamPolicy< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(2);
+  TestTeamPolicy< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestTeamPolicy< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestTeamPolicy< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(1000);
+  TestTeamPolicy< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(1000);
+}
+
+TEST_F( openmp, long_reduce) {
+  TestReduce< long ,   Kokkos::OpenMP >( 1000000 );
+}
+
+TEST_F( openmp, double_reduce) {
+  TestReduce< double ,   Kokkos::OpenMP >( 1000000 );
+}
+
+TEST_F( openmp, long_reduce_dynamic ) {
+  TestReduceDynamic< long ,   Kokkos::OpenMP >( 1000000 );
+}
+
+TEST_F( openmp, double_reduce_dynamic ) {
+  TestReduceDynamic< double ,   Kokkos::OpenMP >( 1000000 );
+}
+
+TEST_F( openmp, long_reduce_dynamic_view ) {
+  TestReduceDynamicView< long ,   Kokkos::OpenMP >( 1000000 );
+}
+
+TEST_F( openmp , reducers )
+{
+  TestReducers<int, Kokkos::OpenMP>::execute_integer();
+  TestReducers<size_t, Kokkos::OpenMP>::execute_integer();
+  TestReducers<double, Kokkos::OpenMP>::execute_float();
+  TestReducers<Kokkos::complex<double>, Kokkos::OpenMP>::execute_basic();
+}
+
+TEST_F( openmp, team_long_reduce) {
+  TestReduceTeam< long ,   Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >( 3 );
+  TestReduceTeam< long ,   Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >( 3 );
+  TestReduceTeam< long ,   Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >( 100000 );
+  TestReduceTeam< long ,   Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >( 100000 );
+}
+
+TEST_F( openmp, team_double_reduce) {
+  TestReduceTeam< double ,   Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >( 3 );
+  TestReduceTeam< double ,   Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >( 3 );
+  TestReduceTeam< double ,   Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >( 100000 );
+  TestReduceTeam< double ,   Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >( 100000 );
+}
+
+TEST_F( openmp, team_shared_request) {
+  TestSharedTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >();
+  TestSharedTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+
+TEST_F( openmp, team_scratch_request) {
+  TestScratchTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >();
+  TestScratchTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+
+#if defined(KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+TEST_F( openmp, team_lambda_shared_request) {
+  TestLambdaSharedTeam< Kokkos::HostSpace, Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >();
+  TestLambdaSharedTeam< Kokkos::HostSpace, Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+#endif
+
+TEST_F( openmp, shmem_size) {
+  TestShmemSize< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp, multi_level_scratch) {
+  TestMultiLevelScratchTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >();
+  TestMultiLevelScratchTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+
+} // namespace test
+
diff --git a/lib/kokkos/core/unit_test/TestOpenMP_c.cpp b/lib/kokkos/core/unit_test/TestOpenMP_c.cpp
new file mode 100644
index 0000000000..f0cdabe913
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestOpenMP_c.cpp
@@ -0,0 +1,262 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Macros.hpp>
+#ifdef KOKKOS_LAMBDA
+#undef KOKKOS_LAMBDA
+#endif
+#define KOKKOS_LAMBDA [=]
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestMemoryPool.hpp>
+#include <TestTaskPolicy.hpp>
+
+
+#include <TestCXX11.hpp>
+#include <TestCXX11Deduction.hpp>
+#include <TestTeamVector.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+
+#include <TestPolicyConstruction.hpp>
+
+
+namespace Test {
+
+class openmp : public ::testing::Test {
+protected:
+  static void SetUpTestCase();
+  static void TearDownTestCase();
+};
+
+TEST_F( openmp , view_remap )
+{
+  enum { N0 = 3 , N1 = 2 , N2 = 8 , N3 = 9 };
+
+  typedef Kokkos::View< double*[N1][N2][N3] ,
+                             Kokkos::LayoutRight ,
+                             Kokkos::OpenMP > output_type ;
+
+  typedef Kokkos::View< int**[N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::OpenMP > input_type ;
+
+  typedef Kokkos::View< int*[N0][N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::OpenMP > diff_type ;
+
+  output_type output( "output" , N0 );
+  input_type  input ( "input" , N0 , N1 );
+  diff_type   diff  ( "diff" , N0 );
+
+  int value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    input(i0,i1,i2,i3) = ++value ;
+  }}}}
+
+  // Kokkos::deep_copy( diff , input ); // throw with incompatible shape
+  Kokkos::deep_copy( output , input );
+
+  value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    ++value ;
+    ASSERT_EQ( value , ((int) output(i0,i1,i2,i3) ) );
+  }}}}
+}
+
+//----------------------------------------------------------------------------
+
+
+TEST_F( openmp , view_aggregate )
+{
+  TestViewAggregate< Kokkos::OpenMP >();
+  TestViewAggregateReduction< Kokkos::OpenMP >();
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( openmp , scan )
+{
+  TestScan< Kokkos::OpenMP >::test_range( 1 , 1000 );
+  TestScan< Kokkos::OpenMP >( 1000000 );
+  TestScan< Kokkos::OpenMP >( 10000000 );
+  Kokkos::OpenMP::fence();
+}
+
+
+TEST_F( openmp , team_scan )
+{
+  TestScanTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >( 10 );
+  TestScanTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >( 10 );
+  TestScanTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Static> >( 10000 );
+  TestScanTeam< Kokkos::OpenMP , Kokkos::Schedule<Kokkos::Dynamic> >( 10000 );
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( openmp , compiler_macros )
+{
+  ASSERT_TRUE( ( TestCompilerMacros::Test< Kokkos::OpenMP >() ) );
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( openmp , memory_space )
+{
+  TestMemorySpace< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp , memory_pool )
+{
+  bool val = TestMemoryPool::test_mempool< Kokkos::OpenMP >( 128, 128000000 );
+  ASSERT_TRUE( val );
+
+  TestMemoryPool::test_mempool2< Kokkos::OpenMP >( 64, 4, 1000000, 2000000 );
+
+  TestMemoryPool::test_memory_exhaustion< Kokkos::OpenMP >();
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( openmp , template_meta_functions )
+{
+  TestTemplateMetaFunctions<int, Kokkos::OpenMP >();
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_OPENMP )
+TEST_F( openmp , cxx11 )
+{
+  if ( Kokkos::Impl::is_same< Kokkos::DefaultExecutionSpace , Kokkos::OpenMP >::value ) {
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::OpenMP >(1) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::OpenMP >(2) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::OpenMP >(3) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::OpenMP >(4) ) );
+  }
+}
+#endif
+
+TEST_F( openmp , reduction_deduction )
+{
+  TestCXX11::test_reduction_deduction< Kokkos::OpenMP >();
+}
+
+TEST_F( openmp , team_vector )
+{
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(0) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(1) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(2) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(3) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(4) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(5) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(6) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(7) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(8) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(9) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::OpenMP >(10) ) );
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+TEST_F( openmp , task_fib )
+{
+  for ( int i = 0 ; i < 25 ; ++i ) {
+    TestTaskPolicy::TestFib< Kokkos::OpenMP >::run(i, (i+1)*1000000 );
+  }
+}
+
+TEST_F( openmp , task_depend )
+{
+  for ( int i = 0 ; i < 25 ; ++i ) {
+    TestTaskPolicy::TestTaskDependence< Kokkos::OpenMP >::run(i);
+  }
+}
+
+TEST_F( openmp , task_team )
+{
+  TestTaskPolicy::TestTaskTeam< Kokkos::OpenMP >::run(1000);
+  //TestTaskPolicy::TestTaskTeamValue< Kokkos::OpenMP >::run(1000); //TODO put back after testing
+}
+
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
+
+} // namespace test
+
+
+
+
+
+
diff --git a/lib/kokkos/core/unit_test/TestPolicyConstruction.hpp b/lib/kokkos/core/unit_test/TestPolicyConstruction.hpp
new file mode 100644
index 0000000000..049138eb07
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestPolicyConstruction.hpp
@@ -0,0 +1,493 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+struct SomeTag{};
+
+template< class ExecutionSpace >
+class TestRangePolicyConstruction {
+public:
+  TestRangePolicyConstruction() {
+    test_compile_time_parameters();
+  }
+private:
+  void test_compile_time_parameters() {
+    {
+      typedef Kokkos::RangePolicy<> policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,typename execution_space::size_type >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Static>    >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<ExecutionSpace> policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,typename execution_space::size_type >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Static>    >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,typename execution_space::size_type >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<Kokkos::IndexType<long>, ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,SomeTag > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>,ExecutionSpace,Kokkos::IndexType<long>,SomeTag > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<SomeTag,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,ExecutionSpace > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,typename execution_space::size_type >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<Kokkos::IndexType<long>, Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,SomeTag > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,SomeTag > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::RangePolicy<SomeTag,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+  }
+};
+
+template< class ExecutionSpace >
+class TestTeamPolicyConstruction {
+public:
+  TestTeamPolicyConstruction() {
+    test_compile_time_parameters();
+    test_run_time_parameters();
+  }
+private:
+  void test_compile_time_parameters() {
+    {
+      typedef Kokkos::TeamPolicy<> policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,typename execution_space::size_type >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Static>    >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<ExecutionSpace> policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,typename execution_space::size_type >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Static>    >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,typename execution_space::size_type >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<Kokkos::IndexType<long>, ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,SomeTag > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,ExecutionSpace,Kokkos::IndexType<long>,SomeTag > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<SomeTag,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,ExecutionSpace > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,ExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace                      >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,typename execution_space::size_type >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<Kokkos::IndexType<long>, Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,void                                >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,SomeTag > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,SomeTag > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+    {
+      typedef Kokkos::TeamPolicy<SomeTag,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long> > policy_t;
+      typedef typename policy_t::execution_space execution_space;
+      typedef typename policy_t::index_type      index_type;
+      typedef typename policy_t::schedule_type   schedule_type;
+      typedef typename policy_t::work_tag        work_tag;
+
+      ASSERT_TRUE((std::is_same<execution_space ,Kokkos::DefaultExecutionSpace       >::value));
+      ASSERT_TRUE((std::is_same<index_type      ,long                                >::value));
+      ASSERT_TRUE((std::is_same<schedule_type   ,Kokkos::Schedule<Kokkos::Dynamic>   >::value));
+      ASSERT_TRUE((std::is_same<work_tag        ,SomeTag                             >::value));
+    }
+  }
+
+
+  template<class policy_t>
+  void test_run_time_parameters_type() {
+    int league_size = 131;
+    int team_size = 4<policy_t::execution_space::concurrency()?4:policy_t::execution_space::concurrency();
+    int chunk_size = 4;
+    int per_team_scratch = 1024;
+    int per_thread_scratch = 16;
+    int scratch_size = per_team_scratch + per_thread_scratch*team_size;
+    policy_t p1(league_size,team_size);
+    ASSERT_EQ  (p1.league_size() , league_size);
+    ASSERT_EQ  (p1.team_size()   , team_size);
+    ASSERT_TRUE(p1.chunk_size()  > 0);
+    ASSERT_EQ  (p1.scratch_size(0), 0);
+
+    policy_t p2 = p1.set_chunk_size(chunk_size);
+    ASSERT_EQ  (p1.league_size() , league_size);
+    ASSERT_EQ  (p1.team_size()   , team_size);
+    ASSERT_TRUE(p1.chunk_size()  > 0);
+    ASSERT_EQ  (p1.scratch_size(0), 0);
+
+    ASSERT_EQ  (p2.league_size() , league_size);
+    ASSERT_EQ  (p2.team_size()   , team_size);
+    ASSERT_EQ  (p2.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p2.scratch_size(0), 0);
+
+    policy_t p3 = p2.set_scratch_size(0,Kokkos::PerTeam(per_team_scratch));
+    ASSERT_EQ  (p2.league_size() , league_size);
+    ASSERT_EQ  (p2.team_size()   , team_size);
+    ASSERT_EQ  (p2.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p2.scratch_size(0), 0);
+    ASSERT_EQ  (p3.league_size() , league_size);
+    ASSERT_EQ  (p3.team_size()   , team_size);
+    ASSERT_EQ  (p3.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p3.scratch_size(0), per_team_scratch);
+
+    policy_t p4 = p2.set_scratch_size(0,Kokkos::PerThread(per_thread_scratch));
+    ASSERT_EQ  (p2.league_size() , league_size);
+    ASSERT_EQ  (p2.team_size()   , team_size);
+    ASSERT_EQ  (p2.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p2.scratch_size(0), 0);
+    ASSERT_EQ  (p4.league_size() , league_size);
+    ASSERT_EQ  (p4.team_size()   , team_size);
+    ASSERT_EQ  (p4.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p4.scratch_size(0), per_thread_scratch*team_size);
+
+    policy_t p5 = p2.set_scratch_size(0,Kokkos::PerThread(per_thread_scratch),Kokkos::PerTeam(per_team_scratch));
+    ASSERT_EQ  (p2.league_size() , league_size);
+    ASSERT_EQ  (p2.team_size()   , team_size);
+    ASSERT_EQ  (p2.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p2.scratch_size(0), 0);
+    ASSERT_EQ  (p5.league_size() , league_size);
+    ASSERT_EQ  (p5.team_size()   , team_size);
+    ASSERT_EQ  (p5.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p5.scratch_size(0), scratch_size);
+
+    policy_t p6 = p2.set_scratch_size(0,Kokkos::PerTeam(per_team_scratch),Kokkos::PerThread(per_thread_scratch));
+    ASSERT_EQ  (p2.league_size() , league_size);
+    ASSERT_EQ  (p2.team_size()   , team_size);
+    ASSERT_EQ  (p2.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p2.scratch_size(0), 0);
+    ASSERT_EQ  (p6.league_size() , league_size);
+    ASSERT_EQ  (p6.team_size()   , team_size);
+    ASSERT_EQ  (p6.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p6.scratch_size(0), scratch_size);
+
+    policy_t p7 = p3.set_scratch_size(0,Kokkos::PerTeam(per_team_scratch),Kokkos::PerThread(per_thread_scratch));
+    ASSERT_EQ  (p3.league_size() , league_size);
+    ASSERT_EQ  (p3.team_size()   , team_size);
+    ASSERT_EQ  (p3.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p3.scratch_size(0), per_team_scratch);
+    ASSERT_EQ  (p7.league_size() , league_size);
+    ASSERT_EQ  (p7.team_size()   , team_size);
+    ASSERT_EQ  (p7.chunk_size()  , chunk_size);
+    ASSERT_EQ  (p7.scratch_size(0), scratch_size);
+}
+  void test_run_time_parameters() {
+    test_run_time_parameters_type<Kokkos::TeamPolicy<ExecutionSpace> >();
+    test_run_time_parameters_type<Kokkos::TeamPolicy<ExecutionSpace,Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long> > >();
+    test_run_time_parameters_type<Kokkos::TeamPolicy<Kokkos::IndexType<long>, ExecutionSpace, Kokkos::Schedule<Kokkos::Dynamic> > >();
+    test_run_time_parameters_type<Kokkos::TeamPolicy<Kokkos::Schedule<Kokkos::Dynamic>,Kokkos::IndexType<long>,ExecutionSpace,SomeTag > >();
+  }
+};
diff --git a/lib/kokkos/core/unit_test/TestQthread.cpp b/lib/kokkos/core/unit_test/TestQthread.cpp
new file mode 100644
index 0000000000..431b844c9f
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestQthread.cpp
@@ -0,0 +1,290 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Qthread.hpp>
+
+#include <Qthread/Kokkos_Qthread_TaskPolicy.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestViewImpl.hpp>
+#include <TestAtomic.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewOfClass.hpp>
+
+#include <TestTeam.hpp>
+#include <TestRange.hpp>
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestAggregate.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestTaskPolicy.hpp>
+// #include <TestTeamVector.hpp>
+
+namespace Test {
+
+class qthread : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    const unsigned numa_count       = Kokkos::hwloc::get_available_numa_count();
+    const unsigned cores_per_numa   = Kokkos::hwloc::get_available_cores_per_numa();
+    const unsigned threads_per_core = Kokkos::hwloc::get_available_threads_per_core();
+
+    int threads_count = std::max( 1u , numa_count )
+                      * std::max( 2u , ( cores_per_numa * threads_per_core ) / 2 );
+    Kokkos::Qthread::initialize( threads_count );
+    Kokkos::Qthread::print_configuration( std::cout , true );
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::Qthread::finalize();
+  }
+};
+
+TEST_F( qthread , compiler_macros )
+{
+  ASSERT_TRUE( ( TestCompilerMacros::Test< Kokkos::Qthread >() ) );
+}
+
+TEST_F( qthread, view_impl) {
+  test_view_impl< Kokkos::Qthread >();
+}
+
+TEST_F( qthread, view_api) {
+  TestViewAPI< double , Kokkos::Qthread >();
+}
+
+TEST_F( qthread , view_nested_view )
+{
+  ::Test::view_nested_view< Kokkos::Qthread >();
+}
+
+TEST_F( qthread , range_tag )
+{
+  TestRange< Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestRange< Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestRange< Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >::test_scan(1000);
+}
+
+TEST_F( qthread , team_tag )
+{
+  TestTeamPolicy< Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >::test_for( 1000 );
+  TestTeamPolicy< Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >::test_reduce( 1000 );
+}
+
+TEST_F( qthread, long_reduce) {
+  TestReduce< long ,   Kokkos::Qthread >( 1000000 );
+}
+
+TEST_F( qthread, double_reduce) {
+  TestReduce< double ,   Kokkos::Qthread >( 1000000 );
+}
+
+TEST_F( qthread, long_reduce_dynamic ) {
+  TestReduceDynamic< long ,   Kokkos::Qthread >( 1000000 );
+}
+
+TEST_F( qthread, double_reduce_dynamic ) {
+  TestReduceDynamic< double ,   Kokkos::Qthread >( 1000000 );
+}
+
+TEST_F( qthread, long_reduce_dynamic_view ) {
+  TestReduceDynamicView< long ,   Kokkos::Qthread >( 1000000 );
+}
+
+TEST_F( qthread, team_long_reduce) {
+  TestReduceTeam< long ,   Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >( 1000000 );
+}
+
+TEST_F( qthread, team_double_reduce) {
+  TestReduceTeam< double ,   Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >( 1000000 );
+}
+
+
+TEST_F( qthread , atomics )
+{
+  const int loop_count = 1e4 ;
+
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Qthread>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Qthread>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Qthread>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Qthread>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Qthread>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Qthread>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Qthread>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Qthread>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Qthread>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Qthread>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Qthread>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Qthread>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Qthread>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Qthread>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Qthread>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Qthread>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Qthread>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Qthread>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Qthread>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Qthread>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Qthread>(100,3) ) );
+
+#if defined( KOKKOS_ENABLE_ASM )
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Qthread>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Qthread>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Qthread>(100,3) ) );
+#endif
+
+}
+
+TEST_F( qthread , view_remap )
+{
+  enum { N0 = 3 , N1 = 2 , N2 = 8 , N3 = 9 };
+
+  typedef Kokkos::View< double*[N1][N2][N3] ,
+                             Kokkos::LayoutRight ,
+                             Kokkos::Qthread > output_type ;
+
+  typedef Kokkos::View< int**[N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::Qthread > input_type ;
+
+  typedef Kokkos::View< int*[N0][N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::Qthread > diff_type ;
+
+  output_type output( "output" , N0 );
+  input_type  input ( "input" , N0 , N1 );
+  diff_type   diff  ( "diff" , N0 );
+
+  int value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    input(i0,i1,i2,i3) = ++value ;
+  }}}}
+
+  // Kokkos::deep_copy( diff , input ); // throw with incompatible shape
+  Kokkos::deep_copy( output , input );
+
+  value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    ++value ;
+    ASSERT_EQ( value , ((int) output(i0,i1,i2,i3) ) );
+  }}}}
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( qthread , view_aggregate )
+{
+  TestViewAggregate< Kokkos::Qthread >();
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( qthread , scan )
+{
+  TestScan< Kokkos::Qthread >::test_range( 1 , 1000 );
+  TestScan< Kokkos::Qthread >( 1000000 );
+  TestScan< Kokkos::Qthread >( 10000000 );
+  Kokkos::Qthread::fence();
+}
+
+TEST_F( qthread, team_shared ) {
+  TestSharedTeam< Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >();
+}
+
+TEST_F( qthread, shmem_size) {
+  TestShmemSize< Kokkos::Qthread >();
+}
+
+TEST_F( qthread , team_scan )
+{
+  TestScanTeam< Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >( 10 );
+  TestScanTeam< Kokkos::Qthread , Kokkos::Schedule<Kokkos::Static> >( 10000 );
+}
+
+#if 0 /* disable */
+TEST_F( qthread , team_vector )
+{
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Qthread >(0) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Qthread >(1) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Qthread >(2) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Qthread >(3) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Qthread >(4) ) );
+}
+#endif
+
+//----------------------------------------------------------------------------
+
+TEST_F( qthread , task_policy )
+{
+  TestTaskPolicy::test_task_dep< Kokkos::Qthread >( 10 );
+  for ( long i = 0 ; i < 25 ; ++i ) TestTaskPolicy::test_fib< Kokkos::Qthread >(i);
+  for ( long i = 0 ; i < 35 ; ++i ) TestTaskPolicy::test_fib2< Kokkos::Qthread >(i);
+}
+
+TEST_F( qthread , task_team )
+{
+  TestTaskPolicy::test_task_team< Kokkos::Qthread >(1000);
+}
+
+//----------------------------------------------------------------------------
+
+} // namespace test
+
diff --git a/lib/kokkos/core/unit_test/TestRange.hpp b/lib/kokkos/core/unit_test/TestRange.hpp
new file mode 100644
index 0000000000..be8b4f90a3
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestRange.hpp
@@ -0,0 +1,242 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdio.h>
+
+#include <Kokkos_Core.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+namespace {
+
+template< class ExecSpace, class ScheduleType >
+struct TestRange {
+
+  typedef int value_type ; ///< typedef required for the parallel_reduce
+
+  typedef Kokkos::View<int*,ExecSpace> view_type ;
+
+  view_type m_flags ;
+
+  struct VerifyInitTag {};
+  struct ResetTag {};
+  struct VerifyResetTag {};
+
+  TestRange( const size_t N )
+    : m_flags( Kokkos::ViewAllocateWithoutInitializing("flags"), N )
+    {}
+
+  static void test_for( const size_t N )
+    {
+      TestRange functor(N);
+
+      typename view_type::HostMirror host_flags = Kokkos::create_mirror_view( functor.m_flags );
+
+      Kokkos::parallel_for( Kokkos::RangePolicy<ExecSpace,ScheduleType>(0,N) , functor );
+      Kokkos::parallel_for( Kokkos::RangePolicy<ExecSpace,ScheduleType,VerifyInitTag>(0,N) , functor );
+
+      Kokkos::deep_copy( host_flags , functor.m_flags );
+
+      size_t error_count = 0 ;
+      for ( size_t i = 0 ; i < N ; ++i ) {
+        if ( int(i) != host_flags(i) ) ++error_count ;
+      }
+      ASSERT_EQ( error_count , size_t(0) );
+
+      Kokkos::parallel_for( Kokkos::RangePolicy<ExecSpace,ScheduleType,ResetTag>(0,N) , functor );
+      Kokkos::parallel_for( std::string("TestKernelFor") , Kokkos::RangePolicy<ExecSpace,ScheduleType,VerifyResetTag>(0,N) , functor );
+
+      Kokkos::deep_copy( host_flags , functor.m_flags );
+
+      error_count = 0 ;
+      for ( size_t i = 0 ; i < N ; ++i ) {
+        if ( int(2*i) != host_flags(i) ) ++error_count ;
+      }
+      ASSERT_EQ( error_count , size_t(0) );
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int i ) const
+    { m_flags(i) = i ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const VerifyInitTag & , const int i ) const
+    { if ( i != m_flags(i) ) { printf("TestRange::test_for error at %d != %d\n",i,m_flags(i)); } }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const ResetTag & , const int i ) const
+    { m_flags(i) = 2 * m_flags(i); }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const VerifyResetTag & , const int i ) const
+    { if ( 2 * i != m_flags(i) ) { printf("TestRange::test_for error at %d != %d\n",i,m_flags(i)); } }
+
+  //----------------------------------------
+
+  struct OffsetTag {};
+
+  static void test_reduce( const size_t N )
+    {
+      TestRange functor(N);
+      int total = 0 ;
+
+      Kokkos::parallel_for(    Kokkos::RangePolicy<ExecSpace,ScheduleType>(0,N) , functor );
+
+      Kokkos::parallel_reduce( "TestKernelReduce" , Kokkos::RangePolicy<ExecSpace,ScheduleType>(0,N) , functor , total );
+      // sum( 0 .. N-1 )
+      ASSERT_EQ( size_t((N-1)*(N)/2) , size_t(total) );
+
+      Kokkos::parallel_reduce( Kokkos::RangePolicy<ExecSpace,ScheduleType,OffsetTag>(0,N) , functor , total );
+      // sum( 1 .. N )
+      ASSERT_EQ( size_t((N)*(N+1)/2) , size_t(total) );
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int i , value_type & update ) const
+    { update += m_flags(i); }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const OffsetTag & , const int i , value_type & update ) const
+    { update += 1 + m_flags(i); }
+
+  //----------------------------------------
+
+  static void test_scan( const size_t N )
+    {
+      TestRange functor(N);
+
+      Kokkos::parallel_for( Kokkos::RangePolicy<ExecSpace,ScheduleType>(0,N) , functor );
+
+      Kokkos::parallel_scan( "TestKernelScan" , Kokkos::RangePolicy<ExecSpace,ScheduleType,OffsetTag>(0,N) , functor );
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const OffsetTag & , const int i , value_type & update , bool final ) const
+    {
+      update += m_flags(i);
+
+      if ( final ) {
+        if ( update != (i*(i+1))/2 ) {
+          printf("TestRange::test_scan error %d : %d != %d\n",i,(i*(i+1))/2,m_flags(i));
+        }
+      }
+    }
+
+  static void test_dynamic_policy( const size_t N ) {
+
+
+    typedef Kokkos::RangePolicy<ExecSpace,Kokkos::Schedule<Kokkos::Dynamic> > policy_t;
+
+    {
+      Kokkos::View<size_t*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Atomic> > count("Count",ExecSpace::concurrency());
+      Kokkos::View<int*,ExecSpace> a("A",N);
+
+      Kokkos::parallel_for( policy_t(0,N),
+          KOKKOS_LAMBDA (const typename policy_t::member_type& i) {
+        for(int k=0; k<(i<N/2?1:10000); k++ )
+          a(i)++;
+        count(ExecSpace::hardware_thread_id())++;
+      });
+
+      int error = 0;
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N), KOKKOS_LAMBDA(const typename policy_t::member_type& i, int& lsum) {
+        lsum += ( a(i)!= (i<N/2?1:10000) );
+      },error);
+      ASSERT_EQ(error,0);
+
+      if( ( ExecSpace::concurrency()>(int)1) && (N>static_cast<const size_t>(4*ExecSpace::concurrency())) ) {
+        size_t min = N;
+        size_t max = 0;
+        for(int t=0; t<ExecSpace::concurrency(); t++) {
+          if(count(t)<min) min = count(t);
+          if(count(t)>max) max = count(t);
+        }
+        ASSERT_TRUE(min<max);
+        //if(ExecSpace::concurrency()>2)
+        //  ASSERT_TRUE(2*min<max);
+      }
+      
+    }
+
+    {
+      Kokkos::View<size_t*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Atomic> > count("Count",ExecSpace::concurrency());
+      Kokkos::View<int*,ExecSpace> a("A",N);
+
+      int sum = 0;
+      Kokkos::parallel_reduce( policy_t(0,N),
+          KOKKOS_LAMBDA (const typename policy_t::member_type& i, int& lsum) {
+        for(int k=0; k<(i<N/2?1:10000); k++ )
+          a(i)++;
+        count(ExecSpace::hardware_thread_id())++;
+        lsum++;
+      },sum);
+      ASSERT_EQ(sum,N);
+
+      int error = 0;
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N), KOKKOS_LAMBDA(const typename policy_t::member_type& i, int& lsum) {
+        lsum += ( a(i)!= (i<N/2?1:10000) );
+      },error);
+      ASSERT_EQ(error,0);
+
+      if( ( ExecSpace::concurrency()>(int)1) && (N>static_cast<const size_t>(4*ExecSpace::concurrency())) ) {
+        size_t min = N;
+        size_t max = 0;
+        for(int t=0; t<ExecSpace::concurrency(); t++) {
+          if(count(t)<min) min = count(t);
+          if(count(t)>max) max = count(t);
+        }
+        ASSERT_TRUE(min<max);
+        //if(ExecSpace::concurrency()>2)
+        //  ASSERT_TRUE(2*min<max);
+      }
+    }
+
+  }
+};
+
+} /* namespace */
+} /* namespace Test */
+
+/*--------------------------------------------------------------------------*/
+
diff --git a/lib/kokkos/core/unit_test/TestReduce.hpp b/lib/kokkos/core/unit_test/TestReduce.hpp
new file mode 100644
index 0000000000..53fc393bcc
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestReduce.hpp
@@ -0,0 +1,1872 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+#include <limits>
+
+#include <Kokkos_Core.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+template< typename ScalarType , class DeviceType >
+class ReduceFunctor
+{
+public:
+  typedef DeviceType  execution_space ;
+  typedef typename execution_space::size_type size_type ;
+
+  struct value_type {
+    ScalarType value[3] ;
+  };
+
+  const size_type nwork ;
+
+  ReduceFunctor( const size_type & arg_nwork ) : nwork( arg_nwork ) {}
+
+  ReduceFunctor( const ReduceFunctor & rhs )
+    : nwork( rhs.nwork ) {}
+
+/*
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & dst ) const
+  {
+    dst.value[0] = 0 ;
+    dst.value[1] = 0 ;
+    dst.value[2] = 0 ;
+  }
+*/
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst ,
+             const volatile value_type & src ) const
+  {
+    dst.value[0] += src.value[0] ;
+    dst.value[1] += src.value[1] ;
+    dst.value[2] += src.value[2] ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type iwork , value_type & dst ) const
+  {
+    dst.value[0] += 1 ;
+    dst.value[1] += iwork + 1 ;
+    dst.value[2] += nwork - iwork ;
+  }
+};
+
+template< class DeviceType >
+class ReduceFunctorFinal : public ReduceFunctor< long , DeviceType > {
+public:
+
+  typedef typename ReduceFunctor< long , DeviceType >::value_type value_type ;
+
+  ReduceFunctorFinal( const size_t n )
+    : ReduceFunctor<long,DeviceType>(n)
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void final( value_type & dst ) const
+  {
+    dst.value[0] = - dst.value[0] ;
+    dst.value[1] = - dst.value[1] ;
+    dst.value[2] = - dst.value[2] ;
+  }
+};
+
+template< typename ScalarType , class DeviceType >
+class RuntimeReduceFunctor
+{
+public:
+  // Required for functor:
+  typedef DeviceType  execution_space ;
+  typedef ScalarType  value_type[] ;
+  const unsigned      value_count ;
+
+
+  // Unit test details:
+
+  typedef typename execution_space::size_type  size_type ;
+
+  const size_type     nwork ;
+
+  RuntimeReduceFunctor( const size_type arg_nwork ,
+                        const size_type arg_count )
+    : value_count( arg_count )
+    , nwork( arg_nwork ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void init( ScalarType dst[] ) const
+  {
+    for ( unsigned i = 0 ; i < value_count ; ++i ) dst[i] = 0 ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile ScalarType dst[] ,
+             const volatile ScalarType src[] ) const
+  {
+    for ( unsigned i = 0 ; i < value_count ; ++i ) dst[i] += src[i] ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type iwork , ScalarType dst[] ) const
+  {
+    const size_type tmp[3] = { 1 , iwork + 1 , nwork - iwork };
+
+    for ( size_type i = 0 ; i < value_count ; ++i ) {
+      dst[i] += tmp[ i % 3 ];
+    }
+  }
+};
+
+template< typename ScalarType , class DeviceType >
+class RuntimeReduceMinMax
+{
+public:
+  // Required for functor:
+  typedef DeviceType  execution_space ;
+  typedef ScalarType  value_type[] ;
+  const unsigned      value_count ;
+
+  // Unit test details:
+
+  typedef typename execution_space::size_type  size_type ;
+
+  const size_type     nwork ;
+  const ScalarType    amin ;
+  const ScalarType    amax ;
+
+  RuntimeReduceMinMax( const size_type arg_nwork ,
+                       const size_type arg_count )
+    : value_count( arg_count )
+    , nwork( arg_nwork )
+    , amin( std::numeric_limits<ScalarType>::min() )
+    , amax( std::numeric_limits<ScalarType>::max() )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void init( ScalarType dst[] ) const
+  {
+    for ( unsigned i = 0 ; i < value_count ; ++i ) {
+      dst[i] = i % 2 ? amax : amin ;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile ScalarType dst[] ,
+             const volatile ScalarType src[] ) const
+  {
+    for ( unsigned i = 0 ; i < value_count ; ++i ) {
+      dst[i] = i % 2 ? ( dst[i] < src[i] ? dst[i] : src[i] )  // min
+                     : ( dst[i] > src[i] ? dst[i] : src[i] ); // max
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type iwork , ScalarType dst[] ) const
+  {
+    const ScalarType tmp[2] = { ScalarType(iwork + 1)
+                              , ScalarType(nwork - iwork) };
+
+    for ( size_type i = 0 ; i < value_count ; ++i ) {
+      dst[i] = i % 2 ? ( dst[i] < tmp[i%2] ? dst[i] : tmp[i%2] )
+                     : ( dst[i] > tmp[i%2] ? dst[i] : tmp[i%2] );
+    }
+  }
+};
+
+template< class DeviceType >
+class RuntimeReduceFunctorFinal : public RuntimeReduceFunctor< long , DeviceType > {
+public:
+
+  typedef RuntimeReduceFunctor< long , DeviceType > base_type ;
+  typedef typename base_type::value_type value_type ;
+  typedef long scalar_type ;
+
+  RuntimeReduceFunctorFinal( const size_t theNwork , const size_t count ) : base_type(theNwork,count) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void final( value_type dst ) const
+  {
+    for ( unsigned i = 0 ; i < base_type::value_count ; ++i ) {
+      dst[i] = - dst[i] ;
+    }
+  }
+};
+} // namespace Test
+
+namespace {
+
+template< typename ScalarType , class DeviceType >
+class TestReduce
+{
+public:
+  typedef DeviceType    execution_space ;
+  typedef typename execution_space::size_type size_type ;
+
+  //------------------------------------
+
+  TestReduce( const size_type & nwork )
+  {
+    run_test(nwork);
+    run_test_final(nwork);
+  }
+
+  void run_test( const size_type & nwork )
+  {
+    typedef Test::ReduceFunctor< ScalarType , execution_space > functor_type ;
+    typedef typename functor_type::value_type value_type ;
+
+    enum { Count = 3 };
+    enum { Repeat = 100 };
+
+    value_type result[ Repeat ];
+
+    const unsigned long nw   = nwork ;
+    const unsigned long nsum = nw % 2 ? nw * (( nw + 1 )/2 )
+                                      : (nw/2) * ( nw + 1 );
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      Kokkos::parallel_reduce( nwork , functor_type(nwork) , result[i] );
+    }
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      for ( unsigned j = 0 ; j < Count ; ++j ) {
+        const unsigned long correct = 0 == j % 3 ? nw : nsum ;
+        ASSERT_EQ( (ScalarType) correct , result[i].value[j] );
+      }
+    }
+  }
+
+  void run_test_final( const size_type & nwork )
+  {
+    typedef Test::ReduceFunctorFinal< execution_space > functor_type ;
+    typedef typename functor_type::value_type value_type ;
+
+    enum { Count = 3 };
+    enum { Repeat = 100 };
+
+    value_type result[ Repeat ];
+
+    const unsigned long nw   = nwork ;
+    const unsigned long nsum = nw % 2 ? nw * (( nw + 1 )/2 )
+                                      : (nw/2) * ( nw + 1 );
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      if(i%2==0)
+        Kokkos::parallel_reduce( nwork , functor_type(nwork) , result[i] );
+      else
+        Kokkos::parallel_reduce( "Reduce", nwork , functor_type(nwork) , result[i] );
+    }
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      for ( unsigned j = 0 ; j < Count ; ++j ) {
+        const unsigned long correct = 0 == j % 3 ? nw : nsum ;
+        ASSERT_EQ( (ScalarType) correct , - result[i].value[j] );
+      }
+    }
+  }
+};
+
+template< typename ScalarType , class DeviceType >
+class TestReduceDynamic
+{
+public:
+  typedef DeviceType    execution_space ;
+  typedef typename execution_space::size_type size_type ;
+
+  //------------------------------------
+
+  TestReduceDynamic( const size_type nwork )
+  {
+    run_test_dynamic(nwork);
+    run_test_dynamic_minmax(nwork);
+    run_test_dynamic_final(nwork);
+  }
+
+  void run_test_dynamic( const size_type nwork )
+  {
+    typedef Test::RuntimeReduceFunctor< ScalarType , execution_space > functor_type ;
+
+    enum { Count = 3 };
+    enum { Repeat = 100 };
+
+    ScalarType result[ Repeat ][ Count ] ;
+
+    const unsigned long nw   = nwork ;
+    const unsigned long nsum = nw % 2 ? nw * (( nw + 1 )/2 )
+                                      : (nw/2) * ( nw + 1 );
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      if(i%2==0)
+        Kokkos::parallel_reduce( nwork , functor_type(nwork,Count) , result[i] );
+      else
+        Kokkos::parallel_reduce( "Reduce", nwork , functor_type(nwork,Count) , result[i] );
+    }
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      for ( unsigned j = 0 ; j < Count ; ++j ) {
+        const unsigned long correct = 0 == j % 3 ? nw : nsum ;
+        ASSERT_EQ( (ScalarType) correct , result[i][j] );
+      }
+    }
+  }
+
+  void run_test_dynamic_minmax( const size_type nwork )
+  {
+    typedef Test::RuntimeReduceMinMax< ScalarType , execution_space > functor_type ;
+
+    enum { Count = 2 };
+    enum { Repeat = 100 };
+
+    ScalarType result[ Repeat ][ Count ] ;
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      if(i%2==0)
+        Kokkos::parallel_reduce( nwork , functor_type(nwork,Count) , result[i] );
+      else
+        Kokkos::parallel_reduce( "Reduce", nwork , functor_type(nwork,Count) , result[i] );
+    }
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      for ( unsigned j = 0 ; j < Count ; ++j ) {
+        const unsigned long correct = j % 2 ? 1 : nwork ;
+        ASSERT_EQ( (ScalarType) correct , result[i][j] );
+      }
+    }
+  }
+
+  void run_test_dynamic_final( const size_type nwork )
+  {
+    typedef Test::RuntimeReduceFunctorFinal< execution_space > functor_type ;
+
+    enum { Count = 3 };
+    enum { Repeat = 100 };
+
+    typename functor_type::scalar_type result[ Repeat ][ Count ] ;
+
+    const unsigned long nw   = nwork ;
+    const unsigned long nsum = nw % 2 ? nw * (( nw + 1 )/2 )
+                                      : (nw/2) * ( nw + 1 );
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      if(i%2==0)
+        Kokkos::parallel_reduce( nwork , functor_type(nwork,Count) , result[i] );
+      else
+        Kokkos::parallel_reduce( "TestKernelReduce" , nwork , functor_type(nwork,Count) , result[i] );
+
+    }
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      for ( unsigned j = 0 ; j < Count ; ++j ) {
+        const unsigned long correct = 0 == j % 3 ? nw : nsum ;
+        ASSERT_EQ( (ScalarType) correct , - result[i][j] );
+      }
+    }
+  }
+};
+
+template< typename ScalarType , class DeviceType >
+class TestReduceDynamicView
+{
+public:
+  typedef DeviceType    execution_space ;
+  typedef typename execution_space::size_type size_type ;
+
+  //------------------------------------
+
+  TestReduceDynamicView( const size_type nwork )
+  {
+    run_test_dynamic_view(nwork);
+  }
+
+  void run_test_dynamic_view( const size_type nwork )
+  {
+    typedef Test::RuntimeReduceFunctor< ScalarType , execution_space > functor_type ;
+
+    typedef Kokkos::View< ScalarType* , DeviceType > result_type ;
+    typedef typename result_type::HostMirror result_host_type ;
+
+    const unsigned CountLimit = 23 ;
+
+    const unsigned long nw   = nwork ;
+    const unsigned long nsum = nw % 2 ? nw * (( nw + 1 )/2 )
+                                      : (nw/2) * ( nw + 1 );
+
+    for ( unsigned count = 0 ; count < CountLimit ; ++count ) {
+
+      result_type result("result",count);
+      result_host_type host_result = Kokkos::create_mirror( result );
+
+      // Test result to host pointer:
+
+      std::string str("TestKernelReduce");
+      if(count%2==0)
+        Kokkos::parallel_reduce( nw , functor_type(nw,count) , host_result.ptr_on_device() );
+      else
+        Kokkos::parallel_reduce( str , nw , functor_type(nw,count) , host_result.ptr_on_device() );
+
+      for ( unsigned j = 0 ; j < count ; ++j ) {
+        const unsigned long correct = 0 == j % 3 ? nw : nsum ;
+        ASSERT_EQ( host_result(j), (ScalarType) correct );
+        host_result(j) = 0 ;
+      }
+    }
+  }
+};
+}
+
+// Computes y^T*A*x
+// (modified from kokkos-tutorials/GTC2016/Exercises/ThreeLevelPar )
+
+#if ( ! defined( KOKKOS_HAVE_CUDA ) ) || defined( KOKKOS_CUDA_USE_LAMBDA )
+
+template< typename ScalarType , class DeviceType >
+class TestTripleNestedReduce
+{
+public:
+  typedef DeviceType execution_space ;
+  typedef typename execution_space::size_type size_type ;
+
+  //------------------------------------
+
+  TestTripleNestedReduce( const size_type & nrows , const size_type & ncols 
+                        , const size_type & team_size , const size_type & vector_length )
+  {
+    run_test( nrows , ncols , team_size, vector_length );
+  }
+
+  void run_test( const size_type & nrows , const size_type & ncols 
+               , const size_type & team_size, const size_type & vector_length )
+  {
+    //typedef Kokkos::LayoutLeft Layout;
+    typedef Kokkos::LayoutRight Layout;
+
+    typedef Kokkos::View<ScalarType* , DeviceType>            ViewVector;
+    typedef Kokkos::View<ScalarType** , Layout , DeviceType>   ViewMatrix;
+    ViewVector y( "y" , nrows );
+    ViewVector x( "x" , ncols );
+    ViewMatrix A( "A" , nrows , ncols );
+
+    typedef Kokkos::RangePolicy<DeviceType> range_policy;
+
+    // Initialize y vector
+    Kokkos::parallel_for( range_policy( 0 , nrows ) , KOKKOS_LAMBDA( const int i ) { y( i ) = 1; } );
+
+    // Initialize x vector
+    Kokkos::parallel_for( range_policy( 0 , ncols ) , KOKKOS_LAMBDA( const int i ) { x( i ) = 1; } );
+
+    typedef Kokkos::TeamPolicy<DeviceType>                        team_policy;
+    typedef typename Kokkos::TeamPolicy<DeviceType>::member_type  member_type;
+
+    // Initialize A matrix, note 2D indexing computation
+    Kokkos::parallel_for( team_policy( nrows , Kokkos::AUTO ) , KOKKOS_LAMBDA( const member_type& teamMember ) {
+      const int j = teamMember.league_rank();
+      Kokkos::parallel_for( Kokkos::TeamThreadRange( teamMember , ncols ) , [&] ( const int i ) {
+        A( j , i ) = 1;
+      } );
+    } );
+
+    // Three level parallelism kernel to force caching of vector x 
+    ScalarType result = 0.0;
+    int chunk_size = 128;
+    Kokkos::parallel_reduce( team_policy( nrows/chunk_size , team_size , vector_length ) , KOKKOS_LAMBDA ( const member_type& teamMember , double &update ) {
+      const int row_start = teamMember.league_rank() * chunk_size;
+      const int row_end   = row_start + chunk_size;
+      Kokkos::parallel_for( Kokkos::TeamThreadRange( teamMember , row_start , row_end ) , [&] ( const int i ) {
+        ScalarType sum_i = 0.0;
+        Kokkos::parallel_reduce( Kokkos::ThreadVectorRange( teamMember , ncols ) , [&] ( const int j , ScalarType &innerUpdate ) {
+          innerUpdate += A( i , j ) * x( j );
+        } , sum_i );
+        Kokkos::single( Kokkos::PerThread( teamMember ) , [&] () {
+          update += y( i ) * sum_i;
+        } );
+      } );
+    } , result );
+
+    const ScalarType solution= ( ScalarType ) nrows * ( ScalarType ) ncols;
+    ASSERT_EQ( solution , result );
+  }
+};
+
+#else /* #if ( ! defined( KOKKOS_HAVE_CUDA ) ) || defined( KOKKOS_CUDA_USE_LAMBDA ) */
+
+template< typename ScalarType , class DeviceType >
+class TestTripleNestedReduce
+{
+public:
+  typedef DeviceType execution_space ;
+  typedef typename execution_space::size_type size_type ;
+
+  TestTripleNestedReduce( const size_type & , const size_type  
+                        , const size_type & , const size_type )
+  { }
+};
+
+#endif
+
+//--------------------------------------------------------------------------
+
+namespace Test {
+namespace ReduceCombinatorical {
+
+template<class Scalar,class Space = Kokkos::HostSpace>
+struct AddPlus {
+public:
+  //Required
+  typedef AddPlus reducer_type;
+  typedef Scalar value_type;
+
+  typedef Kokkos::View<value_type, Space, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
+
+private:
+  result_view_type result;
+
+public:
+
+  AddPlus(value_type& result_):result(&result_) {}
+
+  //Required
+  KOKKOS_INLINE_FUNCTION
+  void join(value_type& dest, const value_type& src)  const {
+    dest += src + 1;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& dest, const volatile value_type& src) const {
+    dest += src + 1;
+  }
+
+  //Optional
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type& val)  const {
+    val = value_type();
+  }
+
+  result_view_type result_view() const {
+    return result;
+  }
+};
+
+template<int ISTEAM>
+struct FunctorScalar;
+
+template<>
+struct FunctorScalar<0>{
+  FunctorScalar(Kokkos::View<double> r):result(r) {}
+  Kokkos::View<double> result;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i,double& update) const {
+    update+=i;
+  }
+};
+
+template<>
+struct FunctorScalar<1>{
+  FunctorScalar(Kokkos::View<double> r):result(r) {}
+  Kokkos::View<double> result;
+
+  typedef Kokkos::TeamPolicy<>::member_type team_type;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_type& team,double& update) const {
+    update+=1.0/team.team_size()*team.league_rank();
+  }
+};
+
+template<int ISTEAM>
+struct FunctorScalarInit;
+
+template<>
+struct FunctorScalarInit<0> {
+  FunctorScalarInit(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i, double& update)  const {
+    update += i;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init(double& update) const {
+    update = 0.0;
+  }
+};
+
+template<>
+struct FunctorScalarInit<1> {
+  FunctorScalarInit(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+
+  typedef Kokkos::TeamPolicy<>::member_type team_type;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_type& team,double& update) const {
+    update+=1.0/team.team_size()*team.league_rank();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init(double& update) const {
+    update = 0.0;
+  }
+};
+
+template<int ISTEAM>
+struct FunctorScalarFinal;
+
+
+template<>
+struct FunctorScalarFinal<0> {
+  FunctorScalarFinal(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i, double& update)  const {
+    update += i;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void final(double& update) const {
+    result() = update;
+  }
+};
+
+template<>
+struct FunctorScalarFinal<1> {
+  FunctorScalarFinal(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+
+  typedef Kokkos::TeamPolicy<>::member_type team_type;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_type& team, double& update) const {
+    update+=1.0/team.team_size()*team.league_rank();
+  }
+  KOKKOS_INLINE_FUNCTION
+  void final(double& update) const {
+    result() = update;
+  }
+};
+
+template<int ISTEAM>
+struct FunctorScalarJoin;
+
+template<>
+struct FunctorScalarJoin<0> {
+  FunctorScalarJoin(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i, double& update)  const {
+    update += i;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile double& dst, const volatile double& update) const {
+    dst += update;
+  }
+};
+
+template<>
+struct FunctorScalarJoin<1> {
+  FunctorScalarJoin(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+
+  typedef Kokkos::TeamPolicy<>::member_type team_type;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_type& team,double& update) const {
+    update+=1.0/team.team_size()*team.league_rank();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile double& dst, const volatile double& update) const {
+    dst += update;
+  }
+};
+
+template<int ISTEAM>
+struct FunctorScalarJoinFinal;
+
+template<>
+struct FunctorScalarJoinFinal<0> {
+  FunctorScalarJoinFinal(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i, double& update)  const {
+    update += i;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile double& dst, const volatile double& update) const {
+    dst += update;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void final(double& update) const {
+    result() = update;
+  }
+};
+
+template<>
+struct FunctorScalarJoinFinal<1> {
+  FunctorScalarJoinFinal(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+
+  typedef Kokkos::TeamPolicy<>::member_type team_type;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_type& team,double& update) const {
+    update+=1.0/team.team_size()*team.league_rank();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile double& dst, const volatile double& update) const {
+    dst += update;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void final(double& update) const {
+    result() = update;
+  }
+};
+
+template<int ISTEAM>
+struct FunctorScalarJoinInit;
+
+template<>
+struct FunctorScalarJoinInit<0> {
+  FunctorScalarJoinInit(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i, double& update)  const {
+    update += i;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile double& dst, const volatile double& update) const {
+    dst += update;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init(double& update) const {
+    update = 0.0;
+  }
+};
+
+template<>
+struct FunctorScalarJoinInit<1> {
+  FunctorScalarJoinInit(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+
+  typedef Kokkos::TeamPolicy<>::member_type team_type;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_type& team,double& update) const {
+    update+=1.0/team.team_size()*team.league_rank();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile double& dst, const volatile double& update) const {
+    dst += update;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init(double& update) const {
+    update = 0.0;
+  }
+};
+
+template<int ISTEAM>
+struct FunctorScalarJoinFinalInit;
+
+template<>
+struct FunctorScalarJoinFinalInit<0> {
+  FunctorScalarJoinFinalInit(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i, double& update)  const {
+    update += i;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile double& dst, const volatile double& update) const {
+    dst += update;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void final(double& update) const {
+    result() = update;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init(double& update) const {
+    update = 0.0;
+  }
+};
+
+template<>
+struct FunctorScalarJoinFinalInit<1> {
+  FunctorScalarJoinFinalInit(Kokkos::View<double> r):result(r) {}
+
+  Kokkos::View<double> result;
+
+  typedef Kokkos::TeamPolicy<>::member_type team_type;
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const team_type& team,double& update) const {
+    update+=1.0/team.team_size()*team.league_rank();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile double& dst, const volatile double& update) const {
+    dst += update;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void final(double& update) const {
+    result() = update;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init(double& update) const {
+    update = 0.0;
+  }
+};
+struct Functor1 {
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i,double& update) const {
+    update+=i;
+  }
+};
+
+struct Functor2 {
+  typedef double value_type[];
+  const unsigned value_count;
+
+  Functor2(unsigned n):value_count(n){}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const unsigned& i,double update[]) const {
+    for(unsigned j=0;j<value_count;j++)
+      update[j]+=i;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( double dst[] ) const
+  {
+    for ( unsigned i = 0 ; i < value_count ; ++i ) dst[i] = 0 ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile double dst[] ,
+             const volatile double src[] ) const
+  {
+    for ( unsigned i = 0 ; i < value_count ; ++i ) dst[i] += src[i] ;
+  }
+};
+
+}
+}
+
+namespace Test {
+
+template<class ExecSpace = Kokkos::DefaultExecutionSpace>
+struct TestReduceCombinatoricalInstantiation {
+  template<class ... Args>
+  static void CallParallelReduce(Args... args) {
+    Kokkos::parallel_reduce(args...);
+  }
+
+  template<class ... Args>
+  static void AddReturnArgument(Args... args) {
+    Kokkos::View<double,Kokkos::HostSpace> result_view("ResultView");
+    double expected_result = 1000.0*999.0/2.0;
+
+    double value = 0;
+    Kokkos::parallel_reduce(args...,value);
+    ASSERT_EQ(expected_result,value);
+
+    result_view() = 0;
+    CallParallelReduce(args...,result_view);
+    ASSERT_EQ(expected_result,result_view());
+
+    value = 0;
+    CallParallelReduce(args...,Kokkos::View<double,Kokkos::HostSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>(&value));
+    ASSERT_EQ(expected_result,value);
+
+    result_view() = 0;
+    const Kokkos::View<double,Kokkos::HostSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> result_view_const_um = result_view;
+    CallParallelReduce(args...,result_view_const_um);
+    ASSERT_EQ(expected_result,result_view_const_um());
+
+    value = 0;
+    CallParallelReduce(args...,Test::ReduceCombinatorical::AddPlus<double>(value));
+    if((Kokkos::DefaultExecutionSpace::concurrency() > 1) && (ExecSpace::concurrency()>1))
+      ASSERT_TRUE(expected_result<value);
+    else if((Kokkos::DefaultExecutionSpace::concurrency() > 1) || (ExecSpace::concurrency()>1))
+      ASSERT_TRUE(expected_result<=value);
+    else
+      ASSERT_EQ(expected_result,value);
+
+    value = 0;
+    Test::ReduceCombinatorical::AddPlus<double> add(value);
+    CallParallelReduce(args...,add);
+    if((Kokkos::DefaultExecutionSpace::concurrency() > 1) && (ExecSpace::concurrency()>1))
+      ASSERT_TRUE(expected_result<value);
+    else if((Kokkos::DefaultExecutionSpace::concurrency() > 1) || (ExecSpace::concurrency()>1))
+      ASSERT_TRUE(expected_result<=value);
+    else
+      ASSERT_EQ(expected_result,value);
+  }
+
+
+  template<class ... Args>
+  static void AddLambdaRange(void*,Args... args) {
+    AddReturnArgument(args...,  KOKKOS_LAMBDA (const int&i , double& lsum) {
+      lsum += i;
+    });
+  }
+
+  template<class ... Args>
+  static void AddLambdaTeam(void*,Args... args) {
+    AddReturnArgument(args..., KOKKOS_LAMBDA (const Kokkos::TeamPolicy<>::member_type& team, double& update) {
+      update+=1.0/team.team_size()*team.league_rank();
+    });
+  }
+
+  template<class ... Args>
+  static void AddLambdaRange(Kokkos::InvalidType,Args... args) {
+  }
+
+  template<class ... Args>
+  static void AddLambdaTeam(Kokkos::InvalidType,Args... args) {
+  }
+
+  template<int ISTEAM, class ... Args>
+  static void AddFunctor(Args... args) {
+    Kokkos::View<double> result_view("FunctorView");
+    auto h_r = Kokkos::create_mirror_view(result_view);
+    Test::ReduceCombinatorical::FunctorScalar<ISTEAM> functor(result_view);
+    double expected_result = 1000.0*999.0/2.0;
+
+    AddReturnArgument(args..., functor);
+    AddReturnArgument(args..., Test::ReduceCombinatorical::FunctorScalar<ISTEAM>(result_view));
+    AddReturnArgument(args..., Test::ReduceCombinatorical::FunctorScalarInit<ISTEAM>(result_view));
+    AddReturnArgument(args..., Test::ReduceCombinatorical::FunctorScalarJoin<ISTEAM>(result_view));
+    AddReturnArgument(args..., Test::ReduceCombinatorical::FunctorScalarJoinInit<ISTEAM>(result_view));
+
+    h_r() = 0;
+    Kokkos::deep_copy(result_view,h_r);
+    CallParallelReduce(args..., Test::ReduceCombinatorical::FunctorScalarFinal<ISTEAM>(result_view));
+    Kokkos::deep_copy(h_r,result_view);
+    ASSERT_EQ(expected_result,h_r());
+
+    h_r() = 0;
+    Kokkos::deep_copy(result_view,h_r);
+    CallParallelReduce(args..., Test::ReduceCombinatorical::FunctorScalarJoinFinal<ISTEAM>(result_view));
+    Kokkos::deep_copy(h_r,result_view);
+    ASSERT_EQ(expected_result,h_r());
+
+    h_r() = 0;
+    Kokkos::deep_copy(result_view,h_r);
+    CallParallelReduce(args..., Test::ReduceCombinatorical::FunctorScalarJoinFinalInit<ISTEAM>(result_view));
+    Kokkos::deep_copy(h_r,result_view);
+    ASSERT_EQ(expected_result,h_r());
+  }
+
+  template<class ... Args>
+  static void AddFunctorLambdaRange(Args... args) {
+    AddFunctor<0,Args...>(args...);
+    #ifdef  KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA
+    AddLambdaRange(typename std::conditional<std::is_same<ExecSpace,Kokkos::DefaultExecutionSpace>::value,void*,Kokkos::InvalidType>::type(), args...);
+    #endif
+  }
+
+  template<class ... Args>
+  static void AddFunctorLambdaTeam(Args... args) {
+    AddFunctor<1,Args...>(args...);
+    #ifdef  KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA
+    AddLambdaTeam(typename std::conditional<std::is_same<ExecSpace,Kokkos::DefaultExecutionSpace>::value,void*,Kokkos::InvalidType>::type(), args...);
+    #endif
+  }
+
+  template<class ... Args>
+  static void AddPolicy(Args... args) {
+    int N = 1000;
+    Kokkos::RangePolicy<ExecSpace> policy(0,N);
+
+    AddFunctorLambdaRange(args...,1000);
+    AddFunctorLambdaRange(args...,N);
+    AddFunctorLambdaRange(args...,policy);
+    AddFunctorLambdaRange(args...,Kokkos::RangePolicy<ExecSpace>(0,N));
+    AddFunctorLambdaRange(args...,Kokkos::RangePolicy<ExecSpace,Kokkos::Schedule<Kokkos::Dynamic> >(0,N));
+    AddFunctorLambdaRange(args...,Kokkos::RangePolicy<ExecSpace,Kokkos::Schedule<Kokkos::Static> >(0,N).set_chunk_size(10));
+    AddFunctorLambdaRange(args...,Kokkos::RangePolicy<ExecSpace,Kokkos::Schedule<Kokkos::Dynamic> >(0,N).set_chunk_size(10));
+
+    AddFunctorLambdaTeam(args...,Kokkos::TeamPolicy<ExecSpace>(N,Kokkos::AUTO));
+    AddFunctorLambdaTeam(args...,Kokkos::TeamPolicy<ExecSpace,Kokkos::Schedule<Kokkos::Dynamic> >(N,Kokkos::AUTO));
+    AddFunctorLambdaTeam(args...,Kokkos::TeamPolicy<ExecSpace,Kokkos::Schedule<Kokkos::Static> >(N,Kokkos::AUTO).set_chunk_size(10));
+    AddFunctorLambdaTeam(args...,Kokkos::TeamPolicy<ExecSpace,Kokkos::Schedule<Kokkos::Dynamic> >(N,Kokkos::AUTO).set_chunk_size(10));
+  }
+
+
+  static void AddLabel() {
+    std::string s("Std::String");
+    AddPolicy();
+    AddPolicy("Char Constant");
+    AddPolicy(s.c_str());
+    AddPolicy(s);
+  }
+
+  static void execute() {
+    AddLabel();
+  }
+};
+
+template<class Scalar, class ExecSpace = Kokkos::DefaultExecutionSpace>
+struct TestReducers {
+
+  struct SumFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      value += values(i);
+    }
+  };
+
+  struct ProdFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      value *= values(i);
+    }
+  };
+
+  struct MinFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      if(values(i) < value)
+        value = values(i);
+    }
+  };
+
+  struct MaxFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      if(values(i) > value)
+        value = values(i);
+    }
+  };
+
+  struct MinLocFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i,
+        typename Kokkos::Experimental::MinLoc<Scalar,int>::value_type& value) const {
+      if(values(i) < value.val) {
+        value.val = values(i);
+        value.loc = i;
+      }
+    }
+  };
+
+  struct MaxLocFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i,
+        typename Kokkos::Experimental::MaxLoc<Scalar,int>::value_type& value) const {
+      if(values(i) > value.val) {
+        value.val = values(i);
+        value.loc = i;
+      }
+    }
+  };
+
+  struct MinMaxLocFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i,
+        typename Kokkos::Experimental::MinMaxLoc<Scalar,int>::value_type& value) const {
+      if(values(i) > value.max_val) {
+        value.max_val = values(i);
+        value.max_loc = i;
+      }
+      if(values(i) < value.min_val) {
+        value.min_val = values(i);
+        value.min_loc = i;
+      }
+    }
+  };
+
+  struct BAndFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      value = value & values(i);
+    }
+  };
+
+  struct BOrFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      value = value | values(i);
+    }
+  };
+
+  struct BXorFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      value = value ^ values(i);
+    }
+  };
+
+  struct LAndFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      value = value && values(i);
+    }
+  };
+
+  struct LOrFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      value = value || values(i);
+    }
+  };
+
+  struct LXorFunctor {
+    Kokkos::View<const Scalar*,ExecSpace> values;
+    KOKKOS_INLINE_FUNCTION
+    void operator() (const int& i, Scalar& value) const {
+      value = value ? (!values(i)) : values(i);
+    }
+  };
+
+  static void test_sum(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_sum = 0;
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%100);
+      reference_sum += h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    SumFunctor f;
+    f.values = values;
+    Scalar init = 0;
+
+    {
+      Scalar sum_scalar = init;
+      Kokkos::Experimental::Sum<Scalar> reducer_scalar(sum_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(sum_scalar,reference_sum);
+      Scalar sum_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(sum_scalar_view,reference_sum);
+    }
+    {
+      Scalar sum_scalar_init = init;
+      Kokkos::Experimental::Sum<Scalar> reducer_scalar_init(sum_scalar_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar_init);
+      ASSERT_EQ(sum_scalar_init,reference_sum);
+      Scalar sum_scalar_init_view = reducer_scalar_init.result_view()();
+      ASSERT_EQ(sum_scalar_init_view,reference_sum);
+    }
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> sum_view("View");
+      sum_view() = init;
+      Kokkos::Experimental::Sum<Scalar> reducer_view(sum_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar sum_view_scalar = sum_view();
+      ASSERT_EQ(sum_view_scalar,reference_sum);
+      Scalar sum_view_view = reducer_view.result_view()();
+      ASSERT_EQ(sum_view_view,reference_sum);
+    }
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> sum_view_init("View");
+      sum_view_init() = init;
+      Kokkos::Experimental::Sum<Scalar> reducer_view_init(sum_view_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view_init);
+      Scalar sum_view_init_scalar = sum_view_init();
+      ASSERT_EQ(sum_view_init_scalar,reference_sum);
+      Scalar sum_view_init_view = reducer_view_init.result_view()();
+      ASSERT_EQ(sum_view_init_view,reference_sum);
+    }
+  }
+
+  static void test_prod(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_prod = 1;
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%4+1);
+      reference_prod *= h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    ProdFunctor f;
+    f.values = values;
+    Scalar init = 1;
+
+    if(std::is_arithmetic<Scalar>::value)
+    {
+      Scalar prod_scalar = init;
+      Kokkos::Experimental::Prod<Scalar> reducer_scalar(prod_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(prod_scalar,reference_prod);
+      Scalar prod_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(prod_scalar_view,reference_prod);
+    }
+    {
+      Scalar prod_scalar_init = init;
+      Kokkos::Experimental::Prod<Scalar> reducer_scalar_init(prod_scalar_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar_init);
+      ASSERT_EQ(prod_scalar_init,reference_prod);
+      Scalar prod_scalar_init_view = reducer_scalar_init.result_view()();
+      ASSERT_EQ(prod_scalar_init_view,reference_prod);
+    }
+
+    if(std::is_arithmetic<Scalar>::value)
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> prod_view("View");
+      prod_view() = init;
+      Kokkos::Experimental::Prod<Scalar> reducer_view(prod_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar prod_view_scalar = prod_view();
+      ASSERT_EQ(prod_view_scalar,reference_prod);
+      Scalar prod_view_view = reducer_view.result_view()();
+      ASSERT_EQ(prod_view_view,reference_prod);
+    }
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> prod_view_init("View");
+      prod_view_init() = init;
+      Kokkos::Experimental::Prod<Scalar> reducer_view_init(prod_view_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view_init);
+      Scalar prod_view_init_scalar = prod_view_init();
+      ASSERT_EQ(prod_view_init_scalar,reference_prod);
+      Scalar prod_view_init_view = reducer_view_init.result_view()();
+      ASSERT_EQ(prod_view_init_view,reference_prod);
+    }
+  }
+
+  static void test_min(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_min = std::numeric_limits<Scalar>::max();
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%100000);
+      if(h_values(i)<reference_min)
+        reference_min = h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    MinFunctor f;
+    f.values = values;
+    Scalar init = std::numeric_limits<Scalar>::max();
+
+    {
+      Scalar min_scalar = init;
+      Kokkos::Experimental::Min<Scalar> reducer_scalar(min_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(min_scalar,reference_min);
+      Scalar min_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(min_scalar_view,reference_min);
+    }
+    {
+      Scalar min_scalar_init = init;
+      Kokkos::Experimental::Min<Scalar> reducer_scalar_init(min_scalar_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar_init);
+      ASSERT_EQ(min_scalar_init,reference_min);
+      Scalar min_scalar_init_view = reducer_scalar_init.result_view()();
+      ASSERT_EQ(min_scalar_init_view,reference_min);
+    }
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> min_view("View");
+      min_view() = init;
+      Kokkos::Experimental::Min<Scalar> reducer_view(min_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar min_view_scalar = min_view();
+      ASSERT_EQ(min_view_scalar,reference_min);
+      Scalar min_view_view = reducer_view.result_view()();
+      ASSERT_EQ(min_view_view,reference_min);
+    }
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> min_view_init("View");
+      min_view_init() = init;
+      Kokkos::Experimental::Min<Scalar> reducer_view_init(min_view_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view_init);
+      Scalar min_view_init_scalar = min_view_init();
+      ASSERT_EQ(min_view_init_scalar,reference_min);
+      Scalar min_view_init_view = reducer_view_init.result_view()();
+      ASSERT_EQ(min_view_init_view,reference_min);
+    }
+  }
+
+  static void test_max(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_max = std::numeric_limits<Scalar>::min();
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%100000+1);
+      if(h_values(i)>reference_max)
+        reference_max = h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    MaxFunctor f;
+    f.values = values;
+    Scalar init = std::numeric_limits<Scalar>::min();
+
+    {
+      Scalar max_scalar = init;
+      Kokkos::Experimental::Max<Scalar> reducer_scalar(max_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(max_scalar,reference_max);
+      Scalar max_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(max_scalar_view,reference_max);
+    }
+    {
+      Scalar max_scalar_init = init;
+      Kokkos::Experimental::Max<Scalar> reducer_scalar_init(max_scalar_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar_init);
+      ASSERT_EQ(max_scalar_init,reference_max);
+      Scalar max_scalar_init_view = reducer_scalar_init.result_view()();
+      ASSERT_EQ(max_scalar_init_view,reference_max);
+    }
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> max_view("View");
+      max_view() = init;
+      Kokkos::Experimental::Max<Scalar> reducer_view(max_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar max_view_scalar = max_view();
+      ASSERT_EQ(max_view_scalar,reference_max);
+      Scalar max_view_view = reducer_view.result_view()();
+      ASSERT_EQ(max_view_view,reference_max);
+    }
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> max_view_init("View");
+      max_view_init() = init;
+      Kokkos::Experimental::Max<Scalar> reducer_view_init(max_view_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view_init);
+      Scalar max_view_init_scalar = max_view_init();
+      ASSERT_EQ(max_view_init_scalar,reference_max);
+      Scalar max_view_init_view = reducer_view_init.result_view()();
+      ASSERT_EQ(max_view_init_view,reference_max);
+    }
+  }
+
+  static void test_minloc(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_min = std::numeric_limits<Scalar>::max();
+    int reference_loc = -1;
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%100000);
+      if(h_values(i)<reference_min) {
+        reference_min = h_values(i);
+        reference_loc = i;
+      }
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    MinLocFunctor f;
+    typedef typename Kokkos::Experimental::MinLoc<Scalar,int>::value_type value_type;
+    f.values = values;
+    Scalar init = std::numeric_limits<Scalar>::max();
+
+
+    {
+      value_type min_scalar;
+      Kokkos::Experimental::MinLoc<Scalar,int> reducer_scalar(min_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(min_scalar.val,reference_min);
+      ASSERT_EQ(min_scalar.loc,reference_loc);
+      value_type min_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(min_scalar_view.val,reference_min);
+      ASSERT_EQ(min_scalar_view.loc,reference_loc);
+    }
+    {
+      value_type min_scalar_init;
+      Kokkos::Experimental::MinLoc<Scalar,int> reducer_scalar_init(min_scalar_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar_init);
+      ASSERT_EQ(min_scalar_init.val,reference_min);
+      ASSERT_EQ(min_scalar_init.loc,reference_loc);
+      value_type min_scalar_init_view = reducer_scalar_init.result_view()();
+      ASSERT_EQ(min_scalar_init_view.val,reference_min);
+      ASSERT_EQ(min_scalar_init_view.loc,reference_loc);
+    }
+    {
+      Kokkos::View<value_type,Kokkos::HostSpace> min_view("View");
+      Kokkos::Experimental::MinLoc<Scalar,int> reducer_view(min_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      value_type min_view_scalar = min_view();
+      ASSERT_EQ(min_view_scalar.val,reference_min);
+      ASSERT_EQ(min_view_scalar.loc,reference_loc);
+      value_type min_view_view = reducer_view.result_view()();
+      ASSERT_EQ(min_view_view.val,reference_min);
+      ASSERT_EQ(min_view_view.loc,reference_loc);
+    }
+    {
+      Kokkos::View<value_type,Kokkos::HostSpace> min_view_init("View");
+      Kokkos::Experimental::MinLoc<Scalar,int> reducer_view_init(min_view_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view_init);
+      value_type min_view_init_scalar = min_view_init();
+      ASSERT_EQ(min_view_init_scalar.val,reference_min);
+      ASSERT_EQ(min_view_init_scalar.loc,reference_loc);
+      value_type min_view_init_view = reducer_view_init.result_view()();
+      ASSERT_EQ(min_view_init_view.val,reference_min);
+      ASSERT_EQ(min_view_init_view.loc,reference_loc);
+    }
+  }
+
+  static void test_maxloc(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_max = std::numeric_limits<Scalar>::min();
+    int reference_loc = -1;
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%100000);
+      if(h_values(i)>reference_max) {
+        reference_max = h_values(i);
+        reference_loc = i;
+      }
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    MaxLocFunctor f;
+    typedef typename Kokkos::Experimental::MaxLoc<Scalar,int>::value_type value_type;
+    f.values = values;
+    Scalar init = std::numeric_limits<Scalar>::min();
+
+
+    {
+      value_type max_scalar;
+      Kokkos::Experimental::MaxLoc<Scalar,int> reducer_scalar(max_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(max_scalar.val,reference_max);
+      ASSERT_EQ(max_scalar.loc,reference_loc);
+      value_type max_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(max_scalar_view.val,reference_max);
+      ASSERT_EQ(max_scalar_view.loc,reference_loc);
+    }
+    {
+      value_type max_scalar_init;
+      Kokkos::Experimental::MaxLoc<Scalar,int> reducer_scalar_init(max_scalar_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar_init);
+      ASSERT_EQ(max_scalar_init.val,reference_max);
+      ASSERT_EQ(max_scalar_init.loc,reference_loc);
+      value_type max_scalar_init_view = reducer_scalar_init.result_view()();
+      ASSERT_EQ(max_scalar_init_view.val,reference_max);
+      ASSERT_EQ(max_scalar_init_view.loc,reference_loc);
+    }
+    {
+      Kokkos::View<value_type,Kokkos::HostSpace> max_view("View");
+      Kokkos::Experimental::MaxLoc<Scalar,int> reducer_view(max_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      value_type max_view_scalar = max_view();
+      ASSERT_EQ(max_view_scalar.val,reference_max);
+      ASSERT_EQ(max_view_scalar.loc,reference_loc);
+      value_type max_view_view = reducer_view.result_view()();
+      ASSERT_EQ(max_view_view.val,reference_max);
+      ASSERT_EQ(max_view_view.loc,reference_loc);
+    }
+    {
+      Kokkos::View<value_type,Kokkos::HostSpace> max_view_init("View");
+      Kokkos::Experimental::MaxLoc<Scalar,int> reducer_view_init(max_view_init,init);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view_init);
+      value_type max_view_init_scalar = max_view_init();
+      ASSERT_EQ(max_view_init_scalar.val,reference_max);
+      ASSERT_EQ(max_view_init_scalar.loc,reference_loc);
+      value_type max_view_init_view = reducer_view_init.result_view()();
+      ASSERT_EQ(max_view_init_view.val,reference_max);
+      ASSERT_EQ(max_view_init_view.loc,reference_loc);
+    }
+  }
+
+  static void test_minmaxloc(int N) {
+     Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+     auto h_values = Kokkos::create_mirror_view(values);
+     Scalar reference_max = std::numeric_limits<Scalar>::min();
+     Scalar reference_min = std::numeric_limits<Scalar>::max();
+     int reference_minloc = -1;
+     int reference_maxloc = -1;
+     for(int i=0; i<N; i++) {
+       h_values(i) = (Scalar)(rand()%100000);
+       if(h_values(i)>reference_max) {
+         reference_max = h_values(i);
+         reference_maxloc = i;
+       }
+       if(h_values(i)<reference_min) {
+         reference_min = h_values(i);
+         reference_minloc = i;
+       }
+     }
+     Kokkos::deep_copy(values,h_values);
+
+     MinMaxLocFunctor f;
+     typedef typename Kokkos::Experimental::MinMaxLoc<Scalar,int>::value_type value_type;
+     f.values = values;
+     Scalar init_min = std::numeric_limits<Scalar>::max();
+     Scalar init_max = std::numeric_limits<Scalar>::min();
+
+
+     {
+       value_type minmax_scalar;
+       Kokkos::Experimental::MinMaxLoc<Scalar,int> reducer_scalar(minmax_scalar);
+       Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+       ASSERT_EQ(minmax_scalar.min_val,reference_min);
+       ASSERT_EQ(minmax_scalar.min_loc,reference_minloc);
+       ASSERT_EQ(minmax_scalar.max_val,reference_max);
+       ASSERT_EQ(minmax_scalar.max_loc,reference_maxloc);
+       value_type minmax_scalar_view = reducer_scalar.result_view()();
+       ASSERT_EQ(minmax_scalar_view.min_val,reference_min);
+       ASSERT_EQ(minmax_scalar_view.min_loc,reference_minloc);
+       ASSERT_EQ(minmax_scalar_view.max_val,reference_max);
+       ASSERT_EQ(minmax_scalar_view.max_loc,reference_maxloc);
+     }
+     {
+       value_type minmax_scalar_init;
+       Kokkos::Experimental::MinMaxLoc<Scalar,int> reducer_scalar_init(minmax_scalar_init,init_min,init_max);
+       Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar_init);
+       ASSERT_EQ(minmax_scalar_init.min_val,reference_min);
+       ASSERT_EQ(minmax_scalar_init.min_loc,reference_minloc);
+       ASSERT_EQ(minmax_scalar_init.max_val,reference_max);
+       ASSERT_EQ(minmax_scalar_init.max_loc,reference_maxloc);
+       value_type minmax_scalar_init_view = reducer_scalar_init.result_view()();
+       ASSERT_EQ(minmax_scalar_init_view.min_val,reference_min);
+       ASSERT_EQ(minmax_scalar_init_view.min_loc,reference_minloc);
+       ASSERT_EQ(minmax_scalar_init_view.max_val,reference_max);
+       ASSERT_EQ(minmax_scalar_init_view.max_loc,reference_maxloc);
+     }
+     {
+       Kokkos::View<value_type,Kokkos::HostSpace> minmax_view("View");
+       Kokkos::Experimental::MinMaxLoc<Scalar,int> reducer_view(minmax_view);
+       Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+       value_type minmax_view_scalar = minmax_view();
+       ASSERT_EQ(minmax_view_scalar.min_val,reference_min);
+       ASSERT_EQ(minmax_view_scalar.min_loc,reference_minloc);
+       ASSERT_EQ(minmax_view_scalar.max_val,reference_max);
+       ASSERT_EQ(minmax_view_scalar.max_loc,reference_maxloc);
+       value_type minmax_view_view = reducer_view.result_view()();
+       ASSERT_EQ(minmax_view_view.min_val,reference_min);
+       ASSERT_EQ(minmax_view_view.min_loc,reference_minloc);
+       ASSERT_EQ(minmax_view_view.max_val,reference_max);
+       ASSERT_EQ(minmax_view_view.max_loc,reference_maxloc);
+     }
+     {
+       Kokkos::View<value_type,Kokkos::HostSpace> minmax_view_init("View");
+       Kokkos::Experimental::MinMaxLoc<Scalar,int> reducer_view_init(minmax_view_init,init_min,init_max);
+       Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view_init);
+       value_type minmax_view_init_scalar = minmax_view_init();
+       ASSERT_EQ(minmax_view_init_scalar.min_val,reference_min);
+       ASSERT_EQ(minmax_view_init_scalar.min_loc,reference_minloc);
+       ASSERT_EQ(minmax_view_init_scalar.max_val,reference_max);
+       ASSERT_EQ(minmax_view_init_scalar.max_loc,reference_maxloc);
+       value_type minmax_view_init_view = reducer_view_init.result_view()();
+       ASSERT_EQ(minmax_view_init_view.min_val,reference_min);
+       ASSERT_EQ(minmax_view_init_view.min_loc,reference_minloc);
+       ASSERT_EQ(minmax_view_init_view.max_val,reference_max);
+       ASSERT_EQ(minmax_view_init_view.max_loc,reference_maxloc);
+     }
+   }
+
+  static void test_BAnd(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_band = Scalar() | (~Scalar());
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%100000+1);
+      reference_band = reference_band & h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    BAndFunctor f;
+    f.values = values;
+    Scalar init = Scalar() | (~Scalar());
+
+    {
+      Scalar band_scalar = init;
+      Kokkos::Experimental::BAnd<Scalar> reducer_scalar(band_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(band_scalar,reference_band);
+      Scalar band_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(band_scalar_view,reference_band);
+    }
+
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> band_view("View");
+      band_view() = init;
+      Kokkos::Experimental::BAnd<Scalar> reducer_view(band_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar band_view_scalar = band_view();
+      ASSERT_EQ(band_view_scalar,reference_band);
+      Scalar band_view_view = reducer_view.result_view()();
+      ASSERT_EQ(band_view_view,reference_band);
+    }
+  }
+
+  static void test_BOr(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_bor = Scalar() & (~Scalar());
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)((rand()%100000+1)*2);
+      reference_bor = reference_bor | h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    BOrFunctor f;
+    f.values = values;
+    Scalar init = Scalar() & (~Scalar());
+
+    {
+      Scalar bor_scalar = init;
+      Kokkos::Experimental::BOr<Scalar> reducer_scalar(bor_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(bor_scalar,reference_bor);
+      Scalar bor_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(bor_scalar_view,reference_bor);
+    }
+
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> bor_view("View");
+      bor_view() = init;
+      Kokkos::Experimental::BOr<Scalar> reducer_view(bor_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar bor_view_scalar = bor_view();
+      ASSERT_EQ(bor_view_scalar,reference_bor);
+      Scalar bor_view_view = reducer_view.result_view()();
+      ASSERT_EQ(bor_view_view,reference_bor);
+    }
+  }
+
+  static void test_BXor(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_bxor = Scalar() & (~Scalar());
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)((rand()%100000+1)*2);
+      reference_bxor = reference_bxor ^ h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    BXorFunctor f;
+    f.values = values;
+    Scalar init = Scalar() & (~Scalar());
+
+    {
+      Scalar bxor_scalar = init;
+      Kokkos::Experimental::BXor<Scalar> reducer_scalar(bxor_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(bxor_scalar,reference_bxor);
+      Scalar bxor_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(bxor_scalar_view,reference_bxor);
+    }
+
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> bxor_view("View");
+      bxor_view() = init;
+      Kokkos::Experimental::BXor<Scalar> reducer_view(bxor_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar bxor_view_scalar = bxor_view();
+      ASSERT_EQ(bxor_view_scalar,reference_bxor);
+      Scalar bxor_view_view = reducer_view.result_view()();
+      ASSERT_EQ(bxor_view_view,reference_bxor);
+    }
+  }
+
+  static void test_LAnd(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_land = 1;
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%2);
+      reference_land = reference_land && h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    LAndFunctor f;
+    f.values = values;
+    Scalar init = 1;
+
+    {
+      Scalar land_scalar = init;
+      Kokkos::Experimental::LAnd<Scalar> reducer_scalar(land_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(land_scalar,reference_land);
+      Scalar land_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(land_scalar_view,reference_land);
+    }
+
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> land_view("View");
+      land_view() = init;
+      Kokkos::Experimental::LAnd<Scalar> reducer_view(land_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar land_view_scalar = land_view();
+      ASSERT_EQ(land_view_scalar,reference_land);
+      Scalar land_view_view = reducer_view.result_view()();
+      ASSERT_EQ(land_view_view,reference_land);
+    }
+  }
+
+  static void test_LOr(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_lor = 0;
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%2);
+      reference_lor = reference_lor || h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    LOrFunctor f;
+    f.values = values;
+    Scalar init = 0;
+
+    {
+      Scalar lor_scalar = init;
+      Kokkos::Experimental::LOr<Scalar> reducer_scalar(lor_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(lor_scalar,reference_lor);
+      Scalar lor_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(lor_scalar_view,reference_lor);
+    }
+
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> lor_view("View");
+      lor_view() = init;
+      Kokkos::Experimental::LOr<Scalar> reducer_view(lor_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar lor_view_scalar = lor_view();
+      ASSERT_EQ(lor_view_scalar,reference_lor);
+      Scalar lor_view_view = reducer_view.result_view()();
+      ASSERT_EQ(lor_view_view,reference_lor);
+    }
+  }
+
+  static void test_LXor(int N) {
+    Kokkos::View<Scalar*,ExecSpace> values("Values",N);
+    auto h_values = Kokkos::create_mirror_view(values);
+    Scalar reference_lxor = 0;
+    for(int i=0; i<N; i++) {
+      h_values(i) = (Scalar)(rand()%2);
+      reference_lxor = reference_lxor ? (!h_values(i)) : h_values(i);
+    }
+    Kokkos::deep_copy(values,h_values);
+
+    LXorFunctor f;
+    f.values = values;
+    Scalar init = 0;
+
+    {
+      Scalar lxor_scalar = init;
+      Kokkos::Experimental::LXor<Scalar> reducer_scalar(lxor_scalar);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_scalar);
+      ASSERT_EQ(lxor_scalar,reference_lxor);
+      Scalar lxor_scalar_view = reducer_scalar.result_view()();
+      ASSERT_EQ(lxor_scalar_view,reference_lxor);
+    }
+
+    {
+      Kokkos::View<Scalar,Kokkos::HostSpace> lxor_view("View");
+      lxor_view() = init;
+      Kokkos::Experimental::LXor<Scalar> reducer_view(lxor_view);
+      Kokkos::parallel_reduce(Kokkos::RangePolicy<ExecSpace>(0,N),f,reducer_view);
+      Scalar lxor_view_scalar = lxor_view();
+      ASSERT_EQ(lxor_view_scalar,reference_lxor);
+      Scalar lxor_view_view = reducer_view.result_view()();
+      ASSERT_EQ(lxor_view_view,reference_lxor);
+    }
+  }
+
+  static void execute_float() {
+    test_sum(10001);
+    test_prod(35);
+    test_min(10003);
+    test_minloc(10003);
+    test_max(10007);
+    test_maxloc(10007);
+    test_minmaxloc(10007);
+  }
+
+  static void execute_integer() {
+    test_sum(10001);
+    test_prod(35);
+    test_min(10003);
+    test_minloc(10003);
+    test_max(10007);
+    test_maxloc(10007);
+    test_minmaxloc(10007);
+    test_BAnd(35);
+    test_BOr(35);
+    test_BXor(35);
+    test_LAnd(35);
+    test_LOr(35);
+    test_LXor(35);
+  }
+
+  static void execute_basic() {
+    test_sum(10001);
+    test_prod(35);
+  }
+};
+}
+
+/*--------------------------------------------------------------------------*/
+
diff --git a/lib/kokkos/core/unit_test/TestScan.hpp b/lib/kokkos/core/unit_test/TestScan.hpp
new file mode 100644
index 0000000000..3eeea57043
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestScan.hpp
@@ -0,0 +1,103 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/*--------------------------------------------------------------------------*/
+
+#include <stdio.h>
+
+namespace Test {
+
+template< class Device , class WorkSpec = size_t >
+struct TestScan {
+
+  typedef  Device    execution_space ;
+  typedef  long int  value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int iwork , value_type & update , const bool final_pass ) const
+  {
+    const value_type n = iwork + 1 ;
+    const value_type imbalance = ( (1000 <= n) && (0 == n % 1000) ) ? 1000 : 0 ;
+
+    // Insert an artificial load imbalance
+
+    for ( value_type i = 0 ; i < imbalance ; ++i ) { ++update ; }
+
+    update += n - imbalance ;
+
+    if ( final_pass ) {
+      const value_type answer = n & 1 ? ( n * ( ( n + 1 ) / 2 ) ) : ( ( n / 2 ) * ( n + 1 ) );
+
+      if ( answer != update ) {
+        printf("TestScan(%d,%ld) != %ld\n",iwork,update,answer);
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & update ) const { update = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile       value_type & update ,
+             volatile const value_type & input ) const
+  { update += input ; }
+
+  TestScan( const WorkSpec & N )
+    { parallel_scan( N , *this ); }
+
+  TestScan( const WorkSpec & Start , const WorkSpec & N )
+    {
+      typedef Kokkos::RangePolicy<execution_space> exec_policy ;
+      parallel_scan( exec_policy( Start , N ) , *this );
+    }
+
+  static void test_range( const WorkSpec & begin , const WorkSpec & end )
+    {
+      for ( WorkSpec i = begin ; i < end ; ++i ) {
+        (void) TestScan( i );
+      }
+    }
+};
+
+}
+
diff --git a/lib/kokkos/core/unit_test/TestSerial.cpp b/lib/kokkos/core/unit_test/TestSerial.cpp
new file mode 100644
index 0000000000..d85614e66e
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestSerial.cpp
@@ -0,0 +1,571 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+#include <gtest/gtest.h>
+
+#include <Kokkos_Macros.hpp>
+#ifdef KOKKOS_LAMBDA
+#undef KOKKOS_LAMBDA
+#endif
+#define KOKKOS_LAMBDA [=]
+
+#include <Kokkos_Core.hpp>
+
+#include <impl/Kokkos_ViewTileLeft.hpp>
+#include <TestTile.hpp>
+
+#include <impl/Kokkos_Serial_TaskPolicy.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestViewImpl.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewOfClass.hpp>
+#include <TestViewSubview.hpp>
+#include <TestAtomic.hpp>
+#include <TestAtomicOperations.hpp>
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestTaskPolicy.hpp>
+#include <TestMemoryPool.hpp>
+
+
+#include <TestCXX11.hpp>
+#include <TestCXX11Deduction.hpp>
+#include <TestTeamVector.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+
+#include <TestPolicyConstruction.hpp>
+
+#include <TestMDRange.hpp>
+
+namespace Test {
+
+class serial : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+    {
+      Kokkos::HostSpace::execution_space::initialize();
+    }
+  static void TearDownTestCase()
+    {
+      Kokkos::HostSpace::execution_space::finalize();
+    }
+};
+
+TEST_F( serial , md_range ) {
+  TestMDRange_2D< Kokkos::Serial >::test_for2(100,100);
+
+  TestMDRange_3D< Kokkos::Serial >::test_for3(100,100,100);
+}
+
+TEST_F( serial , impl_shared_alloc ) {
+  test_shared_alloc< Kokkos::HostSpace , Kokkos::Serial >();
+}
+
+TEST_F( serial, policy_construction) {
+  TestRangePolicyConstruction< Kokkos::Serial >();
+  TestTeamPolicyConstruction< Kokkos::Serial >();
+}
+
+TEST_F( serial , impl_view_mapping ) {
+  test_view_mapping< Kokkos::Serial >();
+  test_view_mapping_subview< Kokkos::Serial >();
+  test_view_mapping_operator< Kokkos::Serial >();
+  TestViewMappingAtomic< Kokkos::Serial >::run();
+}
+
+TEST_F( serial, view_impl) {
+  test_view_impl< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_api) {
+  TestViewAPI< double , Kokkos::Serial >();
+}
+
+TEST_F( serial , view_nested_view )
+{
+  ::Test::view_nested_view< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_auto_1d_left ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutLeft,Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_auto_1d_right ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutRight,Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_auto_1d_stride ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutStride,Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_assign_strided ) {
+  TestViewSubview::test_1d_strided_assignment< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_left_0 ) {
+  TestViewSubview::test_left_0< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_left_1 ) {
+  TestViewSubview::test_left_1< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_left_2 ) {
+  TestViewSubview::test_left_2< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_left_3 ) {
+  TestViewSubview::test_left_3< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_right_0 ) {
+  TestViewSubview::test_right_0< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_right_1 ) {
+  TestViewSubview::test_right_1< Kokkos::Serial >();
+}
+
+TEST_F( serial, view_subview_right_3 ) {
+  TestViewSubview::test_right_3< Kokkos::Serial >();
+}
+
+TEST_F( serial , range_tag )
+{
+  TestRange< Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestRange< Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestRange< Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >::test_scan(1000);
+  TestRange< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(1001);
+  TestRange< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(1001);
+  TestRange< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >::test_scan(1001);
+  TestRange< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >::test_dynamic_policy(1000);
+}
+
+TEST_F( serial , team_tag )
+{
+  TestTeamPolicy< Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestTeamPolicy< Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestTeamPolicy< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(1000);
+  TestTeamPolicy< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(1000);
+}
+
+TEST_F( serial, long_reduce) {
+  TestReduce< long ,   Kokkos::Serial >( 1000000 );
+}
+
+TEST_F( serial, double_reduce) {
+  TestReduce< double ,   Kokkos::Serial >( 1000000 );
+}
+
+TEST_F( serial , reducers )
+{
+  TestReducers<int, Kokkos::Serial>::execute_integer();
+  TestReducers<size_t, Kokkos::Serial>::execute_integer();
+  TestReducers<double, Kokkos::Serial>::execute_float();
+  TestReducers<Kokkos::complex<double>, Kokkos::Serial>::execute_basic();
+}
+
+TEST_F( serial, long_reduce_dynamic ) {
+  TestReduceDynamic< long ,   Kokkos::Serial >( 1000000 );
+}
+
+TEST_F( serial, double_reduce_dynamic ) {
+  TestReduceDynamic< double ,   Kokkos::Serial >( 1000000 );
+}
+
+TEST_F( serial, long_reduce_dynamic_view ) {
+  TestReduceDynamicView< long ,   Kokkos::Serial >( 1000000 );
+}
+
+TEST_F( serial , scan )
+{
+  TestScan< Kokkos::Serial >::test_range( 1 , 1000 );
+  TestScan< Kokkos::Serial >( 10 );
+  TestScan< Kokkos::Serial >( 10000 );
+}
+
+TEST_F( serial , team_long_reduce) {
+  TestReduceTeam< long ,   Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >( 3 );
+  TestReduceTeam< long ,   Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >( 3 );
+  TestReduceTeam< long ,   Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >( 100000 );
+  TestReduceTeam< long ,   Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >( 100000 );
+}
+
+TEST_F( serial , team_double_reduce) {
+  TestReduceTeam< double ,   Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >( 3 );
+  TestReduceTeam< double ,   Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >( 3 );
+  TestReduceTeam< double ,   Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >( 100000 );
+  TestReduceTeam< double ,   Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >( 100000 );
+}
+
+TEST_F( serial , team_shared_request) {
+  TestSharedTeam< Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >();
+  TestSharedTeam< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+
+#if defined(KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+TEST_F( serial , team_lambda_shared_request) {
+  TestLambdaSharedTeam< Kokkos::HostSpace, Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >();
+  TestLambdaSharedTeam< Kokkos::HostSpace, Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+#endif
+
+TEST_F( serial, shmem_size) {
+  TestShmemSize< Kokkos::Serial >();
+}
+
+TEST_F( serial  , team_scan )
+{
+  TestScanTeam< Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >( 10 );
+  TestScanTeam< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >( 10 );
+  TestScanTeam< Kokkos::Serial , Kokkos::Schedule<Kokkos::Static> >( 10000 );
+  TestScanTeam< Kokkos::Serial , Kokkos::Schedule<Kokkos::Dynamic> >( 10000 );
+}
+
+
+TEST_F( serial , view_remap )
+{
+  enum { N0 = 3 , N1 = 2 , N2 = 8 , N3 = 9 };
+
+  typedef Kokkos::View< double*[N1][N2][N3] ,
+                             Kokkos::LayoutRight ,
+                             Kokkos::Serial > output_type ;
+
+  typedef Kokkos::View< int**[N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::Serial > input_type ;
+
+  typedef Kokkos::View< int*[N0][N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::Serial > diff_type ;
+
+  output_type output( "output" , N0 );
+  input_type  input ( "input" , N0 , N1 );
+  diff_type   diff  ( "diff" , N0 );
+
+  int value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    input(i0,i1,i2,i3) = ++value ;
+  }}}}
+
+  // Kokkos::deep_copy( diff , input ); // throw with incompatible shape
+  Kokkos::deep_copy( output , input );
+
+  value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    ++value ;
+    ASSERT_EQ( value , ((int) output(i0,i1,i2,i3) ) );
+  }}}}
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( serial , view_aggregate )
+{
+  TestViewAggregate< Kokkos::Serial >();
+  TestViewAggregateReduction< Kokkos::Serial >();
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( serial , atomics )
+{
+  const int loop_count = 1e6 ;
+
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Serial>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Serial>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Serial>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Serial>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Serial>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Serial>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Serial>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Serial>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Serial>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Serial>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Serial>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Serial>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Serial>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Serial>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Serial>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Serial>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Serial>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Serial>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Serial>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Serial>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Serial>(100,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Serial>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Serial>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Serial>(100,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::Serial>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::Serial>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<4> ,Kokkos::Serial>(100,3) ) );
+}
+
+TEST_F( serial , atomic_operations )
+{
+  const int start = 1; //Avoid zero for division
+  const int end = 11;
+  for (int i = start; i < end; ++i)
+  {
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Serial>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Serial>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Serial>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Serial>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Serial>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Serial>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Serial>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Serial>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Serial>(start, end-i, 4 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Serial>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Serial>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Serial>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Serial>(start, end-i, 4 ) ) );
+  }
+
+}
+//----------------------------------------------------------------------------
+
+TEST_F( serial, tile_layout )
+{
+  TestTile::test< Kokkos::Serial , 1 , 1 >( 1 , 1 );
+  TestTile::test< Kokkos::Serial , 1 , 1 >( 2 , 3 );
+  TestTile::test< Kokkos::Serial , 1 , 1 >( 9 , 10 );
+
+  TestTile::test< Kokkos::Serial , 2 , 2 >( 1 , 1 );
+  TestTile::test< Kokkos::Serial , 2 , 2 >( 2 , 3 );
+  TestTile::test< Kokkos::Serial , 2 , 2 >( 4 , 4 );
+  TestTile::test< Kokkos::Serial , 2 , 2 >( 9 , 9 );
+
+  TestTile::test< Kokkos::Serial , 2 , 4 >( 9 , 9 );
+  TestTile::test< Kokkos::Serial , 4 , 2 >( 9 , 9 );
+
+  TestTile::test< Kokkos::Serial , 4 , 4 >( 1 , 1 );
+  TestTile::test< Kokkos::Serial , 4 , 4 >( 4 , 4 );
+  TestTile::test< Kokkos::Serial , 4 , 4 >( 9 , 9 );
+  TestTile::test< Kokkos::Serial , 4 , 4 >( 9 , 11 );
+
+  TestTile::test< Kokkos::Serial , 8 , 8 >( 1 , 1 );
+  TestTile::test< Kokkos::Serial , 8 , 8 >( 4 , 4 );
+  TestTile::test< Kokkos::Serial , 8 , 8 >( 9 , 9 );
+  TestTile::test< Kokkos::Serial , 8 , 8 >( 9 , 11 );
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( serial , compiler_macros )
+{
+  ASSERT_TRUE( ( TestCompilerMacros::Test< Kokkos::Serial >() ) );
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( serial , memory_space )
+{
+  TestMemorySpace< Kokkos::Serial >();
+}
+
+TEST_F( serial , memory_pool )
+{
+  bool val = TestMemoryPool::test_mempool< Kokkos::Serial >( 128, 128000000 );
+  ASSERT_TRUE( val );
+
+  TestMemoryPool::test_mempool2< Kokkos::Serial >( 64, 4, 1000000, 2000000 );
+
+  TestMemoryPool::test_memory_exhaustion< Kokkos::Serial >();
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+TEST_F( serial , task_fib )
+{
+  for ( int i = 0 ; i < 25 ; ++i ) {
+    TestTaskPolicy::TestFib< Kokkos::Serial >::run(i);
+  }
+}
+
+TEST_F( serial , task_depend )
+{
+  for ( int i = 0 ; i < 25 ; ++i ) {
+    TestTaskPolicy::TestTaskDependence< Kokkos::Serial >::run(i);
+  }
+}
+
+TEST_F( serial , task_team )
+{
+  TestTaskPolicy::TestTaskTeam< Kokkos::Serial >::run(1000);
+  //TestTaskPolicy::TestTaskTeamValue< Kokkos::Serial >::run(1000); //put back after testing
+}
+
+TEST_F( serial , old_task_policy )
+{
+  TestTaskPolicy::test_task_dep< Kokkos::Serial >( 10 );
+  // TestTaskPolicy::test_norm2< Kokkos::Serial >( 1000 );
+  // for ( long i = 0 ; i < 30 ; ++i ) TestTaskPolicy::test_fib< Kokkos::Serial >(i);
+  // for ( long i = 0 ; i < 40 ; ++i ) TestTaskPolicy::test_fib2< Kokkos::Serial >(i);
+  for ( long i = 0 ; i < 20 ; ++i ) TestTaskPolicy::test_fib< Kokkos::Serial >(i);
+  for ( long i = 0 ; i < 25 ; ++i ) TestTaskPolicy::test_fib2< Kokkos::Serial >(i);
+}
+
+TEST_F( serial , old_task_team )
+{
+  TestTaskPolicy::test_task_team< Kokkos::Serial >(1000);
+}
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
+//----------------------------------------------------------------------------
+
+TEST_F( serial , template_meta_functions )
+{
+  TestTemplateMetaFunctions<int, Kokkos::Serial >();
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_SERIAL )
+TEST_F( serial , cxx11 )
+{
+  if ( Kokkos::Impl::is_same< Kokkos::DefaultExecutionSpace , Kokkos::Serial >::value ) {
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::Serial >(1) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::Serial >(2) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::Serial >(3) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::Serial >(4) ) );
+  }
+}
+#endif
+
+TEST_F( serial , reduction_deduction )
+{
+  TestCXX11::test_reduction_deduction< Kokkos::Serial >();
+}
+
+TEST_F( serial , team_vector )
+{
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(0) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(1) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(2) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(3) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(4) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(5) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(6) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(7) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(8) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(9) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Serial >(10) ) );
+}
+
+} // namespace test
+
diff --git a/lib/kokkos/core/unit_test/TestSharedAlloc.hpp b/lib/kokkos/core/unit_test/TestSharedAlloc.hpp
new file mode 100644
index 0000000000..6116688814
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestSharedAlloc.hpp
@@ -0,0 +1,215 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+struct SharedAllocDestroy {
+
+  volatile int * count ;
+
+  SharedAllocDestroy() = default ;
+  SharedAllocDestroy( int * arg ) : count( arg ) {}
+
+  void destroy_shared_allocation()
+    {
+      Kokkos::atomic_fetch_add( count , 1 );
+    }
+
+};
+
+template< class MemorySpace , class ExecutionSpace >
+void test_shared_alloc()
+{
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+
+  typedef const Kokkos::Experimental::Impl::SharedAllocationHeader   Header ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationTracker  Tracker ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationRecord< void , void >                       RecordBase ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationRecord< MemorySpace , void >                RecordMemS ;
+  typedef Kokkos::Experimental::Impl::SharedAllocationRecord< MemorySpace , SharedAllocDestroy >  RecordFull ;
+
+  static_assert( sizeof(Tracker) == sizeof(int*), "SharedAllocationTracker has wrong size!" );
+
+  MemorySpace s ;
+
+  const size_t N = 1200 ;
+  const size_t size = 8 ;
+
+  RecordMemS * rarray[ N ];
+  Header     * harray[ N ];
+
+  RecordMemS ** const r = rarray ;
+  Header     ** const h = harray ;
+
+  Kokkos::RangePolicy< ExecutionSpace > range(0,N);
+  
+  //----------------------------------------
+  {
+  // Since always executed on host space, leave [=]
+    Kokkos::parallel_for( range , [=]( size_t i ){
+      char name[64] ;
+      sprintf(name,"test_%.2d",int(i));
+
+      r[i] = RecordMemS::allocate( s , name , size * ( i + 1 ) );
+      h[i] = Header::get_header( r[i]->data() );
+
+      ASSERT_EQ( r[i]->use_count() , 0 );
+
+      for ( size_t j = 0 ; j < ( i / 10 ) + 1 ; ++j ) RecordBase::increment( r[i] );
+
+      ASSERT_EQ( r[i]->use_count() , ( i / 10 ) + 1 );
+      ASSERT_EQ( r[i] , RecordMemS::get_record( r[i]->data() ) );
+    });
+
+    // Sanity check for the whole set of allocation records to which this record belongs.
+    RecordBase::is_sane( r[0] );
+    // RecordMemS::print_records( std::cout , s , true );
+
+    Kokkos::parallel_for( range , [=]( size_t i ){
+      while ( 0 != ( r[i] = static_cast< RecordMemS *>( RecordBase::decrement( r[i] ) ) ) ) {
+        if ( r[i]->use_count() == 1 ) RecordBase::is_sane( r[i] );
+      }
+    });
+  }
+  //----------------------------------------
+  {
+    int destroy_count = 0 ;
+    SharedAllocDestroy counter( & destroy_count );
+
+    Kokkos::parallel_for( range , [=]( size_t i ){
+      char name[64] ;
+      sprintf(name,"test_%.2d",int(i));
+
+      RecordFull * rec = RecordFull::allocate( s , name , size * ( i + 1 ) );
+
+      rec->m_destroy = counter ;
+
+      r[i] = rec ;
+      h[i] = Header::get_header( r[i]->data() );
+
+      ASSERT_EQ( r[i]->use_count() , 0 );
+
+      for ( size_t j = 0 ; j < ( i / 10 ) + 1 ; ++j ) RecordBase::increment( r[i] );
+
+      ASSERT_EQ( r[i]->use_count() , ( i / 10 ) + 1 );
+      ASSERT_EQ( r[i] , RecordMemS::get_record( r[i]->data() ) );
+    });
+
+    RecordBase::is_sane( r[0] );
+
+    Kokkos::parallel_for( range , [=]( size_t i ){
+      while ( 0 != ( r[i] = static_cast< RecordMemS *>( RecordBase::decrement( r[i] ) ) ) ) {
+        if ( r[i]->use_count() == 1 ) RecordBase::is_sane( r[i] );
+      }
+    });
+
+    ASSERT_EQ( destroy_count , int(N) );
+  }
+
+  //----------------------------------------
+  {
+    int destroy_count = 0 ;
+
+    {
+      RecordFull * rec = RecordFull::allocate( s , "test" , size );
+
+      // ... Construction of the allocated { rec->data() , rec->size() }
+
+      // Copy destruction function object into the allocation record
+      rec->m_destroy = SharedAllocDestroy( & destroy_count );
+
+      ASSERT_EQ( rec->use_count() , 0 );
+
+      // Start tracking, increments the use count from 0 to 1
+      Tracker track ;
+
+      track.assign_allocated_record_to_uninitialized( rec );
+
+      ASSERT_EQ( rec->use_count() , 1 );
+      ASSERT_EQ( track.use_count() , 1 );
+
+      // Verify construction / destruction increment
+      for ( size_t i = 0 ; i < N ; ++i ) {
+        ASSERT_EQ( rec->use_count() , 1 );
+        {
+          Tracker local_tracker ;
+          local_tracker.assign_allocated_record_to_uninitialized( rec );
+          ASSERT_EQ( rec->use_count() , 2 );
+          ASSERT_EQ( local_tracker.use_count() , 2 );
+        }
+        ASSERT_EQ( rec->use_count() , 1 );
+        ASSERT_EQ( track.use_count() , 1 );
+      }
+
+      Kokkos::parallel_for( range , [=]( size_t i ){
+        Tracker local_tracker ;
+        local_tracker.assign_allocated_record_to_uninitialized( rec );
+        ASSERT_GT( rec->use_count() , 1 );
+      });
+
+      ASSERT_EQ( rec->use_count() , 1 );
+      ASSERT_EQ( track.use_count() , 1 );
+
+      // Destruction of 'track' object deallocates the 'rec' and invokes the destroy function object.
+    }
+
+    ASSERT_EQ( destroy_count , 1 );
+  }
+
+#endif /* #if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST ) */
+
+}
+
+
+}
+
diff --git a/lib/kokkos/core/unit_test/TestSynchronic.cpp b/lib/kokkos/core/unit_test/TestSynchronic.cpp
new file mode 100644
index 0000000000..9121dc15a1
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestSynchronic.cpp
@@ -0,0 +1,448 @@
+/*
+
+Copyright (c) 2014, NVIDIA Corporation
+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 HOLDER 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.
+
+*/
+
+//#undef _WIN32_WINNT
+//#define _WIN32_WINNT 0x0602
+
+#if defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(__APPLE__)
+
+// Skip for now
+
+#else
+
+#include <gtest/gtest.h>
+
+#ifdef USEOMP
+#include <omp.h>
+#endif
+
+#include <iostream>
+#include <sstream>
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <map>
+#include <cstring>
+#include <ctime>
+
+//#include <details/config>
+//#undef __SYNCHRONIC_COMPATIBLE
+
+#include <impl/Kokkos_Synchronic.hpp>
+#include <impl/Kokkos_Synchronic_n3998.hpp>
+
+#include "TestSynchronic.hpp"
+
+// Uncomment to allow test to dump output
+//#define VERBOSE_TEST
+
+namespace Test {
+
+unsigned next_table[] =
+    {
+        0, 1, 2, 3,         //0-3
+        4, 4, 6, 6,         //4-7
+        8, 8, 8, 8,         //8-11
+        12, 12, 12, 12,     //12-15
+        16, 16, 16, 16,     //16-19
+        16, 16, 16, 16,     //20-23
+        24, 24, 24, 24,     //24-27
+        24, 24, 24, 24,     //28-31
+        32, 32, 32, 32,     //32-35
+        32, 32, 32, 32,     //36-39
+        40, 40, 40, 40,     //40-43
+        40, 40, 40, 40,     //44-47
+        48, 48, 48, 48,     //48-51
+        48, 48, 48, 48,     //52-55
+        56, 56, 56, 56,     //56-59
+        56, 56, 56, 56,     //60-63
+    };
+
+//change this if you want to allow oversubscription of the system, by default only the range {1-(system size)} is tested
+#define FOR_GAUNTLET(x) for(unsigned x = (std::min)(std::thread::hardware_concurrency()*8,unsigned(sizeof(next_table)/sizeof(unsigned))); x; x = next_table[x-1])
+
+//set this to override the benchmark of barriers to use OMP barriers instead of n3998 std::barrier
+//#define USEOMP
+
+#if defined(__SYNCHRONIC_COMPATIBLE)
+    #define PREFIX "futex-"
+#else
+    #define PREFIX "backoff-"
+#endif
+
+//this test uses a custom Mersenne twister to eliminate implementation variation
+MersenneTwister mt;
+
+int dummya = 1, dummyb =1;
+
+int dummy1 = 1;
+std::atomic<int> dummy2(1);
+std::atomic<int> dummy3(1);
+
+double time_item(int const count = (int)1E8)  {
+
+    clock_t const start = clock();
+
+    for(int i = 0;i < count; ++i)
+        mt.integer();
+
+    clock_t const end = clock();
+    double elapsed_seconds = (end - start) / double(CLOCKS_PER_SEC);
+
+    return elapsed_seconds / count;
+}
+double time_nil(int const count = (int)1E08)  {
+
+    clock_t const start = clock();
+
+    dummy3 = count;
+    for(int i = 0;i < (int)1E6; ++i) {
+        if(dummy1) {
+            // Do some work while holding the lock
+            int workunits = dummy3;//(int) (mtc.poissonInterval((float)num_items_critical) + 0.5f);
+            for (int j = 1; j < workunits; j++)
+                dummy1 &= j;       // Do one work unit
+            dummy2.fetch_add(dummy1,std::memory_order_relaxed);
+        }
+    }
+
+    clock_t const end = clock();
+    double elapsed_seconds = (end - start) / double(CLOCKS_PER_SEC);
+
+    return elapsed_seconds / count;
+}
+
+
+template <class mutex_type>
+void testmutex_inner(mutex_type& m, std::atomic<int>& t,std::atomic<int>& wc,std::atomic<int>& wnc, int const num_iterations,
+                     int const num_items_critical, int const num_items_noncritical, MersenneTwister& mtc, MersenneTwister& mtnc, bool skip) {
+
+    for(int k = 0; k < num_iterations; ++k) {
+
+        if(num_items_noncritical) {
+            // Do some work without holding the lock
+            int workunits = num_items_noncritical;//(int) (mtnc.poissonInterval((float)num_items_noncritical) + 0.5f);
+            for (int i = 1; i < workunits; i++)
+                mtnc.integer();       // Do one work unit
+            wnc.fetch_add(workunits,std::memory_order_relaxed);
+        }
+
+        t.fetch_add(1,std::memory_order_relaxed);
+
+        if(!skip) {
+            std::unique_lock<mutex_type> l(m);
+            if(num_items_critical) {
+                // Do some work while holding the lock
+                int workunits = num_items_critical;//(int) (mtc.poissonInterval((float)num_items_critical) + 0.5f);
+                for (int i = 1; i < workunits; i++)
+                    mtc.integer();       // Do one work unit
+                wc.fetch_add(workunits,std::memory_order_relaxed);
+            }
+        }
+    }
+}
+template <class mutex_type>
+void testmutex_outer(std::map<std::string,std::vector<double>>& results, std::string const& name, double critical_fraction, double critical_duration) {
+
+    std::ostringstream truename;
+    truename << name << " (f=" << critical_fraction << ",d=" << critical_duration << ")";
+
+    std::vector<double>& data = results[truename.str()];
+
+    double const workItemTime = time_item() ,
+                 nilTime = time_nil();
+
+    int const num_items_critical = (critical_duration <= 0 ? 0 : (std::max)( int(critical_duration / workItemTime + 0.5), int(100 * nilTime / workItemTime + 0.5))),
+              num_items_noncritical = (num_items_critical <= 0 ? 0 : int( ( 1 - critical_fraction ) * num_items_critical / critical_fraction + 0.5 ));
+
+    FOR_GAUNTLET(num_threads) {
+
+        //Kokkos::Impl::portable_sleep(std::chrono::microseconds(2000000));
+
+        int const num_iterations = (num_items_critical + num_items_noncritical != 0) ?
+#ifdef __SYNCHRONIC_JUST_YIELD
+                                        int( 1 / ( 8 * workItemTime ) / (num_items_critical + num_items_noncritical) / num_threads + 0.5 ) :
+#else
+                                        int( 1 / ( 8 * workItemTime ) / (num_items_critical + num_items_noncritical) / num_threads + 0.5 ) :
+#endif
+#ifdef WIN32
+                                        int( 1 / workItemTime / (20 * num_threads * num_threads) );
+#else
+                                        int( 1 / workItemTime / (200 * num_threads * num_threads) );
+#endif
+
+#ifdef VERBOSE_TEST
+        std::cerr << "running " << truename.str() << " #" << num_threads << ", " << num_iterations << " * " << num_items_noncritical << "\n" << std::flush;
+#endif
+
+
+        std::atomic<int> t[2], wc[2], wnc[2];
+
+        clock_t start[2], end[2];
+        for(int pass = 0; pass < 2; ++pass) {
+
+            t[pass] = 0;
+            wc[pass] = 0;
+            wnc[pass] = 0;
+
+            srand(num_threads);
+            std::vector<MersenneTwister> randomsnc(num_threads),
+                                         randomsc(num_threads);
+
+            mutex_type m;
+
+            start[pass] = clock();
+#ifdef USEOMP
+            omp_set_num_threads(num_threads);
+            std::atomic<int> _j(0);
+            #pragma omp parallel
+            {
+                int const j = _j.fetch_add(1,std::memory_order_relaxed);
+                testmutex_inner(m, t[pass], wc[pass], wnc[pass], num_iterations, num_items_critical, num_items_noncritical, randomsc[j], randomsnc[j], pass==0);
+                num_threads = omp_get_num_threads();
+            }
+#else
+            std::vector<std::thread*> threads(num_threads);
+            for(unsigned j = 0; j < num_threads; ++j)
+                threads[j] = new std::thread([&,j](){
+                        testmutex_inner(m, t[pass], wc[pass], wnc[pass], num_iterations, num_items_critical, num_items_noncritical, randomsc[j], randomsnc[j], pass==0);
+                    }
+                );
+            for(unsigned j = 0; j < num_threads; ++j) {
+                threads[j]->join();
+                delete threads[j];
+            }
+#endif
+            end[pass] = clock();
+        }
+        if(t[0] != t[1]) throw std::string("mismatched iteration counts");
+        if(wnc[0] != wnc[1]) throw std::string("mismatched work item counts");
+
+        double elapsed_seconds_0 = (end[0] - start[0]) / double(CLOCKS_PER_SEC),
+               elapsed_seconds_1 = (end[1] - start[1]) / double(CLOCKS_PER_SEC);
+        double time = (elapsed_seconds_1 - elapsed_seconds_0 - wc[1]*workItemTime) / num_iterations;
+
+        data.push_back(time);
+#ifdef VERBOSE_TEST
+        std::cerr << truename.str() << " : " << num_threads << "," << elapsed_seconds_1 / num_iterations << " - " << elapsed_seconds_0 / num_iterations << " - " << wc[1]*workItemTime/num_iterations << " = " << time << "                                                 \n";
+#endif
+    }
+}
+
+template <class barrier_type>
+void testbarrier_inner(barrier_type& b, int const num_threads, int const j, std::atomic<int>& t,std::atomic<int>& w,
+                       int const num_iterations_odd, int const num_iterations_even,
+                       int const num_items_noncritical, MersenneTwister& arg_mt, bool skip) {
+
+    for(int k = 0; k < (std::max)(num_iterations_even,num_iterations_odd); ++k) {
+
+        if(k >= (~j & 0x1 ? num_iterations_odd : num_iterations_even )) {
+            if(!skip)
+                b.arrive_and_drop();
+            break;
+        }
+
+        if(num_items_noncritical) {
+            // Do some work without holding the lock
+            int workunits = (int) (arg_mt.poissonInterval((float)num_items_noncritical) + 0.5f);
+            for (int i = 1; i < workunits; i++)
+                arg_mt.integer();       // Do one work unit
+            w.fetch_add(workunits,std::memory_order_relaxed);
+        }
+
+        t.fetch_add(1,std::memory_order_relaxed);
+
+        if(!skip) {
+            int const thiscount = (std::min)(k+1,num_iterations_odd)*((num_threads>>1)+(num_threads&1)) + (std::min)(k+1,num_iterations_even)*(num_threads>>1);
+            if(t.load(std::memory_order_relaxed) > thiscount) {
+                std::cerr << "FAILURE: some threads have run ahead of the barrier (" << t.load(std::memory_order_relaxed) << ">" <<  thiscount << ").\n";
+                EXPECT_TRUE(false);
+            }
+#ifdef USEOMP
+            #pragma omp barrier
+#else
+            b.arrive_and_wait();
+#endif
+            if(t.load(std::memory_order_relaxed) < thiscount) {
+                std::cerr << "FAILURE: some threads have fallen behind the barrier (" << t.load(std::memory_order_relaxed) << "<" << thiscount << ").\n";
+                EXPECT_TRUE(false);
+            }
+        }
+    }
+}
+template <class barrier_type>
+void testbarrier_outer(std::map<std::string,std::vector<double>>& results, std::string const& name, double barrier_frequency, double phase_duration, bool randomIterations = false) {
+
+    std::vector<double>& data = results[name];
+
+    double const workItemTime = time_item();
+    int const num_items_noncritical = int( phase_duration / workItemTime + 0.5 );
+
+    FOR_GAUNTLET(num_threads) {
+
+        int const num_iterations = int( barrier_frequency );
+#ifdef VERBOSE_TEST
+        std::cerr << "running " << name << " #" << num_threads << ", " << num_iterations << " * " << num_items_noncritical << "\r" << std::flush;
+#endif
+
+        srand(num_threads);
+
+        MersenneTwister local_mt;
+        int const num_iterations_odd = randomIterations ? int(local_mt.poissonInterval((float)num_iterations)+0.5f) : num_iterations,
+                  num_iterations_even = randomIterations ? int(local_mt.poissonInterval((float)num_iterations)+0.5f) : num_iterations;
+
+        std::atomic<int> t[2], w[2];
+        std::chrono::time_point<std::chrono::high_resolution_clock> start[2], end[2];
+        for(int pass = 0; pass < 2; ++pass) {
+
+            t[pass] = 0;
+            w[pass] = 0;
+
+            srand(num_threads);
+            std::vector<MersenneTwister> randoms(num_threads);
+
+            barrier_type b(num_threads);
+
+            start[pass] = std::chrono::high_resolution_clock::now();
+#ifdef USEOMP
+            omp_set_num_threads(num_threads);
+            std::atomic<int> _j(0);
+            #pragma omp parallel
+            {
+                int const j = _j.fetch_add(1,std::memory_order_relaxed);
+                testbarrier_inner(b, num_threads, j, t[pass], w[pass], num_iterations_odd, num_iterations_even, num_items_noncritical, randoms[j], pass==0);
+                num_threads = omp_get_num_threads();
+            }
+#else
+            std::vector<std::thread*> threads(num_threads);
+            for(unsigned j = 0; j < num_threads; ++j)
+                threads[j] = new std::thread([&,j](){
+                    testbarrier_inner(b, num_threads, j, t[pass], w[pass], num_iterations_odd, num_iterations_even, num_items_noncritical, randoms[j], pass==0);
+                });
+            for(unsigned j = 0; j < num_threads; ++j) {
+                threads[j]->join();
+                delete threads[j];
+            }
+#endif
+            end[pass] = std::chrono::high_resolution_clock::now();
+        }
+
+        if(t[0] != t[1]) throw std::string("mismatched iteration counts");
+        if(w[0] != w[1]) throw std::string("mismatched work item counts");
+
+        int const phases = (std::max)(num_iterations_odd, num_iterations_even);
+
+        std::chrono::duration<double> elapsed_seconds_0 = end[0]-start[0],
+                                      elapsed_seconds_1 = end[1]-start[1];
+        double const time = (elapsed_seconds_1.count() - elapsed_seconds_0.count()) / phases;
+
+        data.push_back(time);
+#ifdef VERBOSE_TEST
+        std::cerr << name << " : " << num_threads << "," << elapsed_seconds_1.count() / phases << " - " << elapsed_seconds_0.count() / phases << " = " << time << "                                                 \n";
+#endif
+    }
+}
+
+template <class... T>
+struct mutex_tester;
+template <class F>
+struct mutex_tester<F> {
+    static void run(std::map<std::string,std::vector<double>>& results, std::string const name[], double critical_fraction, double critical_duration) {
+        testmutex_outer<F>(results, *name, critical_fraction, critical_duration);
+    }
+};
+template <class F, class... T>
+struct mutex_tester<F,T...> {
+    static void run(std::map<std::string,std::vector<double>>& results, std::string const name[], double critical_fraction, double critical_duration) {
+        mutex_tester<F>::run(results, name, critical_fraction, critical_duration);
+        mutex_tester<T...>::run(results, ++name, critical_fraction, critical_duration);
+    }
+};
+
+TEST( synchronic, main )
+{
+    //warm up
+    time_item();
+
+    //measure up
+#ifdef VERBOSE_TEST
+    std::cerr << "measuring work item speed...\r";
+    std::cerr << "work item speed is " << time_item() << " per item, nil is " << time_nil() << "\n";
+#endif
+    try {
+
+      std::pair<double,double> testpoints[] = { {1, 0}, /*{1E-1, 10E-3}, {5E-1, 2E-6},  {3E-1, 50E-9},*/ };
+        for(auto x : testpoints ) {
+
+            std::map<std::string,std::vector<double>> results;
+
+            //testbarrier_outer<std::barrier>(results, PREFIX"bar 1khz 100us", 1E3, x.second);
+
+            std::string const names[] = {
+                PREFIX"tkt", PREFIX"mcs", PREFIX"ttas", PREFIX"std"
+#ifdef WIN32
+                ,PREFIX"srw"
+#endif
+            };
+
+            //run -->
+
+            mutex_tester<
+                ticket_mutex, mcs_mutex, ttas_mutex, std::mutex
+#ifdef WIN32
+                ,srw_mutex
+#endif
+            >::run(results, names, x.first, x.second);
+
+            //<-- run
+
+#ifdef VERBOSE_TEST
+            std::cout << "threads";
+            for(auto & i : results)
+                std::cout << ",\"" << i.first << '\"';
+            std::cout << std::endl;
+            int j = 0;
+            FOR_GAUNTLET(num_threads) {
+                std::cout << num_threads;
+                for(auto & i : results)
+                    std::cout << ',' << i.second[j];
+                std::cout << std::endl;
+                ++j;
+            }
+#endif
+        }
+    }
+    catch(std::string & e) {
+        std::cerr << "EXCEPTION : " << e << std::endl;
+        EXPECT_TRUE( false );
+    }
+}
+
+} // namespace Test
+
+#endif
diff --git a/lib/kokkos/core/unit_test/TestSynchronic.hpp b/lib/kokkos/core/unit_test/TestSynchronic.hpp
new file mode 100644
index 0000000000..d820129e8b
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestSynchronic.hpp
@@ -0,0 +1,240 @@
+/*
+
+Copyright (c) 2014, NVIDIA Corporation
+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 HOLDER 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 TEST_SYNCHRONIC_HPP
+#define TEST_SYNCHRONIC_HPP
+
+#include <impl/Kokkos_Synchronic.hpp>
+#include <mutex>
+
+namespace Test {
+
+template <bool truly>
+struct dumb_mutex {
+
+    dumb_mutex () : locked(0) {
+    }
+
+    void lock() {
+        while(1) {
+            bool state = false;
+            if (locked.compare_exchange_weak(state,true,std::memory_order_acquire)) {
+                break;
+            }
+            while (locked.load(std::memory_order_relaxed)) {
+              if (!truly) {
+                Kokkos::Impl::portable_yield();
+              }
+            }
+        }
+    }
+
+    void unlock() {
+        locked.store(false,std::memory_order_release);
+    }
+
+private :
+    std::atomic<bool> locked;
+};
+
+#ifdef WIN32
+#include <winsock2.h>
+#include <windows.h>
+#include <synchapi.h>
+struct srw_mutex {
+
+    srw_mutex () {
+        InitializeSRWLock(&_lock);
+    }
+
+    void lock() {
+        AcquireSRWLockExclusive(&_lock);
+    }
+    void unlock() {
+        ReleaseSRWLockExclusive(&_lock);
+    }
+
+private :
+    SRWLOCK _lock;
+};
+#endif
+
+struct ttas_mutex {
+
+    ttas_mutex() : locked(false) {
+    }
+
+	ttas_mutex(const ttas_mutex&) = delete;
+	ttas_mutex& operator=(const ttas_mutex&) = delete;
+
+    void lock() {
+        for(int i = 0;; ++i) {
+            bool state = false;
+            if(locked.compare_exchange_weak(state,true,std::memory_order_relaxed,Kokkos::Impl::notify_none))
+                break;
+            locked.expect_update(true);
+        }
+        std::atomic_thread_fence(std::memory_order_acquire);
+    }
+    void unlock() {
+        locked.store(false,std::memory_order_release);
+    }
+
+private :
+    Kokkos::Impl::synchronic<bool> locked;
+};
+
+struct ticket_mutex {
+
+    ticket_mutex() : active(0), queue(0) {
+    }
+
+	ticket_mutex(const ticket_mutex&) = delete;
+	ticket_mutex& operator=(const ticket_mutex&) = delete;
+
+    void lock() {
+        int const me = queue.fetch_add(1, std::memory_order_relaxed);
+        while(me != active.load_when_equal(me, std::memory_order_acquire))
+            ;
+    }
+
+    void unlock() {
+        active.fetch_add(1,std::memory_order_release);
+    }
+private :
+    Kokkos::Impl::synchronic<int> active;
+    std::atomic<int> queue;
+};
+
+struct mcs_mutex {
+
+    mcs_mutex() : head(nullptr) {
+    }
+
+	mcs_mutex(const mcs_mutex&) = delete;
+	mcs_mutex& operator=(const mcs_mutex&) = delete;
+
+    struct unique_lock {
+
+        unique_lock(mcs_mutex & arg_m) : m(arg_m), next(nullptr), ready(false) {
+
+            unique_lock * const h = m.head.exchange(this,std::memory_order_acquire);
+            if(__builtin_expect(h != nullptr,0)) {
+                h->next.store(this,std::memory_order_seq_cst,Kokkos::Impl::notify_one);
+                while(!ready.load_when_not_equal(false,std::memory_order_acquire))
+                    ;
+            }
+        }
+
+	    unique_lock(const unique_lock&) = delete;
+	    unique_lock& operator=(const unique_lock&) = delete;
+
+        ~unique_lock() {
+            unique_lock * h = this;
+            if(__builtin_expect(!m.head.compare_exchange_strong(h,nullptr,std::memory_order_release, std::memory_order_relaxed),0)) {
+                unique_lock * n = next.load(std::memory_order_relaxed);
+                while(!n)
+                    n = next.load_when_not_equal(n,std::memory_order_relaxed);
+                n->ready.store(true,std::memory_order_release,Kokkos::Impl::notify_one);
+            }
+        }
+
+    private:
+        mcs_mutex & m;
+        Kokkos::Impl::synchronic<unique_lock*> next;
+        Kokkos::Impl::synchronic<bool> ready;
+    };
+
+private :
+    std::atomic<unique_lock*> head;
+};
+
+}
+
+namespace std {
+template<>
+struct unique_lock<Test::mcs_mutex> : Test::mcs_mutex::unique_lock {
+  unique_lock(Test::mcs_mutex & arg_m) : Test::mcs_mutex::unique_lock(arg_m) {
+  }
+  unique_lock(const unique_lock&) = delete;
+  unique_lock& operator=(const unique_lock&) = delete;
+};
+
+}
+
+/* #include <cmath> */
+#include <stdlib.h>
+
+namespace Test {
+
+//-------------------------------------
+//  MersenneTwister
+//-------------------------------------
+#define MT_IA  397
+#define MT_LEN 624
+
+class MersenneTwister
+{
+    volatile unsigned long m_buffer[MT_LEN][64/sizeof(unsigned long)];
+    volatile int m_index;
+
+public:
+    MersenneTwister() {
+        for (int i = 0; i < MT_LEN; i++)
+            m_buffer[i][0] = rand();
+        m_index = 0;
+        for (int i = 0; i < MT_LEN * 100; i++)
+            integer();
+    }
+    unsigned long integer() {
+        // Indices
+        int i = m_index;
+        int i2 = m_index + 1; if (i2 >= MT_LEN) i2 = 0; // wrap-around
+        int j = m_index + MT_IA; if (j >= MT_LEN) j -= MT_LEN; // wrap-around
+
+        // Twist
+        unsigned long s = (m_buffer[i][0] & 0x80000000) | (m_buffer[i2][0] & 0x7fffffff);
+        unsigned long r = m_buffer[j][0] ^ (s >> 1) ^ ((s & 1) * 0x9908B0DF);
+        m_buffer[m_index][0] = r;
+        m_index = i2;
+
+        // Swizzle
+        r ^= (r >> 11);
+        r ^= (r << 7) & 0x9d2c5680UL;
+        r ^= (r << 15) & 0xefc60000UL;
+        r ^= (r >> 18);
+        return r;
+    }
+    float poissonInterval(float ooLambda) {
+        return -logf(1.0f - integer() * 2.3283e-10f) * ooLambda;
+    }
+};
+
+} // namespace Test
+
+#endif //TEST_HPP
diff --git a/lib/kokkos/core/unit_test/TestTaskPolicy.hpp b/lib/kokkos/core/unit_test/TestTaskPolicy.hpp
new file mode 100644
index 0000000000..71790f6def
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestTaskPolicy.hpp
@@ -0,0 +1,1145 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+
+#ifndef KOKKOS_UNITTEST_TASKPOLICY_HPP
+#define KOKKOS_UNITTEST_TASKPOLICY_HPP
+
+#include <stdio.h>
+#include <iostream>
+#include <cmath>
+#include <Kokkos_TaskPolicy.hpp>
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace TestTaskPolicy {
+
+namespace {
+
+long eval_fib( long n )
+{
+  constexpr long mask = 0x03 ;
+
+  long fib[4] = { 0 , 1 , 1 , 2 };
+
+  for ( long i = 2 ; i <= n ; ++i ) {
+    fib[ i & mask ] = fib[ ( i - 1 ) & mask ] + fib[ ( i - 2 ) & mask ];
+  }
+  
+  return fib[ n & mask ];
+}
+
+}
+
+template< typename Space >
+struct TestFib
+{
+  typedef Kokkos::TaskPolicy<Space>  policy_type ;
+  typedef Kokkos::Future<long,Space> future_type ;
+  typedef long value_type ;
+
+  policy_type policy ;
+  future_type fib_m1 ;
+  future_type fib_m2 ;
+  const value_type n ;
+
+  KOKKOS_INLINE_FUNCTION
+  TestFib( const policy_type & arg_policy , const value_type arg_n )
+    : policy(arg_policy)
+    , fib_m1() , fib_m2()
+    , n( arg_n )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( typename policy_type::member_type & , value_type & result )
+    {
+#if 0
+      printf( "\nTestFib(%ld) %d %d\n"
+             , n
+             , int( ! fib_m1.is_null() )
+             , int( ! fib_m2.is_null() )
+             );
+#endif
+
+      if ( n < 2 ) {
+        result = n ;
+      }
+      else if ( ! fib_m2.is_null() && ! fib_m1.is_null() ) {
+        result = fib_m1.get() + fib_m2.get();
+      }
+      else {
+
+        // Spawn new children and respawn myself to sum their results:
+        // Spawn lower value at higher priority as it has a shorter
+        // path to completion.
+
+        fib_m2 = policy.task_spawn( TestFib(policy,n-2)
+                                  , Kokkos::TaskSingle
+                                  , Kokkos::TaskHighPriority );
+
+        fib_m1 = policy.task_spawn( TestFib(policy,n-1)
+                                  , Kokkos::TaskSingle );
+
+        Kokkos::Future<Space> dep[] = { fib_m1 , fib_m2 };
+
+        Kokkos::Future<Space> fib_all = policy.when_all( 2 , dep );
+
+        if ( ! fib_m2.is_null() && ! fib_m1.is_null() && ! fib_all.is_null() ) {
+          // High priority to retire this branch
+          policy.respawn( this , Kokkos::TaskHighPriority , fib_all );
+        }
+        else {
+#if 0
+      printf( "TestFib(%ld) insufficient memory alloc_capacity(%d) task_max(%d) task_accum(%ld)\n"
+             , n
+             , policy.allocation_capacity()
+             , policy.allocated_task_count_max()
+             , policy.allocated_task_count_accum()
+             );
+#endif
+          Kokkos::abort("TestFib insufficient memory");
+
+        }
+      }
+    }
+
+  static void run( int i , size_t MemoryCapacity = 16000 )
+    {
+      typedef typename policy_type::memory_space memory_space ;
+
+      enum { Log2_SuperBlockSize = 12 };
+
+      policy_type root_policy( memory_space() , MemoryCapacity , Log2_SuperBlockSize );
+
+      future_type f = root_policy.host_spawn( TestFib(root_policy,i) , Kokkos::TaskSingle );
+      Kokkos::wait( root_policy );
+      ASSERT_EQ( eval_fib(i) , f.get() );
+
+#if 0
+      fprintf( stdout , "\nTestFib::run(%d) spawn_size(%d) when_all_size(%d) alloc_capacity(%d) task_max(%d) task_accum(%ld)\n"
+             , i
+             , int(root_policy.template spawn_allocation_size<TestFib>())
+             , int(root_policy.when_all_allocation_size(2))
+             , root_policy.allocation_capacity()
+             , root_policy.allocated_task_count_max()
+             , root_policy.allocated_task_count_accum()
+             );
+      fflush( stdout );
+#endif
+    }
+
+};
+
+} // namespace TestTaskPolicy
+
+//----------------------------------------------------------------------------
+
+namespace TestTaskPolicy {
+
+template< class Space >
+struct TestTaskDependence {
+
+  typedef Kokkos::TaskPolicy<Space>  policy_type ;
+  typedef Kokkos::Future<Space>      future_type ;
+  typedef Kokkos::View<long,Space>   accum_type ;
+  typedef void value_type ;
+
+  policy_type  m_policy ;
+  accum_type   m_accum ;
+  long         m_count ;
+
+  KOKKOS_INLINE_FUNCTION
+  TestTaskDependence( long n
+                    , const policy_type & arg_policy
+                    , const accum_type  & arg_accum )
+    : m_policy( arg_policy )
+    , m_accum( arg_accum )
+    , m_count( n )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( typename policy_type::member_type & )
+    {
+       enum { CHUNK = 8 };
+       const int n = CHUNK < m_count ? CHUNK : m_count ;
+
+       if ( 1 < m_count ) {
+         future_type f[ CHUNK ] ;
+
+         const int inc = ( m_count + n - 1 ) / n ;
+
+         for ( int i = 0 ; i < n ; ++i ) {
+           long begin = i * inc ;
+           long count = begin + inc < m_count ? inc : m_count - begin ;
+           f[i] = m_policy.task_spawn( TestTaskDependence(count,m_policy,m_accum) , Kokkos::TaskSingle );
+         }
+
+         m_count = 0 ;
+
+         m_policy.respawn( this , m_policy.when_all( n , f ) );
+       }
+       else if ( 1 == m_count ) {
+         Kokkos::atomic_increment( & m_accum() );
+       }
+    }
+
+  static void run( int n )
+    {
+      typedef typename policy_type::memory_space memory_space ;
+
+      // enum { MemoryCapacity = 4000 }; // Triggers infinite loop in memory pool
+      enum { MemoryCapacity = 16000 };
+      enum { Log2_SuperBlockSize = 12 };
+      policy_type policy( memory_space() , MemoryCapacity , Log2_SuperBlockSize );
+
+      accum_type accum("accum");
+
+      typename accum_type::HostMirror host_accum =
+        Kokkos::create_mirror_view( accum );
+
+      policy.host_spawn( TestTaskDependence(n,policy,accum) , Kokkos::TaskSingle );
+
+      Kokkos::wait( policy );
+
+      Kokkos::deep_copy( host_accum , accum );
+
+      ASSERT_EQ( host_accum() , n );
+    }
+};
+
+} // namespace TestTaskPolicy
+
+//----------------------------------------------------------------------------
+
+namespace TestTaskPolicy {
+
+template< class ExecSpace >
+struct TestTaskTeam {
+
+  //enum { SPAN = 8 };
+  enum { SPAN = 33 };
+  //enum { SPAN = 1 };
+
+  typedef void value_type ;
+  typedef Kokkos::TaskPolicy<ExecSpace>  policy_type ;
+  typedef Kokkos::Future<ExecSpace>      future_type ;
+  typedef Kokkos::View<long*,ExecSpace>  view_type ;
+
+  policy_type  policy ;
+  future_type  future ;
+
+  view_type  parfor_result ;
+  view_type  parreduce_check ;
+  view_type  parscan_result ;
+  view_type  parscan_check ;
+  const long nvalue ;
+
+  KOKKOS_INLINE_FUNCTION
+  TestTaskTeam( const policy_type & arg_policy
+              , const view_type   & arg_parfor_result
+              , const view_type   & arg_parreduce_check
+              , const view_type   & arg_parscan_result
+              , const view_type   & arg_parscan_check
+              , const long          arg_nvalue )
+    : policy(arg_policy)
+    , future()
+    , parfor_result( arg_parfor_result )
+    , parreduce_check( arg_parreduce_check )
+    , parscan_result( arg_parscan_result )
+    , parscan_check( arg_parscan_check )
+    , nvalue( arg_nvalue )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( typename policy_type::member_type & member )
+    {
+      const long end   = nvalue + 1 ;
+      const long begin = 0 < end - SPAN ? end - SPAN : 0 ;
+
+      if ( 0 < begin && future.is_null() ) {
+        if ( member.team_rank() == 0 ) {
+          future = policy.task_spawn
+            ( TestTaskTeam( policy ,
+                            parfor_result ,
+                            parreduce_check,
+                            parscan_result,
+                            parscan_check,
+                            begin - 1 )
+            , Kokkos::TaskTeam );
+
+          assert( ! future.is_null() );
+
+          policy.respawn( this , future );
+        }
+        return ;
+      }
+
+      Kokkos::parallel_for( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i ) { parfor_result[i] = i ; }
+                          );
+
+      // test parallel_reduce without join
+    
+      long tot = 0;
+      long expected = (begin+end-1)*(end-begin)*0.5;
+      
+      Kokkos::parallel_reduce( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i, long &res) { res += parfor_result[i]; }
+                          , tot);
+      Kokkos::parallel_for( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i ) { parreduce_check[i] = expected-tot ; }
+                          );
+
+      // test parallel_reduce with join
+
+      tot = 0;
+      Kokkos::parallel_reduce( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i, long &res) { res += parfor_result[i]; }
+                          , [&]( long& val1, const long& val2) { val1 += val2; }
+                          , tot);
+      Kokkos::parallel_for( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i ) { parreduce_check[i] += expected-tot ; }
+                          );
+
+#if 0
+      // test parallel_scan
+
+      // Exclusive scan
+      Kokkos::parallel_scan<long>( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i, long &val , const bool final ) {
+                              if ( final ) { parscan_result[i] = val; }
+                              val += i;
+                            }
+                          );
+
+      if ( member.team_rank() == 0 ) {
+        for ( long i = begin ; i < end ; ++i ) {
+          parscan_check[i] = (i*(i-1)-begin*(begin-1))*0.5-parscan_result[i];
+        }
+      }
+
+      // Inclusive scan
+      Kokkos::parallel_scan<long>( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i, long &val , const bool final ) {
+                              val += i;
+                              if ( final ) { parscan_result[i] = val; }
+                            }
+                          );
+
+      if ( member.team_rank() == 0 ) {
+        for ( long i = begin ; i < end ; ++i ) {
+          parscan_check[i] += (i*(i+1)-begin*(begin-1))*0.5-parscan_result[i];
+        }
+      }
+#endif
+
+    }
+
+  static void run( long n )
+    {
+      // const unsigned memory_capacity = 10000 ; // causes memory pool infinite loop
+      // const unsigned memory_capacity = 100000 ; // fails with SPAN=1 for serial and OMP
+      const unsigned memory_capacity = 400000 ;
+
+      policy_type root_policy( typename policy_type::memory_space()
+                        , memory_capacity );
+
+      view_type   root_parfor_result("parfor_result",n+1);
+      view_type   root_parreduce_check("parreduce_check",n+1);
+      view_type   root_parscan_result("parscan_result",n+1);
+      view_type   root_parscan_check("parscan_check",n+1);
+
+      typename view_type::HostMirror
+        host_parfor_result = Kokkos::create_mirror_view( root_parfor_result );
+      typename view_type::HostMirror
+        host_parreduce_check = Kokkos::create_mirror_view( root_parreduce_check );
+      typename view_type::HostMirror
+        host_parscan_result = Kokkos::create_mirror_view( root_parscan_result );
+      typename view_type::HostMirror
+        host_parscan_check = Kokkos::create_mirror_view( root_parscan_check );
+
+      future_type f = root_policy.host_spawn(
+                        TestTaskTeam( root_policy ,
+                                      root_parfor_result ,
+                                      root_parreduce_check ,
+                                      root_parscan_result,
+                                      root_parscan_check,
+                                      n ) ,
+                        Kokkos::TaskTeam );
+
+      Kokkos::wait( root_policy );
+
+      Kokkos::deep_copy( host_parfor_result , root_parfor_result );
+      Kokkos::deep_copy( host_parreduce_check , root_parreduce_check );
+      Kokkos::deep_copy( host_parscan_result , root_parscan_result );
+      Kokkos::deep_copy( host_parscan_check , root_parscan_check );
+
+      for ( long i = 0 ; i <= n ; ++i ) {
+        const long answer = i ;
+        if ( host_parfor_result(i) != answer ) {
+          std::cerr << "TestTaskTeam::run ERROR parallel_for result(" << i << ") = "
+                    << host_parfor_result(i) << " != " << answer << std::endl ;
+        }
+        if ( host_parreduce_check(i) != 0 ) {
+          std::cerr << "TestTaskTeam::run ERROR parallel_reduce check(" << i << ") = "
+                    << host_parreduce_check(i) << " != 0" << std::endl ;
+        } //TODO
+        if ( host_parscan_check(i) != 0 ) {
+          std::cerr << "TestTaskTeam::run ERROR parallel_scan check(" << i << ") = "
+                    << host_parscan_check(i) << " != 0" << std::endl ;
+        }
+      }
+    }
+};
+
+template< class ExecSpace >
+struct TestTaskTeamValue {
+
+  enum { SPAN = 8 };
+
+  typedef long value_type ;
+  typedef Kokkos::TaskPolicy<ExecSpace>         policy_type ;
+  typedef Kokkos::Future<value_type,ExecSpace>  future_type ;
+  typedef Kokkos::View<long*,ExecSpace>         view_type ;
+
+  policy_type  policy ;
+  future_type  future ;
+
+  view_type  result ;
+  const long nvalue ;
+
+  KOKKOS_INLINE_FUNCTION
+  TestTaskTeamValue( const policy_type & arg_policy
+                   , const view_type   & arg_result
+                   , const long          arg_nvalue )
+    : policy(arg_policy)
+    , future()
+    , result( arg_result )
+    , nvalue( arg_nvalue )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( typename policy_type::member_type const & member
+                 , value_type & final )
+    {
+      const long end   = nvalue + 1 ;
+      const long begin = 0 < end - SPAN ? end - SPAN : 0 ;
+
+      if ( 0 < begin && future.is_null() ) {
+        if ( member.team_rank() == 0 ) {
+
+          future = policy.task_spawn
+            ( TestTaskTeamValue( policy , result , begin - 1 )
+            , Kokkos::TaskTeam );
+
+          assert( ! future.is_null() );
+
+          policy.respawn( this , future );
+        }
+        return ;
+      }
+
+      Kokkos::parallel_for( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i ) { result[i] = i + 1 ; }
+                          );
+
+      if ( member.team_rank() == 0 ) {
+        final = result[nvalue] ;
+      }
+
+      Kokkos::memory_fence();
+    }
+
+  static void run( long n )
+    {
+      // const unsigned memory_capacity = 10000 ; // causes memory pool infinite loop
+      const unsigned memory_capacity = 100000 ;
+
+      policy_type root_policy( typename policy_type::memory_space()
+                             , memory_capacity );
+
+      view_type   root_result("result",n+1);
+
+      typename view_type::HostMirror
+        host_result = Kokkos::create_mirror_view( root_result );
+
+      future_type fv = root_policy.host_spawn
+        ( TestTaskTeamValue( root_policy, root_result, n ) , Kokkos::TaskTeam );
+
+      Kokkos::wait( root_policy );
+
+      Kokkos::deep_copy( host_result , root_result );
+
+      if ( fv.get() != n + 1 ) {
+        std::cerr << "TestTaskTeamValue ERROR future = "
+                  << fv.get() << " != " << n + 1 << std::endl ;
+      }
+      for ( long i = 0 ; i <= n ; ++i ) {
+        const long answer = i + 1 ;
+        if ( host_result(i) != answer ) {
+          std::cerr << "TestTaskTeamValue ERROR result(" << i << ") = "
+                    << host_result(i) << " != " << answer << std::endl ;
+        }
+      }
+    }
+};
+} // namespace TestTaskPolicy
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace TestTaskPolicy {
+
+template< class ExecSpace >
+struct FibChild {
+
+  typedef long value_type ;
+
+  Kokkos::Experimental::TaskPolicy<ExecSpace> policy ;
+  Kokkos::Experimental::Future<long,ExecSpace> fib_1 ;
+  Kokkos::Experimental::Future<long,ExecSpace> fib_2 ;
+  const value_type n ;
+  int has_nested ;
+
+  KOKKOS_INLINE_FUNCTION
+  FibChild( const Kokkos::Experimental::TaskPolicy<ExecSpace> & arg_policy
+          , const value_type arg_n )
+    : policy(arg_policy)
+    , fib_1() , fib_2()
+    , n( arg_n ), has_nested(0) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void apply( value_type & result )
+    {
+      typedef Kokkos::Experimental::Future<long,ExecSpace> future_type ;
+
+      if ( n < 2 ) {
+
+        has_nested = -1 ;
+
+        result = n ;
+      }
+      else {
+        if ( has_nested == 0 ) {
+          // Spawn new children and respawn myself to sum their results:
+          // Spawn lower value at higher priority as it has a shorter
+          // path to completion.
+          if ( fib_2.is_null() ) {
+            fib_2 = policy.task_create( FibChild(policy,n-2) );
+          }
+
+          if ( ! fib_2.is_null() && fib_1.is_null() ) {
+            fib_1 = policy.task_create( FibChild(policy,n-1) );
+          }
+
+          if ( ! fib_1.is_null() ) {
+            has_nested = 2 ;
+
+            policy.spawn( fib_2 , true /* high priority */ );
+            policy.spawn( fib_1 );
+            policy.add_dependence( this , fib_1 );
+            policy.add_dependence( this , fib_2 );
+            policy.respawn( this );
+          }
+          else {
+            // Release task memory before spawning the task,
+            // after spawning memory cannot be released.
+            fib_2 = future_type();
+            // Respawn when more memory is available
+            policy.respawn_needing_memory( this );
+          }
+        }
+        else if ( has_nested == 2 ) {
+
+          has_nested = -1 ;
+
+          result = fib_1.get() + fib_2.get();
+
+if ( false ) {
+  printf("FibChild %ld = fib(%ld), task_count(%d)\n"
+        , long(n), long(result), policy.allocated_task_count());
+}
+
+        }
+        else {
+          printf("FibChild(%ld) execution error\n",(long)n);
+          Kokkos::abort("FibChild execution error");
+        }
+      }
+    }
+};
+
+template< class ExecSpace >
+struct FibChild2 {
+
+  typedef long value_type ;
+
+  Kokkos::Experimental::TaskPolicy<ExecSpace> policy ;
+  Kokkos::Experimental::Future<long,ExecSpace> fib_a ;
+  Kokkos::Experimental::Future<long,ExecSpace> fib_b ;
+  const value_type n ;
+  int has_nested ;
+
+  KOKKOS_INLINE_FUNCTION
+  FibChild2( const Kokkos::Experimental::TaskPolicy<ExecSpace> & arg_policy
+           , const value_type arg_n )
+    : policy(arg_policy)
+    , n( arg_n ), has_nested(0) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void apply( value_type & result )
+    {
+      if ( 0 == has_nested ) {
+        if ( n < 2 ) {
+
+          has_nested = -1 ;
+
+          result = n ;
+        }
+        else if ( n < 4 ) {
+          // Spawn new children and respawn myself to sum their results:
+          // result = Fib(n-1) + Fib(n-2)
+          has_nested = 2 ;
+
+          // Spawn lower value at higher priority as it has a shorter
+          // path to completion.
+
+          policy.clear_dependence( this );
+          fib_a = policy.spawn( policy.task_create( FibChild2(policy,n-1) ) );
+          fib_b = policy.spawn( policy.task_create( FibChild2(policy,n-2) ) , true );
+          policy.add_dependence( this , fib_a );
+          policy.add_dependence( this , fib_b );
+          policy.respawn( this );
+        }
+        else {
+          // Spawn new children and respawn myself to sum their results:
+          // result = Fib(n-1) + Fib(n-2)
+          // result = ( Fib(n-2) + Fib(n-3) ) + ( Fib(n-3) + Fib(n-4) )
+          // result = ( ( Fib(n-3) + Fib(n-4) ) + Fib(n-3) ) + ( Fib(n-3) + Fib(n-4) )
+          // result = 3 * Fib(n-3) + 2 * Fib(n-4)
+          has_nested = 4 ;
+
+          // Spawn lower value at higher priority as it has a shorter
+          // path to completion.
+
+          policy.clear_dependence( this );
+          fib_a = policy.spawn( policy.task_create( FibChild2(policy,n-3) ) );
+          fib_b = policy.spawn( policy.task_create( FibChild2(policy,n-4) ) , true );
+          policy.add_dependence( this , fib_a );
+          policy.add_dependence( this , fib_b );
+          policy.respawn( this );
+        }
+     }
+     else if ( 2 == has_nested || 4 == has_nested ) {
+        result = ( has_nested == 2 ) ? fib_a.get() + fib_b.get()
+                                     : 3 * fib_a.get() + 2 * fib_b.get() ;
+
+        has_nested = -1 ;
+      }
+      else {
+        printf("FibChild2(%ld) execution error\n",(long)n);
+        Kokkos::abort("FibChild2 execution error");
+      }
+    }
+};
+
+template< class ExecSpace >
+void test_fib( long n , const unsigned task_max_count = 4096 )
+{
+  const unsigned task_max_size   = 256 ;
+  const unsigned task_dependence = 4 ;
+
+  Kokkos::Experimental::TaskPolicy<ExecSpace>
+    policy( task_max_count
+          , task_max_size
+          , task_dependence );
+
+  Kokkos::Experimental::Future<long,ExecSpace> f =
+    policy.spawn( policy.proc_create( FibChild<ExecSpace>(policy,n) ) );
+
+  Kokkos::Experimental::wait( policy );
+
+  if ( f.get() != eval_fib(n) ) {
+    std::cout << "Fib(" << n << ") = " << f.get();
+    std::cout << " != " << eval_fib(n);
+    std::cout << std::endl ;
+  }
+}
+
+template< class ExecSpace >
+void test_fib2( long n , const unsigned task_max_count = 1024 )
+{
+  const unsigned task_max_size   = 256 ;
+  const unsigned task_dependence = 4 ;
+
+  Kokkos::Experimental::TaskPolicy<ExecSpace>
+    policy( task_max_count
+          , task_max_size
+          , task_dependence );
+
+  Kokkos::Experimental::Future<long,ExecSpace> f =
+    policy.spawn( policy.proc_create( FibChild2<ExecSpace>(policy,n) ) );
+
+  Kokkos::Experimental::wait( policy );
+
+  if ( f.get() != eval_fib(n) ) {
+    std::cout << "Fib2(" << n << ") = " << f.get();
+    std::cout << " != " << eval_fib(n);
+    std::cout << std::endl ;
+  }
+}
+
+//----------------------------------------------------------------------------
+
+template< class ExecSpace >
+struct Norm2 {
+
+  typedef double value_type ;
+
+  const double * const m_x ;
+
+  Norm2( const double * x ) : m_x(x) {}
+
+  inline
+  void init( double & val ) const { val = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int i , double & val ) const { val += m_x[i] * m_x[i] ; }
+
+  void apply( double & dst ) const { dst = std::sqrt( dst ); }
+};
+
+template< class ExecSpace >
+void test_norm2( const int n )
+{
+  const unsigned task_max_count  = 1024 ;
+  const unsigned task_max_size   = 256 ;
+  const unsigned task_dependence = 4 ;
+
+  Kokkos::Experimental::TaskPolicy<ExecSpace>
+    policy( task_max_count
+          , task_max_size
+          , task_dependence );
+
+  double * const x = new double[n];
+
+  for ( int i = 0 ; i < n ; ++i ) x[i] = 1 ;
+
+  Kokkos::RangePolicy<ExecSpace> r(0,n);
+
+  Kokkos::Experimental::Future<double,ExecSpace> f =
+    Kokkos::Experimental::spawn_reduce( policy , r , Norm2<ExecSpace>(x) );
+
+  Kokkos::Experimental::wait( policy );
+
+#if defined(PRINT)
+  std::cout << "Norm2: " << f.get() << std::endl ;
+#endif
+
+  delete[] x ;
+}
+
+//----------------------------------------------------------------------------
+
+template< class Space >
+struct TaskDep {
+
+  typedef int value_type ;
+  typedef Kokkos::Experimental::TaskPolicy< Space > policy_type ;
+
+  const policy_type policy ;
+  const int         input ;
+
+  TaskDep( const policy_type & arg_p , const int arg_i )
+    : policy( arg_p ), input( arg_i ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void apply( int & val )
+  {
+    val = input ;
+    const int num = policy.get_dependence( this );
+
+    for ( int i = 0 ; i < num ; ++i ) {
+      Kokkos::Experimental::Future<int,Space> f = policy.get_dependence( this , i );
+      val += f.get();
+    }
+  }
+};
+
+
+template< class Space >
+void test_task_dep( const int n )
+{
+  enum { NTEST = 64 };
+
+  const unsigned task_max_count  = 1024 ;
+  const unsigned task_max_size   = 64 ;
+  const unsigned task_dependence = 4 ;
+
+  Kokkos::Experimental::TaskPolicy<Space>
+    policy( task_max_count
+          , task_max_size
+          , task_dependence );
+
+  Kokkos::Experimental::Future<int,Space> f[ NTEST ];
+
+  for ( int i = 0 ; i < NTEST ; ++i ) {
+    // Create task in the "constructing" state with capacity for 'n+1' dependences
+    f[i] = policy.proc_create( TaskDep<Space>(policy,0) , n + 1 );
+
+    if ( f[i].get_task_state() != Kokkos::Experimental::TASK_STATE_CONSTRUCTING ) {
+      Kokkos::Impl::throw_runtime_exception("get_task_state() != Kokkos::Experimental::TASK_STATE_CONSTRUCTING");
+    }
+
+    // Only use 'n' dependences
+
+    for ( int j = 0 ; j < n ; ++j ) {
+
+      Kokkos::Experimental::Future<int,Space> nested =
+        policy.proc_create( TaskDep<Space>(policy,j+1) );
+
+      policy.spawn( nested );
+
+      // Add dependence to a "constructing" task
+      policy.add_dependence( f[i] , nested );
+    }
+
+    // Spawn task from the "constructing" to the "waiting" state
+    policy.spawn( f[i] );
+  }
+
+  const int answer = n % 2 ? n * ( ( n + 1 ) / 2 ) : ( n / 2 ) * ( n + 1 );
+
+  Kokkos::Experimental::wait( policy );
+
+  int error = 0 ;
+  for ( int i = 0 ; i < NTEST ; ++i ) {
+    if ( f[i].get_task_state() != Kokkos::Experimental::TASK_STATE_COMPLETE ) {
+      Kokkos::Impl::throw_runtime_exception("get_task_state() != Kokkos::Experimental::TASK_STATE_COMPLETE");
+    }
+    if ( answer != f[i].get() && 0 == error ) {
+      std::cout << "test_task_dep(" << n << ") ERROR at[" << i << "]"
+                << " answer(" << answer << ") != result(" << f[i].get() << ")" << std::endl ;
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+
+template< class ExecSpace >
+struct TaskTeam {
+
+  enum { SPAN = 8 };
+
+  typedef void value_type ;
+  typedef Kokkos::Experimental::TaskPolicy<ExecSpace>  policy_type ;
+  typedef Kokkos::Experimental::Future<void,ExecSpace> future_type ;
+  typedef Kokkos::View<long*,ExecSpace>                view_type ;
+
+  policy_type  policy ;
+  future_type  future ;
+
+  view_type  result ;
+  const long nvalue ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskTeam( const policy_type & arg_policy
+          , const view_type   & arg_result
+          , const long          arg_nvalue )
+    : policy(arg_policy)
+    , future()
+    , result( arg_result )
+    , nvalue( arg_nvalue )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void apply( const typename policy_type::member_type & member )
+    {
+      const long end   = nvalue + 1 ;
+      const long begin = 0 < end - SPAN ? end - SPAN : 0 ;
+
+      if ( 0 < begin && future.get_task_state() == Kokkos::Experimental::TASK_STATE_NULL ) {
+        if ( member.team_rank() == 0 ) {
+          future = policy.spawn( policy.task_create_team( TaskTeam( policy , result , begin - 1 ) ) );
+          policy.clear_dependence( this );
+          policy.add_dependence( this , future );
+          policy.respawn( this );
+        }
+        return ;
+      }
+
+      Kokkos::parallel_for( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i ) { result[i] = i + 1 ; }
+                          );
+    }
+};
+
+template< class ExecSpace >
+struct TaskTeamValue {
+
+  enum { SPAN = 8 };
+
+  typedef long value_type ;
+  typedef Kokkos::Experimental::TaskPolicy<ExecSpace>         policy_type ;
+  typedef Kokkos::Experimental::Future<value_type,ExecSpace>  future_type ;
+  typedef Kokkos::View<long*,ExecSpace>                       view_type ;
+
+  policy_type  policy ;
+  future_type  future ;
+
+  view_type  result ;
+  const long nvalue ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskTeamValue( const policy_type & arg_policy
+               , const view_type   & arg_result
+               , const long          arg_nvalue )
+    : policy(arg_policy)
+    , future()
+    , result( arg_result )
+    , nvalue( arg_nvalue )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void apply( const typename policy_type::member_type & member , value_type & final )
+    {
+      const long end   = nvalue + 1 ;
+      const long begin = 0 < end - SPAN ? end - SPAN : 0 ;
+
+      if ( 0 < begin && future.is_null() ) {
+        if ( member.team_rank() == 0 ) {
+
+          future = policy.task_create_team( TaskTeamValue( policy , result , begin - 1 ) );
+
+          policy.spawn( future );
+          policy.add_dependence( this , future );
+          policy.respawn( this );
+        }
+        return ;
+      }
+
+      Kokkos::parallel_for( Kokkos::TeamThreadRange(member,begin,end)
+                          , [&]( int i ) { result[i] = i + 1 ; }
+                          );
+
+      if ( member.team_rank() == 0 ) {
+        final = result[nvalue] ;
+      }
+
+      Kokkos::memory_fence();
+    }
+};
+
+template< class ExecSpace >
+void test_task_team( long n )
+{
+  typedef TaskTeam< ExecSpace >            task_type ;
+  typedef TaskTeamValue< ExecSpace >       task_value_type ;
+  typedef typename task_type::view_type    view_type ;
+  typedef typename task_type::policy_type  policy_type ;
+
+  typedef typename task_type::future_type        future_type ;
+  typedef typename task_value_type::future_type  future_value_type ;
+
+  const unsigned task_max_count  = 1024 ;
+  const unsigned task_max_size   = 256 ;
+  const unsigned task_dependence = 4 ;
+
+  policy_type
+    policy( task_max_count
+          , task_max_size
+          , task_dependence );
+
+  view_type    result("result",n+1);
+
+  typename view_type::HostMirror
+    host_result = Kokkos::create_mirror_view( result );
+
+  future_type f = policy.proc_create_team( task_type( policy , result , n ) );
+
+  ASSERT_FALSE( f.is_null() );
+
+  policy.spawn( f );
+
+  Kokkos::Experimental::wait( policy );
+
+  Kokkos::deep_copy( host_result , result );
+
+  for ( long i = 0 ; i <= n ; ++i ) {
+    const long answer = i + 1 ;
+    if ( host_result(i) != answer ) {
+      std::cerr << "test_task_team void ERROR result(" << i << ") = "
+                << host_result(i) << " != " << answer << std::endl ;
+    }
+  }
+
+  future_value_type fv = policy.proc_create_team( task_value_type( policy , result , n ) );
+
+  ASSERT_FALSE( fv.is_null() );
+
+  policy.spawn( fv );
+
+  Kokkos::Experimental::wait( policy );
+
+  Kokkos::deep_copy( host_result , result );
+
+  if ( fv.get() != n + 1 ) {
+    std::cerr << "test_task_team value ERROR future = "
+              << fv.get() << " != " << n + 1 << std::endl ;
+  }
+  for ( long i = 0 ; i <= n ; ++i ) {
+    const long answer = i + 1 ;
+    if ( host_result(i) != answer ) {
+      std::cerr << "test_task_team value ERROR result(" << i << ") = "
+                << host_result(i) << " != " << answer << std::endl ;
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+
+template< class ExecSpace >
+struct TaskLatchAdd {
+
+  typedef void value_type ;
+  typedef Kokkos::Experimental::Future< Kokkos::Experimental::Latch , ExecSpace >  future_type ;
+
+  future_type     latch ;
+  volatile int *  count ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskLatchAdd( const future_type & arg_latch 
+              , volatile int * const arg_count )
+    : latch( arg_latch )
+    , count( arg_count )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void apply()
+    {
+      Kokkos::atomic_fetch_add( count , 1 );
+      latch.add(1);
+    }
+};
+
+template< class ExecSpace >
+struct TaskLatchRun {
+
+  typedef void value_type ;
+  typedef Kokkos::Experimental::TaskPolicy< ExecSpace >      policy_type ;
+  typedef Kokkos::Experimental::Future< Kokkos::Experimental::Latch , ExecSpace >  future_type ;
+
+  policy_type policy ;
+  int total ;
+  volatile int count ;
+
+  KOKKOS_INLINE_FUNCTION
+  TaskLatchRun( const policy_type & arg_policy , const int arg_total )
+    : policy(arg_policy), total(arg_total), count(0) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void apply()
+    {
+      if ( 0 == count && 0 < total ) {
+        future_type latch = policy.create_latch( total );
+
+        for ( int i = 0 ; i < total ; ++i ) {
+          auto f = policy.task_create( TaskLatchAdd<ExecSpace>(latch,&count) , 0 );
+          if ( f.is_null() ) {
+            Kokkos::abort("TaskLatchAdd allocation FAILED" );
+          }
+
+          if ( policy.spawn( f ).is_null() ) {
+            Kokkos::abort("TaskLatcAdd spawning FAILED" );
+          }
+        }
+
+        policy.add_dependence( this , latch );
+        policy.respawn( this );
+      }
+      else if ( count != total ) {
+        printf("TaskLatchRun FAILED %d != %d\n",count,total);
+      }
+    }
+};
+
+
+template< class ExecSpace >
+void test_latch( int n )
+{
+  typedef TaskLatchRun< ExecSpace >        task_type ;
+  typedef typename task_type::policy_type  policy_type ;
+
+  // Primary + latch + n * LatchAdd
+  //
+  // This test uses several two different block sizes for allocation from the
+  // memory pool, so the memory size requested must be big enough to cause two
+  // or more superblocks to be used.  Currently, the superblock size in the
+  // task policy is 2^16, so make the minimum requested memory size greater
+  // than this.
+  const unsigned task_max_count  = n + 2 < 256 ? 256 : n + 2;
+  const unsigned task_max_size   = 256;
+  const unsigned task_dependence = 4 ;
+
+  policy_type
+    policy( task_max_count
+          , task_max_size
+          , task_dependence );
+
+  policy.spawn( policy.proc_create( TaskLatchRun<ExecSpace>(policy,n) ) );
+
+  wait( policy );
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+} // namespace TestTaskPolicy
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+#endif /* #ifndef KOKKOS_UNITTEST_TASKPOLICY_HPP */
+
+
diff --git a/lib/kokkos/core/unit_test/TestTeam.hpp b/lib/kokkos/core/unit_test/TestTeam.hpp
new file mode 100644
index 0000000000..db6b0cff7e
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestTeam.hpp
@@ -0,0 +1,910 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <stdio.h>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+namespace {
+
+template< class ExecSpace, class ScheduleType >
+struct TestTeamPolicy {
+
+  typedef typename Kokkos::TeamPolicy< ScheduleType,  ExecSpace >::member_type team_member ;
+  typedef Kokkos::View<int**,ExecSpace> view_type ;
+
+  view_type m_flags ;
+
+  TestTeamPolicy( const size_t league_size )
+    : m_flags( Kokkos::ViewAllocateWithoutInitializing("flags")
+             , Kokkos::TeamPolicy< ScheduleType,  ExecSpace >::team_size_max( *this )
+             , league_size )
+    {}
+
+  struct VerifyInitTag {};
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const team_member & member ) const
+    {
+      const int tid = member.team_rank() + member.team_size() * member.league_rank();
+
+      m_flags( member.team_rank() , member.league_rank() ) = tid ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const VerifyInitTag & , const team_member & member ) const
+    {
+      const int tid = member.team_rank() + member.team_size() * member.league_rank();
+
+      if ( tid != m_flags( member.team_rank() , member.league_rank() ) ) {
+        printf("TestTeamPolicy member(%d,%d) error %d != %d\n"
+              , member.league_rank() , member.team_rank()
+              , tid , m_flags( member.team_rank() , member.league_rank() ) );
+      }
+    }
+
+  // included for test_small_league_size
+  TestTeamPolicy()
+    : m_flags()
+  {}
+
+  // included for test_small_league_size
+  struct NoOpTag {} ;
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const NoOpTag & , const team_member & member ) const
+    {}
+
+
+  static void test_small_league_size() {
+
+    int bs = 8; // batch size (number of elements per batch)
+    int ns = 16; // total number of "problems" to process
+
+    // calculate total scratch memory space size
+    const int level = 0;
+    int mem_size = 960;
+    const int num_teams = ns/bs;
+    const Kokkos::TeamPolicy< ExecSpace, NoOpTag > policy(num_teams, Kokkos::AUTO());
+
+    Kokkos::parallel_for ( policy.set_scratch_size(level, Kokkos::PerTeam(mem_size), Kokkos::PerThread(0))
+                         , TestTeamPolicy()
+                         );
+  }
+
+  static void test_for( const size_t league_size )
+    {
+      TestTeamPolicy functor( league_size );
+
+      const int team_size = Kokkos::TeamPolicy< ScheduleType,  ExecSpace >::team_size_max( functor );
+
+      Kokkos::parallel_for( Kokkos::TeamPolicy< ScheduleType,  ExecSpace >( league_size , team_size ) , functor );
+      Kokkos::parallel_for( Kokkos::TeamPolicy< ScheduleType,  ExecSpace , VerifyInitTag >( league_size , team_size ) , functor );
+
+      test_small_league_size();
+    }
+
+  struct ReduceTag {};
+
+  typedef long value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const team_member & member , value_type & update ) const
+    {
+      update += member.team_rank() + member.team_size() * member.league_rank();
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const ReduceTag & , const team_member & member , value_type & update ) const
+    {
+      update += 1 + member.team_rank() + member.team_size() * member.league_rank();
+    }
+
+  static void test_reduce( const size_t league_size )
+    {
+      TestTeamPolicy functor( league_size );
+
+      const int team_size = Kokkos::TeamPolicy< ScheduleType,  ExecSpace >::team_size_max( functor );
+      const long N = team_size * league_size ;
+
+      long total = 0 ;
+
+      Kokkos::parallel_reduce( Kokkos::TeamPolicy< ScheduleType,  ExecSpace >( league_size , team_size ) , functor , total );
+      ASSERT_EQ( size_t((N-1)*(N))/2 , size_t(total) );
+
+      Kokkos::parallel_reduce( Kokkos::TeamPolicy< ScheduleType,  ExecSpace , ReduceTag >( league_size , team_size ) , functor , total );
+      ASSERT_EQ( (size_t(N)*size_t(N+1))/2 , size_t(total) );
+    }
+};
+
+}
+}
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+template< typename ScalarType , class DeviceType, class ScheduleType >
+class ReduceTeamFunctor
+{
+public:
+  typedef DeviceType execution_space ;
+  typedef Kokkos::TeamPolicy< ScheduleType,  execution_space >  policy_type ;
+  typedef typename execution_space::size_type        size_type ;
+
+  struct value_type {
+    ScalarType value[3] ;
+  };
+
+  const size_type nwork ;
+
+  ReduceTeamFunctor( const size_type & arg_nwork ) : nwork( arg_nwork ) {}
+
+  ReduceTeamFunctor( const ReduceTeamFunctor & rhs )
+    : nwork( rhs.nwork ) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & dst ) const
+  {
+    dst.value[0] = 0 ;
+    dst.value[1] = 0 ;
+    dst.value[2] = 0 ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile value_type & dst ,
+             const volatile value_type & src ) const
+  {
+    dst.value[0] += src.value[0] ;
+    dst.value[1] += src.value[1] ;
+    dst.value[2] += src.value[2] ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const typename policy_type::member_type ind , value_type & dst ) const
+  {
+    const int thread_rank = ind.team_rank() + ind.team_size() * ind.league_rank();
+    const int thread_size = ind.team_size() * ind.league_size();
+    const int chunk = ( nwork + thread_size - 1 ) / thread_size ;
+
+    size_type iwork = chunk * thread_rank ;
+    const size_type iwork_end = iwork + chunk < nwork ? iwork + chunk : nwork ;
+
+    for ( ; iwork < iwork_end ; ++iwork ) {
+      dst.value[0] += 1 ;
+      dst.value[1] += iwork + 1 ;
+      dst.value[2] += nwork - iwork ;
+    }
+  }
+};
+
+} // namespace Test
+
+namespace {
+
+template< typename ScalarType , class DeviceType, class ScheduleType >
+class TestReduceTeam
+{
+public:
+  typedef DeviceType    execution_space ;
+  typedef Kokkos::TeamPolicy< ScheduleType,  execution_space >  policy_type ;
+  typedef typename execution_space::size_type    size_type ;
+
+  //------------------------------------
+
+  TestReduceTeam( const size_type & nwork )
+  {
+    run_test(nwork);
+  }
+
+  void run_test( const size_type & nwork )
+  {
+    typedef Test::ReduceTeamFunctor< ScalarType , execution_space , ScheduleType> functor_type ;
+    typedef typename functor_type::value_type value_type ;
+    typedef Kokkos::View< value_type, Kokkos::HostSpace, Kokkos::MemoryUnmanaged > result_type ;
+
+    enum { Count = 3 };
+    enum { Repeat = 100 };
+
+    value_type result[ Repeat ];
+
+    const unsigned long nw   = nwork ;
+    const unsigned long nsum = nw % 2 ? nw * (( nw + 1 )/2 )
+                                      : (nw/2) * ( nw + 1 );
+
+    const unsigned team_size   = policy_type::team_size_recommended( functor_type(nwork) );
+    const unsigned league_size = ( nwork + team_size - 1 ) / team_size ;
+
+    policy_type team_exec( league_size , team_size );
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      result_type tmp( & result[i] );
+      Kokkos::parallel_reduce( team_exec , functor_type(nwork) , tmp );
+    }
+
+    execution_space::fence();
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      for ( unsigned j = 0 ; j < Count ; ++j ) {
+        const unsigned long correct = 0 == j % 3 ? nw : nsum ;
+        ASSERT_EQ( (ScalarType) correct , result[i].value[j] );
+      }
+    }
+  }
+};
+
+}
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+template< class DeviceType, class ScheduleType >
+class ScanTeamFunctor
+{
+public:
+  typedef DeviceType  execution_space ;
+  typedef Kokkos::TeamPolicy< ScheduleType,  execution_space >  policy_type ;
+
+  typedef long int    value_type ;
+  Kokkos::View< value_type , execution_space > accum ;
+  Kokkos::View< value_type , execution_space > total ;
+
+  ScanTeamFunctor() : accum("accum"), total("total") {}
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & error ) const { error = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( value_type volatile & error ,
+             value_type volatile const & input ) const
+    { if ( input ) error = 1 ; }
+
+  struct JoinMax {
+    typedef long int value_type ;
+    KOKKOS_INLINE_FUNCTION
+    void join( value_type volatile & dst
+             , value_type volatile const & input ) const
+      { if ( dst < input ) dst = input ; }
+  };
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const typename policy_type::member_type ind , value_type & error ) const
+  {
+    if ( 0 == ind.league_rank() && 0 == ind.team_rank() ) {
+      const long int thread_count = ind.league_size() * ind.team_size();
+      total() = ( thread_count * ( thread_count + 1 ) ) / 2 ;
+    }
+
+    // Team max:
+    const int long m = ind.team_reduce( (long int) ( ind.league_rank() + ind.team_rank() ) , JoinMax() );
+
+    if ( m != ind.league_rank() + ( ind.team_size() - 1 ) ) {
+      printf("ScanTeamFunctor[%d.%d of %d.%d] reduce_max_answer(%ld) != reduce_max(%ld)\n"
+            , ind.league_rank(), ind.team_rank()
+            , ind.league_size(), ind.team_size()
+            , (long int)(ind.league_rank() + ( ind.team_size() - 1 )) , m );
+    }
+
+    // Scan:
+    const long int answer =
+      ( ind.league_rank() + 1 ) * ind.team_rank() +
+      ( ind.team_rank() * ( ind.team_rank() + 1 ) ) / 2 ;
+
+    const long int result =
+      ind.team_scan( ind.league_rank() + 1 + ind.team_rank() + 1 );
+
+    const long int result2 =
+      ind.team_scan( ind.league_rank() + 1 + ind.team_rank() + 1 );
+
+    if ( answer != result || answer != result2 ) {
+      printf("ScanTeamFunctor[%d.%d of %d.%d] answer(%ld) != scan_first(%ld) or scan_second(%ld)\n",
+             ind.league_rank(), ind.team_rank(),
+             ind.league_size(), ind.team_size(),
+             answer,result,result2);
+      error = 1 ;
+    }
+
+    const long int thread_rank = ind.team_rank() +
+                                 ind.team_size() * ind.league_rank();
+    ind.team_scan( 1 + thread_rank , accum.ptr_on_device() );
+  }
+};
+
+template< class DeviceType, class ScheduleType >
+class TestScanTeam
+{
+public:
+  typedef DeviceType  execution_space ;
+  typedef long int    value_type ;
+
+  typedef Kokkos::TeamPolicy< ScheduleType,  execution_space > policy_type ;
+  typedef Test::ScanTeamFunctor<DeviceType, ScheduleType> functor_type ;
+
+  //------------------------------------
+
+  TestScanTeam( const size_t nteam )
+  {
+    run_test(nteam);
+  }
+
+  void run_test( const size_t nteam )
+  {
+    typedef Kokkos::View< long int , Kokkos::HostSpace , Kokkos::MemoryUnmanaged >  result_type ;
+
+    const unsigned REPEAT = 100000 ;
+    const unsigned Repeat = ( REPEAT + nteam - 1 ) / nteam ;
+
+    functor_type functor ;
+
+    policy_type team_exec( nteam , policy_type::team_size_max( functor ) );
+
+    for ( unsigned i = 0 ; i < Repeat ; ++i ) {
+      long int accum = 0 ;
+      long int total = 0 ;
+      long int error = 0 ;
+      Kokkos::deep_copy( functor.accum , total );
+      Kokkos::parallel_reduce( team_exec , functor , result_type( & error ) );
+      DeviceType::fence();
+      Kokkos::deep_copy( accum , functor.accum );
+      Kokkos::deep_copy( total , functor.total );
+
+      ASSERT_EQ( error , 0 );
+      ASSERT_EQ( total , accum );
+    }
+
+    execution_space::fence();
+  }
+};
+
+} // namespace Test
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+template< class ExecSpace, class ScheduleType >
+struct SharedTeamFunctor {
+
+  typedef ExecSpace  execution_space ;
+  typedef int        value_type ;
+  typedef Kokkos::TeamPolicy< ScheduleType,  execution_space >  policy_type ;
+
+  enum { SHARED_COUNT = 1000 };
+
+  typedef typename ExecSpace::scratch_memory_space shmem_space ;
+
+  // tbd: MemoryUnmanaged should be the default for shared memory space
+  typedef Kokkos::View<int*,shmem_space,Kokkos::MemoryUnmanaged> shared_int_array_type ;
+
+  // Tell how much shared memory will be required by this functor:
+  inline
+  unsigned team_shmem_size( int team_size ) const
+  {
+    return shared_int_array_type::shmem_size( SHARED_COUNT ) +
+           shared_int_array_type::shmem_size( SHARED_COUNT );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const typename policy_type::member_type & ind , value_type & update ) const
+  {
+    const shared_int_array_type shared_A( ind.team_shmem() , SHARED_COUNT );
+    const shared_int_array_type shared_B( ind.team_shmem() , SHARED_COUNT );
+
+    if ((shared_A.ptr_on_device () == NULL && SHARED_COUNT > 0) ||
+        (shared_B.ptr_on_device () == NULL && SHARED_COUNT > 0)) {
+      printf ("Failed to allocate shared memory of size %lu\n",
+              static_cast<unsigned long> (SHARED_COUNT));
+      ++update; // failure to allocate is an error
+    }
+    else {
+      for ( int i = ind.team_rank() ; i < SHARED_COUNT ; i += ind.team_size() ) {
+        shared_A[i] = i + ind.league_rank();
+        shared_B[i] = 2 * i + ind.league_rank();
+      }
+
+      ind.team_barrier();
+
+      if ( ind.team_rank() + 1 == ind.team_size() ) {
+        for ( int i = 0 ; i < SHARED_COUNT ; ++i ) {
+          if ( shared_A[i] != i + ind.league_rank() ) {
+            ++update ;
+          }
+          if ( shared_B[i] != 2 * i + ind.league_rank() ) {
+            ++update ;
+          }
+        }
+      }
+    }
+  }
+};
+
+}
+
+namespace {
+
+template< class ExecSpace, class ScheduleType >
+struct TestSharedTeam {
+
+  TestSharedTeam()
+  { run(); }
+
+  void run()
+  {
+    typedef Test::SharedTeamFunctor<ExecSpace, ScheduleType> Functor ;
+    typedef Kokkos::View< typename Functor::value_type , Kokkos::HostSpace , Kokkos::MemoryUnmanaged >  result_type ;
+
+    const size_t team_size = Kokkos::TeamPolicy< ScheduleType,  ExecSpace >::team_size_max( Functor() );
+
+    Kokkos::TeamPolicy< ScheduleType,  ExecSpace > team_exec( 8192 / team_size , team_size );
+
+    typename Functor::value_type error_count = 0 ;
+
+    Kokkos::parallel_reduce( team_exec , Functor() , result_type( & error_count ) );
+
+    ASSERT_EQ( error_count , 0 );
+  }
+};
+}
+
+namespace Test {
+
+#if defined (KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+template< class MemorySpace, class ExecSpace, class ScheduleType >
+struct TestLambdaSharedTeam {
+
+  TestLambdaSharedTeam()
+  { run(); }
+
+  void run()
+  {
+    typedef Test::SharedTeamFunctor<ExecSpace, ScheduleType> Functor ;
+    //typedef Kokkos::View< typename Functor::value_type , Kokkos::HostSpace , Kokkos::MemoryUnmanaged >  result_type ;
+    typedef Kokkos::View< typename Functor::value_type , MemorySpace, Kokkos::MemoryUnmanaged >  result_type ;
+
+    typedef typename ExecSpace::scratch_memory_space shmem_space ;
+
+    // tbd: MemoryUnmanaged should be the default for shared memory space
+    typedef Kokkos::View<int*,shmem_space,Kokkos::MemoryUnmanaged> shared_int_array_type ;
+
+    const int SHARED_COUNT = 1000;
+    int team_size = 1;
+#ifdef KOKKOS_HAVE_CUDA
+    if(std::is_same<ExecSpace,Kokkos::Cuda>::value)
+      team_size = 128;
+#endif
+    Kokkos::TeamPolicy< ScheduleType,  ExecSpace > team_exec( 8192 / team_size , team_size);
+    team_exec = team_exec.set_scratch_size(0,Kokkos::PerTeam(SHARED_COUNT*2*sizeof(int)));
+
+    typename Functor::value_type error_count = 0 ;
+
+    Kokkos::parallel_reduce( team_exec , KOKKOS_LAMBDA
+        ( const typename Kokkos::TeamPolicy< ScheduleType,  ExecSpace >::member_type & ind , int & update ) {
+
+      const shared_int_array_type shared_A( ind.team_shmem() , SHARED_COUNT );
+      const shared_int_array_type shared_B( ind.team_shmem() , SHARED_COUNT );
+
+      if ((shared_A.ptr_on_device () == NULL && SHARED_COUNT > 0) ||
+          (shared_B.ptr_on_device () == NULL && SHARED_COUNT > 0)) {
+        printf ("Failed to allocate shared memory of size %lu\n",
+                static_cast<unsigned long> (SHARED_COUNT));
+        ++update; // failure to allocate is an error
+      } else {
+        for ( int i = ind.team_rank() ; i < SHARED_COUNT ; i += ind.team_size() ) {
+          shared_A[i] = i + ind.league_rank();
+          shared_B[i] = 2 * i + ind.league_rank();
+        }
+
+        ind.team_barrier();
+
+        if ( ind.team_rank() + 1 == ind.team_size() ) {
+          for ( int i = 0 ; i < SHARED_COUNT ; ++i ) {
+            if ( shared_A[i] != i + ind.league_rank() ) {
+              ++update ;
+            }
+            if ( shared_B[i] != 2 * i + ind.league_rank() ) {
+              ++update ;
+            }
+          }
+        }
+      }
+    }, result_type( & error_count ) );
+
+    ASSERT_EQ( error_count , 0 );
+  }
+};
+#endif
+}
+
+namespace Test {
+
+template< class ExecSpace, class ScheduleType >
+struct ScratchTeamFunctor {
+
+  typedef ExecSpace  execution_space ;
+  typedef int        value_type ;
+  typedef Kokkos::TeamPolicy< ScheduleType,  execution_space >  policy_type ;
+
+  enum { SHARED_TEAM_COUNT = 100 };
+  enum { SHARED_THREAD_COUNT = 10 };
+
+  typedef typename ExecSpace::scratch_memory_space shmem_space ;
+
+  // tbd: MemoryUnmanaged should be the default for shared memory space
+  typedef Kokkos::View<size_t*,shmem_space,Kokkos::MemoryUnmanaged> shared_int_array_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const typename policy_type::member_type & ind , value_type & update ) const
+  {
+    const shared_int_array_type scratch_ptr( ind.team_scratch(1) , 2*ind.team_size() );
+    const shared_int_array_type scratch_A( ind.team_scratch(1) , SHARED_TEAM_COUNT );
+    const shared_int_array_type scratch_B( ind.thread_scratch(1) , SHARED_THREAD_COUNT );
+
+    if ((scratch_ptr.ptr_on_device () == NULL ) ||
+        (scratch_A.  ptr_on_device () == NULL && SHARED_TEAM_COUNT > 0) ||
+        (scratch_B.  ptr_on_device () == NULL && SHARED_THREAD_COUNT > 0)) {
+      printf ("Failed to allocate shared memory of size %lu\n",
+              static_cast<unsigned long> (SHARED_TEAM_COUNT));
+      ++update; // failure to allocate is an error
+    }
+    else {
+      Kokkos::parallel_for(Kokkos::TeamThreadRange(ind,0,(int)SHARED_TEAM_COUNT),[&] (const int &i) {
+        scratch_A[i] = i + ind.league_rank();
+      });
+      for(int i=0; i<SHARED_THREAD_COUNT; i++)
+        scratch_B[i] = 10000*ind.league_rank() + 100*ind.team_rank() + i;
+
+      scratch_ptr[ind.team_rank()] = (size_t) scratch_A.ptr_on_device();
+      scratch_ptr[ind.team_rank() + ind.team_size()] = (size_t) scratch_B.ptr_on_device();
+
+      ind.team_barrier();
+
+      for( int i = 0; i<SHARED_TEAM_COUNT; i++) {
+        if(scratch_A[i] != size_t(i + ind.league_rank()))
+          ++update;
+      }
+      for( int i = 0; i < ind.team_size(); i++) {
+        if(scratch_ptr[0]!=scratch_ptr[i]) ++update;
+      }
+      if(scratch_ptr[1+ind.team_size()] - scratch_ptr[0 + ind.team_size()] <
+         SHARED_THREAD_COUNT*sizeof(size_t))
+        ++update;
+      for( int i = 1; i < ind.team_size(); i++) {
+        if((scratch_ptr[i+ind.team_size()] - scratch_ptr[i-1+ind.team_size()]) !=
+           (scratch_ptr[1+ind.team_size()] - scratch_ptr[0 + ind.team_size()])) ++update;
+
+      }
+    }
+  }
+};
+
+}
+
+namespace {
+
+template< class ExecSpace, class ScheduleType >
+struct TestScratchTeam {
+
+  TestScratchTeam()
+  { run(); }
+
+  void run()
+  {
+    typedef Test::ScratchTeamFunctor<ExecSpace, ScheduleType> Functor ;
+    typedef Kokkos::View< typename Functor::value_type , Kokkos::HostSpace , Kokkos::MemoryUnmanaged >  result_type ;
+
+    const size_t team_size = Kokkos::TeamPolicy< ScheduleType,  ExecSpace >::team_size_max( Functor() );
+
+    Kokkos::TeamPolicy< ScheduleType,  ExecSpace > team_exec( 8192 / team_size , team_size );
+
+    typename Functor::value_type error_count = 0 ;
+
+    int team_scratch_size   = Functor::shared_int_array_type::shmem_size(Functor::SHARED_TEAM_COUNT) +
+                              Functor::shared_int_array_type::shmem_size(2*team_size);
+    int thread_scratch_size = Functor::shared_int_array_type::shmem_size(Functor::SHARED_THREAD_COUNT);
+    Kokkos::parallel_reduce( team_exec.set_scratch_size(0,Kokkos::PerTeam(team_scratch_size),
+                                                          Kokkos::PerThread(thread_scratch_size)) ,
+                             Functor() , result_type( & error_count ) );
+
+    ASSERT_EQ( error_count , 0 );
+  }
+};
+}
+
+namespace Test {
+template< class ExecSpace>
+KOKKOS_INLINE_FUNCTION
+int test_team_mulit_level_scratch_loop_body(const typename Kokkos::TeamPolicy<ExecSpace>::member_type& team) {
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> a_team1(team.team_scratch(0),128);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> a_thread1(team.thread_scratch(0),16);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> a_team2(team.team_scratch(0),128);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> a_thread2(team.thread_scratch(0),16);
+
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> b_team1(team.team_scratch(1),128000);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> b_thread1(team.thread_scratch(1),16000);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> b_team2(team.team_scratch(1),128000);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> b_thread2(team.thread_scratch(1),16000);
+
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> a_team3(team.team_scratch(0),128);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> a_thread3(team.thread_scratch(0),16);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> b_team3(team.team_scratch(1),128000);
+      Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>> b_thread3(team.thread_scratch(1),16000);
+
+
+      Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,128), [&] (const int& i) {
+        a_team1(i) = 1000000 + i;
+        a_team2(i) = 2000000 + i;
+        a_team3(i) = 3000000 + i;
+      });
+      team.team_barrier();
+      Kokkos::parallel_for(Kokkos::ThreadVectorRange(team,16), [&] (const int& i){
+        a_thread1(i) = 1000000 + 100000*team.team_rank() + 16-i;
+        a_thread2(i) = 2000000 + 100000*team.team_rank() + 16-i;
+        a_thread3(i) = 3000000 + 100000*team.team_rank() + 16-i;
+      });
+
+      Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,128000), [&] (const int& i) {
+        b_team1(i) = 1000000 + i;
+        b_team2(i) = 2000000 + i;
+        b_team3(i) = 3000000 + i;
+      });
+      team.team_barrier();
+      Kokkos::parallel_for(Kokkos::ThreadVectorRange(team,16000), [&] (const int& i){
+        b_thread1(i) = 1000000 + 100000*team.team_rank() + 16-i;
+        b_thread2(i) = 2000000 + 100000*team.team_rank() + 16-i;
+        b_thread3(i) = 3000000 + 100000*team.team_rank() + 16-i;
+      });
+
+      team.team_barrier();
+      int error = 0;
+      Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,128), [&] (const int& i) {
+        if(a_team1(i) != 1000000 + i) error++;
+        if(a_team2(i) != 2000000 + i) error++;
+        if(a_team3(i) != 3000000 + i) error++;
+      });
+      team.team_barrier();
+      Kokkos::parallel_for(Kokkos::ThreadVectorRange(team,16), [&] (const int& i){
+        if(a_thread1(i) != 1000000 + 100000*team.team_rank() + 16-i) error++;
+        if(a_thread2(i) != 2000000 + 100000*team.team_rank() + 16-i) error++;
+        if(a_thread3(i) != 3000000 + 100000*team.team_rank() + 16-i) error++;
+      });
+
+      Kokkos::parallel_for(Kokkos::TeamThreadRange(team,0,128000), [&] (const int& i) {
+        if(b_team1(i) != 1000000 + i) error++;
+        if(b_team2(i) != 2000000 + i) error++;
+        if(b_team3(i) != 3000000 + i) error++;
+      });
+      team.team_barrier();
+      Kokkos::parallel_for(Kokkos::ThreadVectorRange(team,16000), [&] (const int& i){
+        if(b_thread1(i) != 1000000 + 100000*team.team_rank() + 16-i) error++;
+        if(b_thread2(i) != 2000000 + 100000*team.team_rank() + 16-i) error++;
+        if( b_thread3(i) != 3000000 + 100000*team.team_rank() + 16-i) error++;
+      });
+
+  return error;
+}
+
+
+struct TagReduce {};
+struct TagFor {};
+
+template< class ExecSpace, class ScheduleType >
+struct ClassNoShmemSizeFunction {
+  Kokkos::View<int,ExecSpace,Kokkos::MemoryTraits<Kokkos::Atomic> > errors;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const TagFor&, const typename Kokkos::TeamPolicy<ExecSpace,ScheduleType>::member_type& team) const {
+    int error = test_team_mulit_level_scratch_loop_body<ExecSpace>(team);
+    errors() += error;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const TagReduce&, const typename Kokkos::TeamPolicy<ExecSpace,ScheduleType>::member_type& team, int& error) const {
+    error += test_team_mulit_level_scratch_loop_body<ExecSpace>(team);
+  }
+
+  void run() {
+    Kokkos::View<int,ExecSpace> d_errors = Kokkos::View<int,ExecSpace>("Errors");
+    errors = d_errors;
+
+    const int per_team0 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(128);
+    const int per_thread0 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(16);
+
+    const int per_team1 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(128000);
+    const int per_thread1 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(16000);
+    {
+    Kokkos::TeamPolicy<TagFor,ExecSpace,ScheduleType> policy(10,8,16);
+    Kokkos::parallel_for(policy.set_scratch_size(0,Kokkos::PerTeam(per_team0),Kokkos::PerThread(per_thread0)).set_scratch_size(1,Kokkos::PerTeam(per_team1),Kokkos::PerThread(per_thread1)),
+      *this);
+    Kokkos::fence();
+    typename Kokkos::View<int,ExecSpace>::HostMirror h_errors = Kokkos::create_mirror_view(d_errors);
+    Kokkos::deep_copy(h_errors,d_errors);
+    ASSERT_EQ(h_errors(),0);
+    }
+
+    {
+    int error = 0;
+    Kokkos::TeamPolicy<TagReduce,ExecSpace,ScheduleType> policy(10,8,16);
+    Kokkos::parallel_reduce(policy.set_scratch_size(0,Kokkos::PerTeam(per_team0),Kokkos::PerThread(per_thread0)).set_scratch_size(1,Kokkos::PerTeam(per_team1),Kokkos::PerThread(per_thread1)),
+      *this,error);
+    Kokkos::fence();
+    ASSERT_EQ(error,0);
+    }
+  };
+};
+
+template< class ExecSpace, class ScheduleType >
+struct ClassWithShmemSizeFunction {
+  Kokkos::View<int,ExecSpace,Kokkos::MemoryTraits<Kokkos::Atomic> > errors;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const TagFor&, const typename Kokkos::TeamPolicy<ExecSpace,ScheduleType>::member_type& team) const {
+    int error = test_team_mulit_level_scratch_loop_body<ExecSpace>(team);
+    errors() += error;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const TagReduce&, const typename Kokkos::TeamPolicy<ExecSpace,ScheduleType>::member_type& team, int& error) const {
+    error += test_team_mulit_level_scratch_loop_body<ExecSpace>(team);
+  }
+
+  void run() {
+    Kokkos::View<int,ExecSpace> d_errors = Kokkos::View<int,ExecSpace>("Errors");
+    errors = d_errors;
+
+    const int per_team1 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(128000);
+    const int per_thread1 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(16000);
+    {
+    Kokkos::TeamPolicy<TagFor,ExecSpace,ScheduleType> policy(10,8,16);
+    Kokkos::parallel_for(policy.set_scratch_size(1,Kokkos::PerTeam(per_team1),Kokkos::PerThread(per_thread1)),
+      *this);
+    Kokkos::fence();
+    typename Kokkos::View<int,ExecSpace>::HostMirror h_errors= Kokkos::create_mirror_view(d_errors);
+    Kokkos::deep_copy(h_errors,d_errors);
+    ASSERT_EQ(h_errors(),0);
+    }
+
+    {
+    int error = 0;
+    Kokkos::TeamPolicy<TagReduce,ExecSpace,ScheduleType> policy(10,8,16);
+    Kokkos::parallel_reduce(policy.set_scratch_size(1,Kokkos::PerTeam(per_team1),Kokkos::PerThread(per_thread1)),
+      *this,error);
+    Kokkos::fence();
+    ASSERT_EQ(error,0);
+    }
+  };
+
+  unsigned team_shmem_size(int team_size) const {
+    const int per_team0 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(128);
+    const int per_thread0 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(16);
+    return per_team0 + team_size * per_thread0;
+  }
+};
+
+template< class ExecSpace, class ScheduleType >
+void test_team_mulit_level_scratch_test_lambda() {
+#ifdef KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA
+  Kokkos::View<int,ExecSpace,Kokkos::MemoryTraits<Kokkos::Atomic> > errors;
+  Kokkos::View<int,ExecSpace> d_errors("Errors");
+  errors = d_errors;
+
+  const int per_team0 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(128);
+  const int per_thread0 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(16);
+
+  const int per_team1 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(128000);
+  const int per_thread1 = 3*Kokkos::View<double*,ExecSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>::shmem_size(16000);
+
+  Kokkos::TeamPolicy<ExecSpace,ScheduleType> policy(10,8,16);
+  Kokkos::parallel_for(policy.set_scratch_size(0,Kokkos::PerTeam(per_team0),Kokkos::PerThread(per_thread0)).set_scratch_size(1,Kokkos::PerTeam(per_team1),Kokkos::PerThread(per_thread1)),
+    KOKKOS_LAMBDA(const typename Kokkos::TeamPolicy<ExecSpace>::member_type& team) {
+    int error = test_team_mulit_level_scratch_loop_body<ExecSpace>(team);
+    errors() += error;
+  });
+  Kokkos::fence();
+  typename Kokkos::View<int,ExecSpace>::HostMirror h_errors= Kokkos::create_mirror_view(errors);
+  Kokkos::deep_copy(h_errors,d_errors);
+  ASSERT_EQ(h_errors(),0);
+
+  int error = 0;
+  Kokkos::parallel_reduce(policy.set_scratch_size(0,Kokkos::PerTeam(per_team0),Kokkos::PerThread(per_thread0)).set_scratch_size(1,Kokkos::PerTeam(per_team1),Kokkos::PerThread(per_thread1)),
+    KOKKOS_LAMBDA(const typename Kokkos::TeamPolicy<ExecSpace>::member_type& team, int& count) {
+      count += test_team_mulit_level_scratch_loop_body<ExecSpace>(team);
+  },error);
+  ASSERT_EQ(error,0);
+  Kokkos::fence();
+#endif
+}
+
+
+}
+
+namespace {
+template< class ExecSpace, class ScheduleType >
+struct TestMultiLevelScratchTeam {
+
+  TestMultiLevelScratchTeam()
+  { run(); }
+
+  void run()
+  {
+#ifdef KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA
+    Test::test_team_mulit_level_scratch_test_lambda<ExecSpace, ScheduleType>();
+#endif
+    Test::ClassNoShmemSizeFunction<ExecSpace, ScheduleType> c1;
+    c1.run();
+
+    Test::ClassWithShmemSizeFunction<ExecSpace, ScheduleType> c2;
+    c2.run();
+
+  }
+};
+}
+
+namespace Test {
+
+template< class ExecSpace >
+struct TestShmemSize {
+
+  TestShmemSize() { run(); }
+
+  void run()
+  {
+    typedef Kokkos::View< long***, ExecSpace > view_type;
+
+    size_t d1 = 5;
+    size_t d2 = 6;
+    size_t d3 = 7;
+
+    size_t size = view_type::shmem_size( d1, d2, d3 );
+
+    ASSERT_EQ( size, d1 * d2 * d3 * sizeof(long) );
+  }
+};
+}
+
+/*--------------------------------------------------------------------------*/
diff --git a/lib/kokkos/core/unit_test/TestTeamVector.hpp b/lib/kokkos/core/unit_test/TestTeamVector.hpp
new file mode 100644
index 0000000000..48187f0368
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestTeamVector.hpp
@@ -0,0 +1,646 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#include <impl/Kokkos_Timer.hpp>
+#include <iostream>
+#include <cstdlib>
+
+namespace TestTeamVector {
+
+struct my_complex {
+  double re,im;
+  int dummy;
+  KOKKOS_INLINE_FUNCTION
+  my_complex() {
+    re = 0.0;
+    im = 0.0;
+    dummy = 0;
+  }
+  KOKKOS_INLINE_FUNCTION
+  my_complex(const my_complex& src) {
+    re = src.re;
+    im = src.im;
+    dummy = src.dummy;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  my_complex(const volatile my_complex& src) {
+    re = src.re;
+    im = src.im;
+    dummy = src.dummy;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  my_complex(const double& val) {
+    re = val;
+    im = 0.0;
+    dummy = 0;
+  }
+  KOKKOS_INLINE_FUNCTION
+  my_complex& operator += (const my_complex& src) {
+    re += src.re;
+    im += src.im;
+    dummy += src.dummy;
+    return *this;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator += (const volatile my_complex& src) volatile {
+    re += src.re;
+    im += src.im;
+    dummy += src.dummy;
+  }
+  KOKKOS_INLINE_FUNCTION
+  my_complex& operator *= (const my_complex& src) {
+    double re_tmp = re*src.re - im*src.im;
+    double im_tmp = re * src.im + im * src.re;
+    re = re_tmp;
+    im = im_tmp;
+    dummy *= src.dummy;
+    return *this;
+  }
+  KOKKOS_INLINE_FUNCTION
+  void operator *= (const volatile my_complex& src) volatile {
+    double re_tmp = re*src.re - im*src.im;
+    double im_tmp = re * src.im + im * src.re;
+    re = re_tmp;
+    im = im_tmp;
+    dummy *= src.dummy;
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator == (const my_complex& src) {
+    return (re == src.re) && (im == src.im) && ( dummy == src.dummy );
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator != (const my_complex& src) {
+      return (re != src.re) || (im != src.im) || ( dummy != src.dummy );
+  }
+  KOKKOS_INLINE_FUNCTION
+  bool operator != (const double& val) {
+    return (re != val) ||
+           (im != 0) || (dummy != 0);
+  }
+  KOKKOS_INLINE_FUNCTION
+  my_complex& operator= (const int& val) {
+    re = val;
+    im = 0.0;
+    dummy = 0;
+    return *this;
+  }
+  KOKKOS_INLINE_FUNCTION
+  my_complex& operator= (const double& val) {
+    re = val;
+    im = 0.0;
+    dummy = 0;
+    return *this;
+  }
+  KOKKOS_INLINE_FUNCTION
+  operator double() {
+    return re;
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_team_for {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_team_for(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  unsigned team_shmem_size(int team_size) const {return team_size*13*sizeof(Scalar)+8;}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+
+    typedef typename ExecutionSpace::scratch_memory_space shmem_space ;
+    typedef Kokkos::View<Scalar*,shmem_space,Kokkos::MemoryUnmanaged> shared_int;
+    typedef typename shared_int::size_type size_type;
+
+    const size_type shmemSize = team.team_size () * 13;
+    shared_int values = shared_int (team.team_shmem (), shmemSize);
+
+    if (values.ptr_on_device () == NULL || values.dimension_0 () < shmemSize) {
+      printf ("FAILED to allocate shared memory of size %u\n",
+              static_cast<unsigned int> (shmemSize));
+    }
+    else {
+
+      // Initialize shared memory
+      values(team.team_rank ()) = 0;
+
+      // Accumulate value into per thread shared memory
+      // This is non blocking
+      Kokkos::parallel_for(Kokkos::TeamThreadRange(team,131),[&] (int i) {
+        values(team.team_rank ()) += i - team.league_rank () + team.league_size () + team.team_size ();
+      });
+      // Wait for all memory to be written
+      team.team_barrier ();
+      // One thread per team executes the comparison
+      Kokkos::single(Kokkos::PerTeam(team),[&]() {
+            Scalar test = 0;
+            Scalar value = 0;
+            for (int i = 0; i < 131; ++i) {
+              test += i - team.league_rank () + team.league_size () + team.team_size ();
+            }
+            for (int i = 0; i < team.team_size (); ++i) {
+              value += values(i);
+            }
+            if (test != value) {
+              printf ("FAILED team_parallel_for %i %i %f %f\n",
+                      team.league_rank (), team.team_rank (),
+                      static_cast<double> (test), static_cast<double> (value));
+              flag() = 1;
+            }
+      });
+    }
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_team_reduce {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_team_reduce(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  unsigned team_shmem_size(int team_size) const {return team_size*13*sizeof(Scalar)+8;}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+
+    Scalar value = Scalar();
+    Kokkos::parallel_reduce(Kokkos::TeamThreadRange(team,131),[&] (int i, Scalar& val) {
+      val += i - team.league_rank () + team.league_size () + team.team_size ();
+    },value);
+
+    team.team_barrier ();
+    Kokkos::single(Kokkos::PerTeam(team),[&]() {
+         Scalar test = 0;
+         for (int i = 0; i < 131; ++i) {
+           test += i - team.league_rank () + team.league_size () + team.team_size ();
+         }
+         if (test != value) {
+           if(team.league_rank() == 0)
+           printf ("FAILED team_parallel_reduce %i %i %f %f %lu\n",
+             team.league_rank (), team.team_rank (),
+             static_cast<double> (test), static_cast<double> (value),sizeof(Scalar));
+              flag() = 1;
+         }
+    });
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_team_reduce_join {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_team_reduce_join(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  unsigned team_shmem_size(int team_size) const {return team_size*13*sizeof(Scalar)+8;}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+
+    Scalar value = 0;
+
+    Kokkos::parallel_reduce(Kokkos::TeamThreadRange(team,131)
+      , [&] (int i, Scalar& val) {
+        val += i - team.league_rank () + team.league_size () + team.team_size ();
+      }
+      , [&] (volatile Scalar& val, const volatile Scalar& src) {val+=src;}
+      , value
+    );
+
+    team.team_barrier ();
+    Kokkos::single(Kokkos::PerTeam(team),[&]() {
+         Scalar test = 0;
+         for (int i = 0; i < 131; ++i) {
+           test += i - team.league_rank () + team.league_size () + team.team_size ();
+         }
+         if (test != value) {
+           printf ("FAILED team_vector_parallel_reduce_join %i %i %f %f\n",
+             team.league_rank (), team.team_rank (),
+             static_cast<double> (test), static_cast<double> (value));
+              flag() = 1;
+         }
+    });
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_team_vector_for {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_team_vector_for(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  unsigned team_shmem_size(int team_size) const {return team_size*13*sizeof(Scalar)+8;}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+
+    typedef typename ExecutionSpace::scratch_memory_space shmem_space ;
+    typedef Kokkos::View<Scalar*,shmem_space,Kokkos::MemoryUnmanaged> shared_int;
+    typedef typename shared_int::size_type size_type;
+
+    const size_type shmemSize = team.team_size () * 13;
+    shared_int values = shared_int (team.team_shmem (), shmemSize);
+
+    if (values.ptr_on_device () == NULL || values.dimension_0 () < shmemSize) {
+      printf ("FAILED to allocate shared memory of size %u\n",
+              static_cast<unsigned int> (shmemSize));
+    }
+    else {
+      Kokkos::single(Kokkos::PerThread(team),[&] () {
+        values(team.team_rank ()) = 0;
+      });
+
+      Kokkos::parallel_for(Kokkos::TeamThreadRange(team,131),[&] (int i) {
+        Kokkos::single(Kokkos::PerThread(team),[&] () {
+          values(team.team_rank ()) += i - team.league_rank () + team.league_size () + team.team_size ();
+        });
+      });
+
+      team.team_barrier ();
+      Kokkos::single(Kokkos::PerTeam(team),[&]() {
+        Scalar test = 0;
+        Scalar value = 0;
+        for (int i = 0; i < 131; ++i) {
+          test += i - team.league_rank () + team.league_size () + team.team_size ();
+        }
+        for (int i = 0; i < team.team_size (); ++i) {
+          value += values(i);
+        }
+        if (test != value) {
+          printf ("FAILED team_vector_parallel_for %i %i %f %f\n",
+                  team.league_rank (), team.team_rank (),
+                  static_cast<double> (test), static_cast<double> (value));
+          flag() = 1;
+        }
+      });
+    }
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_team_vector_reduce {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_team_vector_reduce(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  unsigned team_shmem_size(int team_size) const {return team_size*13*sizeof(Scalar)+8;}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+
+    Scalar value = Scalar();
+    Kokkos::parallel_reduce(Kokkos::TeamThreadRange(team,131),[&] (int i, Scalar& val) {
+        val += i - team.league_rank () + team.league_size () + team.team_size ();
+    },value);
+
+    team.team_barrier ();
+    Kokkos::single(Kokkos::PerTeam(team),[&]() {
+      Scalar test = 0;
+      for (int i = 0; i < 131; ++i) {
+        test += i - team.league_rank () + team.league_size () + team.team_size ();
+      }
+      if (test != value) {
+        if(team.league_rank() == 0)
+        printf ("FAILED team_vector_parallel_reduce %i %i %f %f %lu\n",
+          team.league_rank (), team.team_rank (),
+          static_cast<double> (test), static_cast<double> (value),sizeof(Scalar));
+           flag() = 1;
+      }
+    });
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_team_vector_reduce_join {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_team_vector_reduce_join(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  unsigned team_shmem_size(int team_size) const {return team_size*13*sizeof(Scalar)+8;}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+
+    Scalar value = 0;
+    Kokkos::parallel_reduce(Kokkos::TeamThreadRange(team,131)
+      , [&] (int i, Scalar& val) {
+        val += i - team.league_rank () + team.league_size () + team.team_size ();
+      }
+      , [&] (volatile Scalar& val, const volatile Scalar& src) {val+=src;}
+      , value
+    );
+
+    team.team_barrier ();
+    Kokkos::single(Kokkos::PerTeam(team),[&]() {
+      Scalar test = 0;
+      for (int i = 0; i < 131; ++i) {
+         test += i - team.league_rank () + team.league_size () + team.team_size ();
+      }
+      if (test != value) {
+        printf ("FAILED team_vector_parallel_reduce_join %i %i %f %f\n",
+          team.league_rank (), team.team_rank (),
+          static_cast<double> (test), static_cast<double> (value));
+        flag() = 1;
+      }
+    });
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_vec_single {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_vec_single(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+
+    // Warning: this test case intentionally violates permissable semantics
+    // It is not valid to get references to members of the enclosing region
+    // inside a parallel_for and write to it.
+    Scalar value = 0;
+
+    Kokkos::parallel_for(Kokkos::ThreadVectorRange(team,13),[&] (int i) {
+      value = i; // This write is violating Kokkos semantics for nested parallelism
+    });
+
+    Kokkos::single(Kokkos::PerThread(team),[&] (Scalar& val) {
+      val = 1;
+    },value);
+
+    Scalar value2 = 0;
+    Kokkos::parallel_reduce(Kokkos::ThreadVectorRange(team,13), [&] (int i, Scalar& val) {
+      val += value;
+    },value2);
+
+    if(value2!=(value*13)) {
+      printf("FAILED vector_single broadcast %i %i %f %f\n",team.league_rank(),team.team_rank(),(double) value2,(double) value);
+      flag()=1;
+    }
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_vec_for {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_vec_for(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  unsigned team_shmem_size(int team_size) const {return team_size*13*sizeof(Scalar)+8;}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+
+    typedef typename ExecutionSpace::scratch_memory_space shmem_space ;
+    typedef Kokkos::View<Scalar*,shmem_space,Kokkos::MemoryUnmanaged> shared_int;
+    shared_int values = shared_int(team.team_shmem(),team.team_size()*13);
+
+    if (values.ptr_on_device () == NULL ||
+        values.dimension_0() < (unsigned) team.team_size() * 13) {
+      printf ("FAILED to allocate memory of size %i\n",
+              static_cast<int> (team.team_size () * 13));
+      flag() = 1;
+    }
+    else {
+      Kokkos::parallel_for(Kokkos::ThreadVectorRange(team,13), [&] (int i) {
+        values(13*team.team_rank() + i) = i - team.team_rank() - team.league_rank() + team.league_size() + team.team_size();
+      });
+
+      Kokkos::single(Kokkos::PerThread(team),[&] () {
+        Scalar test = 0;
+        Scalar value = 0;
+        for (int i = 0; i < 13; ++i) {
+          test += i - team.team_rank() - team.league_rank() + team.league_size() + team.team_size();
+          value += values(13*team.team_rank() + i);
+        }
+        if (test != value) {
+          printf ("FAILED vector_par_for %i %i %f %f\n",
+                  team.league_rank (), team.team_rank (),
+                  static_cast<double> (test), static_cast<double> (value));
+          flag() = 1;
+        }
+      });
+    }
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_vec_red {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_vec_red(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+    Scalar value = 0;
+
+    Kokkos::parallel_reduce(Kokkos::ThreadVectorRange(team,13),[&] (int i, Scalar& val) {
+      val += i;
+    }, value);
+
+    Kokkos::single(Kokkos::PerThread(team),[&] () {
+      Scalar test = 0;
+      for(int i = 0; i < 13; i++) {
+        test+=i;
+      }
+      if(test!=value) {
+        printf("FAILED vector_par_reduce %i %i %f %f\n",team.league_rank(),team.team_rank(),(double) test,(double) value);
+        flag()=1;
+      }
+    });
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_vec_red_join {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_vec_red_join(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+    Scalar value = 1;
+
+    Kokkos::parallel_reduce(Kokkos::ThreadVectorRange(team,13)
+      , [&] (int i, Scalar& val) { val *= i; }
+      , [&] (Scalar& val, const Scalar& src) {val*=src;}
+      , value
+    );
+
+    Kokkos::single(Kokkos::PerThread(team),[&] () {
+      Scalar test = 1;
+      for(int i = 0; i < 13; i++) {
+        test*=i;
+      }
+      if(test!=value) {
+        printf("FAILED vector_par_reduce_join %i %i %f %f\n",team.league_rank(),team.team_rank(),(double) test,(double) value);
+        flag()=1;
+      }
+    });
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_vec_scan {
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_vec_scan(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team) const {
+    Kokkos::parallel_scan(Kokkos::ThreadVectorRange(team,13),[&] (int i, Scalar& val, bool final) {
+      val += i;
+      if(final) {
+        Scalar test = 0;
+        for(int k = 0; k <= i; k++) {
+          test+=k;
+        }
+        if(test!=val) {
+          printf("FAILED vector_par_scan %i %i %f %f\n",team.league_rank(),team.team_rank(),(double) test,(double) val);
+          flag()=1;
+        }
+      }
+    });
+  }
+};
+
+template<typename Scalar, class ExecutionSpace>
+struct functor_reduce {
+  typedef double value_type;
+  typedef Kokkos::TeamPolicy<ExecutionSpace> policy_type;
+  typedef ExecutionSpace execution_space;
+
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag;
+  functor_reduce(Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> flag_):flag(flag_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename policy_type::member_type team, double& sum) const {
+    sum += team.league_rank() * 100 + team.thread_rank();
+  }
+};
+
+template<typename Scalar,class ExecutionSpace>
+bool test_scalar(int nteams, int team_size, int test) {
+  Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace> d_flag("flag");
+  typename Kokkos::View<int,Kokkos::LayoutLeft,ExecutionSpace>::HostMirror h_flag("h_flag");
+  h_flag() = 0 ;
+  Kokkos::deep_copy(d_flag,h_flag);
+  
+  if(test==0)
+  Kokkos::parallel_for( std::string("A") , Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size,8),
+      functor_vec_red<Scalar, ExecutionSpace>(d_flag));
+  if(test==1)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size,8),
+      functor_vec_red_join<Scalar, ExecutionSpace>(d_flag));
+  if(test==2)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size,8),
+      functor_vec_scan<Scalar, ExecutionSpace>(d_flag));
+  if(test==3)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size,8),
+      functor_vec_for<Scalar, ExecutionSpace>(d_flag));
+  if(test==4)
+  Kokkos::parallel_for( "B" , Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size,8),
+      functor_vec_single<Scalar, ExecutionSpace>(d_flag));
+  if(test==5)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size),
+      functor_team_for<Scalar, ExecutionSpace>(d_flag));
+  if(test==6)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size),
+      functor_team_reduce<Scalar, ExecutionSpace>(d_flag));
+  if(test==7)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size),
+      functor_team_reduce_join<Scalar, ExecutionSpace>(d_flag));
+  if(test==8)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size,8),
+      functor_team_vector_for<Scalar, ExecutionSpace>(d_flag));
+  if(test==9)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size,8),
+      functor_team_vector_reduce<Scalar, ExecutionSpace>(d_flag));
+  if(test==10)
+  Kokkos::parallel_for( Kokkos::TeamPolicy<ExecutionSpace>(nteams,team_size,8),
+      functor_team_vector_reduce_join<Scalar, ExecutionSpace>(d_flag));
+  
+  Kokkos::deep_copy(h_flag,d_flag);
+
+  return (h_flag() == 0);
+}
+
+template<class ExecutionSpace>
+bool Test(int test) {
+  bool passed = true;
+  passed = passed && test_scalar<int, ExecutionSpace>(317,33,test);
+  passed = passed && test_scalar<long long int, ExecutionSpace>(317,33,test);
+  passed = passed && test_scalar<float, ExecutionSpace>(317,33,test);
+  passed = passed && test_scalar<double, ExecutionSpace>(317,33,test);
+  passed = passed && test_scalar<my_complex, ExecutionSpace>(317,33,test);
+  return passed;
+}
+
+}
+
diff --git a/lib/kokkos/core/unit_test/TestTemplateMetaFunctions.hpp b/lib/kokkos/core/unit_test/TestTemplateMetaFunctions.hpp
new file mode 100644
index 0000000000..4f136bc64b
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestTemplateMetaFunctions.hpp
@@ -0,0 +1,219 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#define KOKKOS_PRAGMA_UNROLL(a)
+
+namespace {
+
+template<class Scalar, class ExecutionSpace>
+struct SumPlain {
+  typedef ExecutionSpace execution_space;
+  typedef typename Kokkos::View<Scalar*,execution_space> type;
+  type view;
+  SumPlain(type view_):view(view_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, Scalar& val) {
+    val += Scalar();
+  }
+};
+
+template<class Scalar, class ExecutionSpace>
+struct SumInitJoinFinalValueType {
+  typedef ExecutionSpace execution_space;
+  typedef typename Kokkos::View<Scalar*,execution_space> type;
+  type view;
+  typedef Scalar value_type;
+  SumInitJoinFinalValueType(type view_):view(view_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void init(value_type& val) const {
+    val = value_type();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& val, volatile value_type& src) const {
+    val += src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, value_type& val) const {
+    val += value_type();
+  }
+
+};
+
+template<class Scalar, class ExecutionSpace>
+struct SumInitJoinFinalValueType2 {
+  typedef ExecutionSpace execution_space;
+  typedef typename Kokkos::View<Scalar*,execution_space> type;
+  type view;
+  typedef Scalar value_type;
+  SumInitJoinFinalValueType2(type view_):view(view_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void init(volatile value_type& val) const {
+    val = value_type();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& val, const volatile value_type& src) const {
+    val += src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, value_type& val) const {
+    val += value_type();
+  }
+
+};
+
+template<class Scalar, class ExecutionSpace>
+struct SumInitJoinFinalValueTypeArray {
+  typedef ExecutionSpace execution_space;
+  typedef typename Kokkos::View<Scalar*,execution_space> type;
+  type view;
+  typedef Scalar value_type[];
+  int n;
+  SumInitJoinFinalValueTypeArray(type view_, int n_):view(view_),n(n_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void init(value_type val) const {
+    for(int k=0;k<n;k++)
+      val[k] = 0;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type val, const volatile value_type src) const {
+    for(int k=0;k<n;k++)
+      val[k] += src[k];
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, value_type val) const {
+    for(int k=0;k<n;k++)
+      val[k] += k*i;
+  }
+
+};
+
+template<class Scalar, class ExecutionSpace>
+struct SumWrongInitJoinFinalValueType {
+  typedef ExecutionSpace execution_space;
+  typedef typename Kokkos::View<Scalar*,execution_space> type;
+  type view;
+  typedef Scalar value_type;
+  SumWrongInitJoinFinalValueType(type view_):view(view_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void init(double& val) const {
+    val = double();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type& val, const value_type& src) const {
+    val += src;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, value_type& val) const {
+    val += value_type();
+  }
+
+};
+
+template<class Scalar, class ExecutionSpace>
+void TestTemplateMetaFunctions() {
+  typedef typename Kokkos::View<Scalar*,ExecutionSpace> type;
+  type a("A",100);
+/*  #ifdef KOKKOS_HAVE_CXX11
+  int sum_plain_has_init_arg = Kokkos::Impl::FunctorHasInit<SumPlain<Scalar,ExecutionSpace>, Scalar& >::value;
+  ASSERT_EQ(sum_plain_has_init_arg,0);
+  int sum_initjoinfinalvaluetype_has_init_arg = Kokkos::Impl::FunctorHasInit<SumInitJoinFinalValueType<Scalar,ExecutionSpace>, Scalar >::value;
+  ASSERT_EQ(sum_initjoinfinalvaluetype_has_init_arg,1);
+  int sum_initjoinfinalvaluetype_has_init_arg2 = Kokkos::Impl::FunctorHasInit<SumInitJoinFinalValueType2<Scalar,ExecutionSpace>, Scalar >::value;
+  ASSERT_EQ(sum_initjoinfinalvaluetype_has_init_arg2,1);
+  int sum_wronginitjoinfinalvaluetype_has_init_arg = Kokkos::Impl::FunctorHasInit<SumWrongInitJoinFinalValueType<Scalar,ExecutionSpace>, Scalar >::value;
+  ASSERT_EQ(sum_wronginitjoinfinalvaluetype_has_init_arg,0);
+
+  //int sum_initjoinfinalvaluetypearray_has_init_arg = Kokkos::Impl::FunctorHasInit<SumInitJoinFinalValueTypeArray<Scalar,ExecutionSpace>, Scalar[] >::value;
+  //ASSERT_EQ(sum_initjoinfinalvaluetypearray_has_init_arg,1);
+
+  #else
+
+  int sum_plain_has_init_arg = Kokkos::Impl::FunctorHasInit<SumPlain<Scalar,ExecutionSpace>, Scalar& >::value;
+  ASSERT_EQ(sum_plain_has_init_arg,0);
+  int sum_initjoinfinalvaluetype_has_init_arg = Kokkos::Impl::FunctorHasInit<SumInitJoinFinalValueType<Scalar,ExecutionSpace>, Scalar& >::value;
+  ASSERT_EQ(sum_initjoinfinalvaluetype_has_init_arg,1);
+  int sum_wronginitjoinfinalvaluetype_has_init_arg = Kokkos::Impl::FunctorHasInit<SumWrongInitJoinFinalValueType<Scalar,ExecutionSpace>, Scalar& >::value;
+  ASSERT_EQ(sum_wronginitjoinfinalvaluetype_has_init_arg,1);
+
+  #endif
+
+  //printf("Values Init: %i %i %i\n",sum_plain_has_init_arg,sum_initjoinfinalvaluetype_has_init_arg,sum_wronginitjoinfinalvaluetype_has_init_arg);
+
+#ifdef KOKKOS_HAVE_CXX11
+  int sum_plain_has_join_arg = Kokkos::Impl::FunctorHasJoin<SumPlain<Scalar,ExecutionSpace>, Scalar >::value;
+  ASSERT_EQ(sum_plain_has_join_arg,0);
+  int sum_initjoinfinalvaluetype_has_join_arg = Kokkos::Impl::FunctorHasJoin<SumInitJoinFinalValueType<Scalar,ExecutionSpace>, Scalar >::value;
+  ASSERT_EQ(sum_initjoinfinalvaluetype_has_join_arg,1);
+  int sum_initjoinfinalvaluetype_has_join_arg2 = Kokkos::Impl::FunctorHasJoin<SumInitJoinFinalValueType2<Scalar,ExecutionSpace>, Scalar >::value;
+  ASSERT_EQ(sum_initjoinfinalvaluetype_has_join_arg2,1);
+  int sum_wronginitjoinfinalvaluetype_has_join_arg = Kokkos::Impl::FunctorHasJoin<SumWrongInitJoinFinalValueType<Scalar,ExecutionSpace>, Scalar >::value;
+  ASSERT_EQ(sum_wronginitjoinfinalvaluetype_has_join_arg,0);
+#else
+  int sum_plain_has_join_arg = Kokkos::Impl::FunctorHasJoin<SumPlain<Scalar,ExecutionSpace>, Scalar& >::value;
+  ASSERT_EQ(sum_plain_has_join_arg,0);
+  int sum_initjoinfinalvaluetype_has_join_arg = Kokkos::Impl::FunctorHasJoin<SumInitJoinFinalValueType<Scalar,ExecutionSpace>, Scalar& >::value;
+  ASSERT_EQ(sum_initjoinfinalvaluetype_has_join_arg,1);
+  int sum_initjoinfinalvaluetype_has_join_arg2 = Kokkos::Impl::FunctorHasJoin<SumInitJoinFinalValueType2<Scalar,ExecutionSpace>, Scalar& >::value;
+  ASSERT_EQ(sum_initjoinfinalvaluetype_has_join_arg2,1);
+  int sum_wronginitjoinfinalvaluetype_has_join_arg = Kokkos::Impl::FunctorHasJoin<SumWrongInitJoinFinalValueType<Scalar,ExecutionSpace>, Scalar& >::value;
+  ASSERT_EQ(sum_wronginitjoinfinalvaluetype_has_join_arg,1);
+#endif*/
+  //printf("Values Join: %i %i %i\n",sum_plain_has_join_arg,sum_initjoinfinalvaluetype_has_join_arg,sum_wronginitjoinfinalvaluetype_has_join_arg);
+}
+
+}
diff --git a/lib/kokkos/core/unit_test/TestThreads.cpp b/lib/kokkos/core/unit_test/TestThreads.cpp
new file mode 100644
index 0000000000..93049b95dd
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestThreads.cpp
@@ -0,0 +1,614 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Macros.hpp>
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+#ifdef KOKKOS_LAMBDA
+#undef KOKKOS_LAMBDA
+#endif
+#define KOKKOS_LAMBDA [=]
+
+#include <Kokkos_Core.hpp>
+
+#include <Threads/Kokkos_Threads_TaskPolicy.hpp>
+
+//----------------------------------------------------------------------------
+
+#include <TestSharedAlloc.hpp>
+#include <TestViewMapping.hpp>
+
+#include <TestViewImpl.hpp>
+
+#include <TestViewAPI.hpp>
+#include <TestViewSubview.hpp>
+#include <TestViewOfClass.hpp>
+#include <TestAtomic.hpp>
+#include <TestAtomicOperations.hpp>
+
+#include <TestReduce.hpp>
+#include <TestScan.hpp>
+#include <TestRange.hpp>
+#include <TestTeam.hpp>
+#include <TestAggregate.hpp>
+#include <TestAggregateReduction.hpp>
+#include <TestCompilerMacros.hpp>
+#include <TestTaskPolicy.hpp>
+#include <TestMemoryPool.hpp>
+
+
+#include <TestCXX11.hpp>
+#include <TestCXX11Deduction.hpp>
+#include <TestTeamVector.hpp>
+#include <TestMemorySpaceTracking.hpp>
+#include <TestTemplateMetaFunctions.hpp>
+
+
+#include <TestPolicyConstruction.hpp>
+
+#include <TestMDRange.hpp>
+
+namespace Test {
+
+class threads : public ::testing::Test {
+protected:
+  static void SetUpTestCase()
+  {
+    // Finalize without initialize is a no-op:
+    Kokkos::Threads::finalize();
+
+    const unsigned numa_count       = Kokkos::hwloc::get_available_numa_count();
+    const unsigned cores_per_numa   = Kokkos::hwloc::get_available_cores_per_numa();
+    const unsigned threads_per_core = Kokkos::hwloc::get_available_threads_per_core();
+
+    unsigned threads_count = 0 ;
+
+    // Initialize and finalize with no threads:
+    Kokkos::Threads::initialize( 1u );
+    Kokkos::Threads::finalize();
+
+    threads_count = std::max( 1u , numa_count )
+                  * std::max( 2u , cores_per_numa * threads_per_core );
+
+    Kokkos::Threads::initialize( threads_count );
+    Kokkos::Threads::finalize();
+
+    threads_count = std::max( 1u , numa_count * 2 )
+                  * std::max( 2u , ( cores_per_numa * threads_per_core ) / 2 );
+
+    Kokkos::Threads::initialize( threads_count );
+    Kokkos::Threads::finalize();
+
+    // Quick attempt to verify thread start/terminate don't have race condition:
+    threads_count = std::max( 1u , numa_count )
+                  * std::max( 2u , ( cores_per_numa * threads_per_core ) / 2 );
+    for ( unsigned i = 0 ; i < 10 ; ++i ) {
+      Kokkos::Threads::initialize( threads_count );
+      Kokkos::Threads::sleep();
+      Kokkos::Threads::wake();
+      Kokkos::Threads::finalize();
+    }
+
+    Kokkos::Threads::initialize( threads_count );
+    Kokkos::Threads::print_configuration( std::cout , true /* detailed */ );
+  }
+
+  static void TearDownTestCase()
+  {
+    Kokkos::Threads::finalize();
+  }
+};
+
+TEST_F( threads , init ) {
+  ;
+}
+
+TEST_F( threads , md_range ) {
+  TestMDRange_2D< Kokkos::Threads >::test_for2(100,100);
+
+  TestMDRange_3D< Kokkos::Threads >::test_for3(100,100,100);
+}
+
+TEST_F( threads , dispatch )
+{
+  const int repeat = 100 ;
+  for ( int i = 0 ; i < repeat ; ++i ) {
+  for ( int j = 0 ; j < repeat ; ++j ) {
+    Kokkos::parallel_for( Kokkos::RangePolicy< Kokkos::Threads >(0,j)
+                        , KOKKOS_LAMBDA( int ) {} );
+  }}
+}
+
+TEST_F( threads , impl_shared_alloc ) {
+  test_shared_alloc< Kokkos::HostSpace , Kokkos::Threads >();
+}
+
+TEST_F( threads, policy_construction) {
+  TestRangePolicyConstruction< Kokkos::Threads >();
+  TestTeamPolicyConstruction< Kokkos::Threads >();
+}
+
+TEST_F( threads , impl_view_mapping ) {
+  test_view_mapping< Kokkos::Threads >();
+  test_view_mapping_subview< Kokkos::Threads >();
+  test_view_mapping_operator< Kokkos::Threads >();
+  TestViewMappingAtomic< Kokkos::Threads >::run();
+}
+
+
+TEST_F( threads, view_impl) {
+  test_view_impl< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_api) {
+  TestViewAPI< double , Kokkos::Threads >();
+}
+
+TEST_F( threads , view_nested_view )
+{
+  ::Test::view_nested_view< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_auto_1d_left ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutLeft,Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_auto_1d_right ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutRight,Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_auto_1d_stride ) {
+  TestViewSubview::test_auto_1d< Kokkos::LayoutStride,Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_assign_strided ) {
+  TestViewSubview::test_1d_strided_assignment< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_left_0 ) {
+  TestViewSubview::test_left_0< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_left_1 ) {
+  TestViewSubview::test_left_1< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_left_2 ) {
+  TestViewSubview::test_left_2< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_left_3 ) {
+  TestViewSubview::test_left_3< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_right_0 ) {
+  TestViewSubview::test_right_0< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_right_1 ) {
+  TestViewSubview::test_right_1< Kokkos::Threads >();
+}
+
+TEST_F( threads, view_subview_right_3 ) {
+  TestViewSubview::test_right_3< Kokkos::Threads >();
+}
+
+
+TEST_F( threads, view_aggregate ) {
+  TestViewAggregate< Kokkos::Threads >();
+  TestViewAggregateReduction< Kokkos::Threads >();
+}
+
+TEST_F( threads , range_tag )
+{
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_for(2);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_reduce(2);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_scan(2);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(3);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(3);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_scan(3);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_dynamic_policy(2);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_scan(1000);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(1001);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(1001);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_scan(1001);
+  TestRange< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_dynamic_policy(1000);
+}
+
+TEST_F( threads , team_tag )
+{
+  TestTeamPolicy< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_for(2);
+  TestTeamPolicy< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_reduce(2);
+  TestTeamPolicy< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(2);
+  TestTeamPolicy< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(2);
+  TestTeamPolicy< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_for(1000);
+  TestTeamPolicy< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >::test_reduce(1000);
+  TestTeamPolicy< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_for(1000);
+  TestTeamPolicy< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >::test_reduce(1000);
+}
+
+TEST_F( threads, long_reduce) {
+  TestReduce< long ,   Kokkos::Threads >( 1000000 );
+}
+
+TEST_F( threads, double_reduce) {
+  TestReduce< double ,   Kokkos::Threads >( 1000000 );
+}
+
+TEST_F( threads , reducers )
+{
+  TestReducers<int, Kokkos::Threads>::execute_integer();
+  TestReducers<size_t, Kokkos::Threads>::execute_integer();
+  TestReducers<double, Kokkos::Threads>::execute_float();
+  TestReducers<Kokkos::complex<double>, Kokkos::Threads>::execute_basic();
+}
+
+TEST_F( threads, team_long_reduce) {
+  TestReduceTeam< long ,   Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >( 3 );
+  TestReduceTeam< long ,   Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >( 3 );
+  TestReduceTeam< long ,   Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >( 100000 );
+  TestReduceTeam< long ,   Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >( 100000 );
+}
+
+TEST_F( threads, team_double_reduce) {
+  TestReduceTeam< double ,   Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >( 3 );
+  TestReduceTeam< double ,   Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >( 3 );
+  TestReduceTeam< double ,   Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >( 100000 );
+  TestReduceTeam< double ,   Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >( 100000 );
+}
+
+TEST_F( threads, long_reduce_dynamic ) {
+  TestReduceDynamic< long ,   Kokkos::Threads >( 1000000 );
+}
+
+TEST_F( threads, double_reduce_dynamic ) {
+  TestReduceDynamic< double ,   Kokkos::Threads >( 1000000 );
+}
+
+TEST_F( threads, long_reduce_dynamic_view ) {
+  TestReduceDynamicView< long ,   Kokkos::Threads >( 1000000 );
+}
+
+TEST_F( threads, team_shared_request) {
+  TestSharedTeam< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >();
+  TestSharedTeam< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+
+#if defined(KOKKOS_HAVE_CXX11_DISPATCH_LAMBDA)
+TEST_F( threads, team_lambda_shared_request) {
+  TestLambdaSharedTeam< Kokkos::HostSpace, Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >();
+  TestLambdaSharedTeam< Kokkos::HostSpace, Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >();
+}
+#endif
+
+TEST_F( threads, shmem_size) {
+  TestShmemSize< Kokkos::Threads >();
+}
+
+TEST_F( threads , view_remap )
+{
+  enum { N0 = 3 , N1 = 2 , N2 = 8 , N3 = 9 };
+
+  typedef Kokkos::View< double*[N1][N2][N3] ,
+                             Kokkos::LayoutRight ,
+                             Kokkos::Threads > output_type ;
+
+  typedef Kokkos::View< int**[N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::Threads > input_type ;
+
+  typedef Kokkos::View< int*[N0][N2][N3] ,
+                             Kokkos::LayoutLeft ,
+                             Kokkos::Threads > diff_type ;
+
+  output_type output( "output" , N0 );
+  input_type  input ( "input" , N0 , N1 );
+  diff_type   diff  ( "diff" , N0 );
+
+  int value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    input(i0,i1,i2,i3) = ++value ;
+  }}}}
+
+  // Kokkos::deep_copy( diff , input ); // throw with incompatible shape
+  Kokkos::deep_copy( output , input );
+
+  value = 0 ;
+  for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+  for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+  for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+  for ( size_t i0 = 0 ; i0 < N0 ; ++i0 ) {
+    ++value ;
+    ASSERT_EQ( value , ((int) output(i0,i1,i2,i3) ) );
+  }}}}
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( threads , atomics )
+{
+  const int loop_count = 1e6 ;
+
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Threads>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Threads>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<int,Kokkos::Threads>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Threads>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Threads>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned int,Kokkos::Threads>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Threads>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Threads>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long int,Kokkos::Threads>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Threads>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Threads>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<unsigned long int,Kokkos::Threads>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Threads>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Threads>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<long long int,Kokkos::Threads>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Threads>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Threads>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<double,Kokkos::Threads>(loop_count,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Threads>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Threads>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<float,Kokkos::Threads>(100,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Threads>(100,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Threads>(100,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<Kokkos::complex<double> ,Kokkos::Threads>(100,3) ) );
+
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<3>, Kokkos::Threads>(loop_count,1) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<3>, Kokkos::Threads>(loop_count,2) ) );
+  ASSERT_TRUE( ( TestAtomic::Loop<TestAtomic::SuperScalar<3>, Kokkos::Threads>(loop_count,3) ) );
+}
+
+TEST_F( threads , atomic_operations )
+{
+  const int start = 1; //Avoid zero for division
+  const int end = 11;
+  for (int i = start; i < end; ++i)
+  {
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<int,Kokkos::Threads>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned int,Kokkos::Threads>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long int,Kokkos::Threads>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<unsigned long int,Kokkos::Threads>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 4 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 5 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 6 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 7 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 8 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestIntegralType<long long int,Kokkos::Threads>(start, end-i, 9 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Threads>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Threads>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Threads>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<double,Kokkos::Threads>(start, end-i, 4 ) ) );
+
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Threads>(start, end-i, 1 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Threads>(start, end-i, 2 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Threads>(start, end-i, 3 ) ) );
+    ASSERT_TRUE( ( TestAtomicOperations::AtomicOperationsTestNonIntegralType<float,Kokkos::Threads>(start, end-i, 4 ) ) );
+  }
+
+}
+
+//----------------------------------------------------------------------------
+
+#if 0
+TEST_F( threads , scan_small )
+{
+  typedef TestScan< Kokkos::Threads , Kokkos::Impl::ThreadsExecUseScanSmall > TestScanFunctor ;
+  for ( int i = 0 ; i < 1000 ; ++i ) {
+    TestScanFunctor( 10 );
+    TestScanFunctor( 10000 );
+  }
+  TestScanFunctor( 1000000 );
+  TestScanFunctor( 10000000 );
+
+  Kokkos::Threads::fence();
+}
+#endif
+
+TEST_F( threads , scan )
+{
+  TestScan< Kokkos::Threads >::test_range( 1 , 1000 );
+  TestScan< Kokkos::Threads >( 1000000 );
+  TestScan< Kokkos::Threads >( 10000000 );
+  Kokkos::Threads::fence();
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( threads , team_scan )
+{
+  TestScanTeam< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >( 10 );
+  TestScanTeam< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >( 10 );
+  TestScanTeam< Kokkos::Threads , Kokkos::Schedule<Kokkos::Static> >( 10000 );
+  TestScanTeam< Kokkos::Threads , Kokkos::Schedule<Kokkos::Dynamic> >( 10000 );
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( threads , compiler_macros )
+{
+  ASSERT_TRUE( ( TestCompilerMacros::Test< Kokkos::Threads >() ) );
+}
+
+TEST_F( threads , memory_space )
+{
+  TestMemorySpace< Kokkos::Threads >();
+}
+
+TEST_F( threads , memory_pool )
+{
+  bool val = TestMemoryPool::test_mempool< Kokkos::Threads >( 128, 128000000 );
+  ASSERT_TRUE( val );
+
+  TestMemoryPool::test_mempool2< Kokkos::Threads >( 64, 4, 1000000, 2000000 );
+
+  TestMemoryPool::test_memory_exhaustion< Kokkos::Threads >();
+}
+
+//----------------------------------------------------------------------------
+
+TEST_F( threads , template_meta_functions )
+{
+  TestTemplateMetaFunctions<int, Kokkos::Threads >();
+}
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS )
+TEST_F( threads , cxx11 )
+{
+  if ( Kokkos::Impl::is_same< Kokkos::DefaultExecutionSpace , Kokkos::Threads >::value ) {
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::Threads >(1) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::Threads >(2) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::Threads >(3) ) );
+    ASSERT_TRUE( ( TestCXX11::Test< Kokkos::Threads >(4) ) );
+  }
+}
+
+TEST_F( threads , reduction_deduction )
+{
+  TestCXX11::test_reduction_deduction< Kokkos::Threads >();
+}
+#endif /* #if defined( KOKKOS_HAVE_DEFAULT_DEVICE_TYPE_THREADS ) */
+
+TEST_F( threads , team_vector )
+{
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(0) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(1) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(2) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(3) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(4) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(5) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(6) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(7) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(8) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(9) ) );
+  ASSERT_TRUE( ( TestTeamVector::Test< Kokkos::Threads >(10) ) );
+}
+
+#if defined( KOKKOS_ENABLE_TASKPOLICY )
+
+TEST_F( threads , task_policy )
+{
+  TestTaskPolicy::test_task_dep< Kokkos::Threads >( 10 );
+
+  for ( long i = 0 ; i < 25 ; ++i ) {
+//    printf( "test_fib():  %2ld\n", i );
+    TestTaskPolicy::test_fib< Kokkos::Threads >(i);
+  }
+  for ( long i = 0 ; i < 35 ; ++i ) {
+//    printf( "test_fib2(): %2ld\n", i );
+    TestTaskPolicy::test_fib2< Kokkos::Threads >(i);
+  }
+}
+
+TEST_F( threads , task_team )
+{
+  TestTaskPolicy::test_task_team< Kokkos::Threads >(1000);
+}
+
+TEST_F( threads , task_latch )
+{
+  TestTaskPolicy::test_latch< Kokkos::Threads >(10);
+  TestTaskPolicy::test_latch< Kokkos::Threads >(1000);
+}
+
+#endif /* #if defined( KOKKOS_ENABLE_TASKPOLICY ) */
+
+} // namespace Test
+
+#endif /* #if defined( KOKKOS_HAVE_PTHREAD ) */
diff --git a/lib/kokkos/core/unit_test/TestTile.hpp b/lib/kokkos/core/unit_test/TestTile.hpp
new file mode 100644
index 0000000000..dfb2bd81b3
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestTile.hpp
@@ -0,0 +1,153 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef TEST_TILE_HPP
+#define TEST_TILE_HPP
+
+#include <Kokkos_Core.hpp>
+
+namespace TestTile {
+
+template < typename Device , typename TileLayout>
+struct ReduceTileErrors
+{
+  typedef Device execution_space ;
+
+  typedef Kokkos::View< ptrdiff_t**, TileLayout, Device>  array_type;
+  typedef Kokkos::View< ptrdiff_t[ TileLayout::N0 ][ TileLayout::N1 ], Kokkos::LayoutLeft , Device >  tile_type ;
+
+  array_type m_array ;
+
+  typedef ptrdiff_t value_type;
+
+  ReduceTileErrors( array_type a )
+    : m_array(a)
+  {}
+
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & errors )
+  {
+    errors = 0;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & errors ,
+                    const volatile value_type & src_errors )
+  {
+    errors += src_errors;
+  }
+
+  // Initialize
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_t iwork ) const
+  {
+    const size_t i = iwork % m_array.dimension_0();
+    const size_t j = iwork / m_array.dimension_0();
+    if ( j < m_array.dimension_1() ) {
+      m_array(i,j) = & m_array(i,j) - & m_array(0,0);
+
+// printf("m_array(%d,%d) = %d\n",int(i),int(j),int(m_array(i,j)));
+
+    }
+  }
+
+  // Verify:
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_t iwork , value_type & errors ) const
+  {
+    const size_t tile_dim0 = ( m_array.dimension_0() + TileLayout::N0 - 1 ) / TileLayout::N0 ;
+    const size_t tile_dim1 = ( m_array.dimension_1() + TileLayout::N1 - 1 ) / TileLayout::N1 ;
+
+    const size_t itile = iwork % tile_dim0 ;
+    const size_t jtile = iwork / tile_dim0 ;
+
+    if ( jtile < tile_dim1 ) {
+
+      tile_type tile = Kokkos::tile_subview( m_array , itile , jtile );
+
+      if ( tile(0,0) != ptrdiff_t(( itile + jtile * tile_dim0 ) * TileLayout::N0 * TileLayout::N1 ) ) {
+        ++errors ;
+      }
+      else {
+
+        for ( size_t j = 0 ; j < size_t(TileLayout::N1) ; ++j ) {
+        for ( size_t i = 0 ; i < size_t(TileLayout::N0) ; ++i ) {
+          const size_t iglobal = i + itile * TileLayout::N0 ;
+          const size_t jglobal = j + jtile * TileLayout::N1 ;
+
+          if ( iglobal < m_array.dimension_0() && jglobal < m_array.dimension_1() ) {
+            if ( tile(i,j) != ptrdiff_t( tile(0,0) + i + j * TileLayout::N0 ) ) ++errors ;
+
+// printf("tile(%d,%d)(%d,%d) = %d\n",int(itile),int(jtile),int(i),int(j),int(tile(i,j)));
+
+          }
+        }
+        }
+      }
+    }
+  }
+};
+
+template< class Space , unsigned N0 , unsigned N1 >
+void test( const size_t dim0 , const size_t dim1 )
+{
+  typedef Kokkos::LayoutTileLeft<N0,N1>  array_layout ;
+  typedef ReduceTileErrors< Space , array_layout > functor_type ;
+
+  const size_t tile_dim0 = ( dim0 + N0 - 1 ) / N0 ;
+  const size_t tile_dim1 = ( dim1 + N1 - 1 ) / N1 ;
+  
+  typename functor_type::array_type array("",dim0,dim1);
+
+  Kokkos::parallel_for( Kokkos::RangePolicy<Space,size_t>(0,dim0*dim1) , functor_type( array ) );
+
+  ptrdiff_t error = 0 ;
+
+  Kokkos::parallel_reduce( Kokkos::RangePolicy<Space,size_t>(0,tile_dim0*tile_dim1) , functor_type( array ) , error );
+
+  EXPECT_EQ( error , ptrdiff_t(0) );
+}
+
+} /* namespace TestTile */
+
+#endif //TEST_TILE_HPP
+
diff --git a/lib/kokkos/core/unit_test/TestViewAPI.hpp b/lib/kokkos/core/unit_test/TestViewAPI.hpp
new file mode 100644
index 0000000000..ae4c6d2185
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestViewAPI.hpp
@@ -0,0 +1,1416 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+/*--------------------------------------------------------------------------*/
+
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+#if KOKKOS_USING_EXP_VIEW
+
+template< class T , class ... P >
+size_t allocation_count( const Kokkos::View<T,P...> & view )
+{
+  const size_t card  = view.size();
+  const size_t alloc = view.span();
+
+  const int memory_span = Kokkos::View<int*>::required_allocation_size(100);
+
+  return (card <= alloc && memory_span == 400) ? alloc : 0 ;
+}
+
+#else
+
+template< class T , class L , class D , class M , class S >
+size_t allocation_count( const Kokkos::View<T,L,D,M,S> & view )
+{
+  const size_t card  = Kokkos::Impl::cardinality_count( view.shape() );
+  const size_t alloc = view.capacity();
+
+  return card <= alloc ? alloc : 0 ;
+}
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+template< typename T, class DeviceType>
+struct TestViewOperator
+{
+  typedef typename DeviceType::execution_space  execution_space ;
+
+  static const unsigned N = 100 ;
+  static const unsigned D = 3 ;
+
+  typedef Kokkos::View< T*[D] , execution_space > view_type ;
+
+  const view_type v1 ;
+  const view_type v2 ;
+
+  TestViewOperator()
+    : v1( "v1" , N )
+    , v2( "v2" , N )
+    {}
+
+  static void testit()
+  {
+    Kokkos::parallel_for( N , TestViewOperator() );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned i ) const
+  {
+    const unsigned X = 0 ;
+    const unsigned Y = 1 ;
+    const unsigned Z = 2 ;
+
+    v2(i,X) = v1(i,X);
+    v2(i,Y) = v1(i,Y);
+    v2(i,Z) = v1(i,Z);
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< class DataType ,
+          class DeviceType ,
+          unsigned Rank = Kokkos::ViewTraits< DataType >::rank >
+struct TestViewOperator_LeftAndRight ;
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 8 >
+{
+  typedef typename DeviceType::execution_space    execution_space ;
+  typedef typename DeviceType::memory_space       memory_space ;
+  typedef typename execution_space::size_type     size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutStride, execution_space > stride_view ;
+
+  left_view    left ;
+  right_view   right ;
+  stride_view  left_stride ;
+  stride_view  right_stride ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight()
+    : left(  "left" )
+    , right( "right" )
+    , left_stride( left )
+    , right_stride( right )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit()
+  {
+    TestViewOperator_LeftAndRight driver ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i7 = 0 ; i7 < unsigned(left.dimension_7()) ; ++i7 )
+    for ( unsigned i6 = 0 ; i6 < unsigned(left.dimension_6()) ; ++i6 )
+    for ( unsigned i5 = 0 ; i5 < unsigned(left.dimension_5()) ; ++i5 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(left.dimension_4()) ; ++i4 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3, i4, i5, i6, i7 ) -
+                     & left(  0,  0,  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+
+      if ( & left(i0,i1,i2,i3,i4,i5,i6,i7) !=
+           & left_stride(i0,i1,i2,i3,i4,i5,i6,i7) ) {
+        update |= 4 ;
+      }
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(right.dimension_4()) ; ++i4 )
+    for ( unsigned i5 = 0 ; i5 < unsigned(right.dimension_5()) ; ++i5 )
+    for ( unsigned i6 = 0 ; i6 < unsigned(right.dimension_6()) ; ++i6 )
+    for ( unsigned i7 = 0 ; i7 < unsigned(right.dimension_7()) ; ++i7 )
+    {
+      const long j = & right( i0, i1, i2, i3, i4, i5, i6, i7 ) -
+                     & right(  0,  0,  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+
+      if ( & right(i0,i1,i2,i3,i4,i5,i6,i7) !=
+           & right_stride(i0,i1,i2,i3,i4,i5,i6,i7) ) {
+        update |= 8 ;
+      }
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 7 >
+{
+  typedef typename DeviceType::execution_space  execution_space ;
+  typedef typename DeviceType::memory_space     memory_space ;
+  typedef typename execution_space::size_type   size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  left_view    left ;
+  right_view   right ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight()
+    : left(  "left" )
+    , right( "right" )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit()
+  {
+    TestViewOperator_LeftAndRight driver ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i6 = 0 ; i6 < unsigned(left.dimension_6()) ; ++i6 )
+    for ( unsigned i5 = 0 ; i5 < unsigned(left.dimension_5()) ; ++i5 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(left.dimension_4()) ; ++i4 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3, i4, i5, i6 ) -
+                     & left(  0,  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(right.dimension_4()) ; ++i4 )
+    for ( unsigned i5 = 0 ; i5 < unsigned(right.dimension_5()) ; ++i5 )
+    for ( unsigned i6 = 0 ; i6 < unsigned(right.dimension_6()) ; ++i6 )
+    {
+      const long j = & right( i0, i1, i2, i3, i4, i5, i6 ) -
+                     & right(  0,  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 6 >
+{
+  typedef typename DeviceType::execution_space  execution_space ;
+  typedef typename DeviceType::memory_space     memory_space ;
+  typedef typename execution_space::size_type   size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  left_view    left ;
+  right_view   right ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight()
+    : left(  "left" )
+    , right( "right" )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit()
+  {
+    TestViewOperator_LeftAndRight driver ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i5 = 0 ; i5 < unsigned(left.dimension_5()) ; ++i5 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(left.dimension_4()) ; ++i4 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3, i4, i5 ) -
+                     & left(  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(right.dimension_4()) ; ++i4 )
+    for ( unsigned i5 = 0 ; i5 < unsigned(right.dimension_5()) ; ++i5 )
+    {
+      const long j = & right( i0, i1, i2, i3, i4, i5 ) -
+                     & right(  0,  0,  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 5 >
+{
+  typedef typename DeviceType::execution_space  execution_space ;
+  typedef typename DeviceType::memory_space     memory_space ;
+  typedef typename execution_space::size_type   size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutStride, execution_space > stride_view ;
+
+  left_view    left ;
+  right_view   right ;
+  stride_view  left_stride ;
+  stride_view  right_stride ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight()
+    : left(  "left" )
+    , right( "right" )
+    , left_stride( left )
+    , right_stride( right )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit()
+  {
+    TestViewOperator_LeftAndRight driver ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i4 = 0 ; i4 < unsigned(left.dimension_4()) ; ++i4 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3, i4 ) -
+                     & left(  0,  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+
+      if ( & left( i0, i1, i2, i3, i4 ) !=
+           & left_stride( i0, i1, i2, i3, i4 ) ) { update |= 4 ; }
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    for ( unsigned i4 = 0 ; i4 < unsigned(right.dimension_4()) ; ++i4 )
+    {
+      const long j = & right( i0, i1, i2, i3, i4 ) -
+                     & right(  0,  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+
+      if ( & right( i0, i1, i2, i3, i4 ) !=
+           & right_stride( i0, i1, i2, i3, i4 ) ) { update |= 8 ; }
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 4 >
+{
+  typedef typename DeviceType::execution_space  execution_space ;
+  typedef typename DeviceType::memory_space     memory_space ;
+  typedef typename execution_space::size_type   size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  left_view    left ;
+  right_view   right ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight()
+    : left(  "left" )
+    , right( "right" )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit()
+  {
+    TestViewOperator_LeftAndRight driver ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i3 = 0 ; i3 < unsigned(left.dimension_3()) ; ++i3 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2, i3 ) -
+                     & left(  0,  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    for ( unsigned i3 = 0 ; i3 < unsigned(right.dimension_3()) ; ++i3 )
+    {
+      const long j = & right( i0, i1, i2, i3 ) -
+                     & right(  0,  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+    }
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 3 >
+{
+  typedef typename DeviceType::execution_space  execution_space ;
+  typedef typename DeviceType::memory_space     memory_space ;
+  typedef typename execution_space::size_type   size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutStride, execution_space > stride_view ;
+
+  left_view    left ;
+  right_view   right ;
+  stride_view  left_stride ;
+  stride_view  right_stride ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight()
+    : left(  std::string("left") )
+    , right( std::string("right") )
+    , left_stride( left )
+    , right_stride( right )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit()
+  {
+    TestViewOperator_LeftAndRight driver ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1, i2 ) -
+                     & left(  0,  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+
+      if ( & left(i0,i1,i2) != & left_stride(i0,i1,i2) ) { update |= 4 ; }
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(right.dimension_2()) ; ++i2 )
+    {
+      const long j = & right( i0, i1, i2 ) -
+                     & right(  0,  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+
+      if ( & right(i0,i1,i2) != & right_stride(i0,i1,i2) ) { update |= 8 ; }
+    }
+
+#if KOKKOS_USING_EXP_VIEW
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i2 = 0 ; i2 < unsigned(left.dimension_2()) ; ++i2 )
+    {
+      if ( & left(i0,i1,i2)  != & left(i0,i1,i2,0,0,0,0,0) )  { update |= 3 ; }
+      if ( & right(i0,i1,i2) != & right(i0,i1,i2,0,0,0,0,0) ) { update |= 3 ; }
+    }
+#endif
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 2 >
+{
+  typedef typename DeviceType::execution_space  execution_space ;
+  typedef typename DeviceType::memory_space     memory_space ;
+  typedef typename execution_space::size_type   size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  left_view    left ;
+  right_view   right ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight()
+    : left(  "left" )
+    , right( "right" )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit()
+  {
+    TestViewOperator_LeftAndRight driver ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    long offset ;
+
+    offset = -1 ;
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+      const long j = & left( i0, i1 ) -
+                     & left(  0,  0 );
+      if ( j <= offset || left_alloc <= j ) { update |= 1 ; }
+      offset = j ;
+    }
+
+    offset = -1 ;
+    for ( unsigned i0 = 0 ; i0 < unsigned(right.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(right.dimension_1()) ; ++i1 )
+    {
+      const long j = & right( i0, i1 ) -
+                     & right(  0,  0 );
+      if ( j <= offset || right_alloc <= j ) { update |= 2 ; }
+      offset = j ;
+    }
+
+#if KOKKOS_USING_EXP_VIEW
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    for ( unsigned i1 = 0 ; i1 < unsigned(left.dimension_1()) ; ++i1 )
+    {
+      if ( & left(i0,i1)  != & left(i0,i1,0,0,0,0,0,0) )  { update |= 3 ; }
+      if ( & right(i0,i1) != & right(i0,i1,0,0,0,0,0,0) ) { update |= 3 ; }
+    }
+#endif
+  }
+};
+
+template< class DataType , class DeviceType >
+struct TestViewOperator_LeftAndRight< DataType , DeviceType , 1 >
+{
+  typedef typename DeviceType::execution_space  execution_space ;
+  typedef typename DeviceType::memory_space     memory_space ;
+  typedef typename execution_space::size_type   size_type ;
+
+  typedef int value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & input )
+    { update |= input ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+    { update = 0 ; }
+
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutLeft, execution_space > left_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutRight, execution_space > right_view ;
+
+  typedef Kokkos::
+    View< DataType, Kokkos::LayoutStride, execution_space > stride_view ;
+
+  left_view    left ;
+  right_view   right ;
+  stride_view  left_stride ;
+  stride_view  right_stride ;
+  long         left_alloc ;
+  long         right_alloc ;
+
+  TestViewOperator_LeftAndRight()
+    : left(  "left" )
+    , right( "right" )
+    , left_stride( left )
+    , right_stride( right )
+    , left_alloc( allocation_count( left ) )
+    , right_alloc( allocation_count( right ) )
+    {}
+
+  static void testit()
+  {
+    TestViewOperator_LeftAndRight driver ;
+
+    int error_flag = 0 ;
+
+    Kokkos::parallel_reduce( 1 , driver , error_flag );
+
+    ASSERT_EQ( error_flag , 0 );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type , value_type & update ) const
+  {
+    for ( unsigned i0 = 0 ; i0 < unsigned(left.dimension_0()) ; ++i0 )
+    {
+#if KOKKOS_USING_EXP_VIEW
+      if ( & left(i0)  != & left(i0,0,0,0,0,0,0,0) )  { update |= 3 ; }
+      if ( & right(i0) != & right(i0,0,0,0,0,0,0,0) ) { update |= 3 ; }
+#endif
+      if ( & left(i0)  != & left_stride(i0) ) { update |= 4 ; }
+      if ( & right(i0) != & right_stride(i0) ) { update |= 8 ; }
+    }
+  }
+};
+
+template<class Layout, class DeviceType>
+struct TestViewMirror {
+
+  template<class MemoryTraits>
+  void static test_mirror() {
+    Kokkos::View<double*, Layout, Kokkos::HostSpace> a_org("A",1000);
+    Kokkos::View<double*, Layout, Kokkos::HostSpace, MemoryTraits> a_h = a_org;
+    auto a_h2 = Kokkos::create_mirror(Kokkos::HostSpace(),a_h);
+    auto a_d = Kokkos::create_mirror(DeviceType(),a_h);
+
+    int equal_ptr_h_h2  = (a_h.data() ==a_h2.data())?1:0;
+    int equal_ptr_h_d   = (a_h.data() ==a_d. data())?1:0;
+    int equal_ptr_h2_d  = (a_h2.data()==a_d. data())?1:0;
+
+    ASSERT_EQ(equal_ptr_h_h2,0);
+    ASSERT_EQ(equal_ptr_h_d ,0);
+    ASSERT_EQ(equal_ptr_h2_d,0);
+    
+
+    ASSERT_EQ(a_h.dimension_0(),a_h2.dimension_0());
+    ASSERT_EQ(a_h.dimension_0(),a_d .dimension_0());
+  }
+
+
+  template<class MemoryTraits>
+  void static test_mirror_view() {
+    Kokkos::View<double*, Layout, Kokkos::HostSpace> a_org("A",1000);
+    Kokkos::View<double*, Layout, Kokkos::HostSpace, MemoryTraits> a_h = a_org;
+    auto a_h2 = Kokkos::create_mirror_view(Kokkos::HostSpace(),a_h);
+    auto a_d = Kokkos::create_mirror_view(DeviceType(),a_h);
+
+    int equal_ptr_h_h2  = a_h.data() ==a_h2.data()?1:0;
+    int equal_ptr_h_d   = a_h.data() ==a_d. data()?1:0;
+    int equal_ptr_h2_d  = a_h2.data()==a_d. data()?1:0;
+
+    int is_same_memspace = std::is_same<Kokkos::HostSpace,typename DeviceType::memory_space>::value?1:0; 
+    ASSERT_EQ(equal_ptr_h_h2,1);
+    ASSERT_EQ(equal_ptr_h_d ,is_same_memspace);
+    ASSERT_EQ(equal_ptr_h2_d ,is_same_memspace);
+
+
+    ASSERT_EQ(a_h.dimension_0(),a_h2.dimension_0());
+    ASSERT_EQ(a_h.dimension_0(),a_d .dimension_0());
+  } 
+
+  void static testit() {
+    test_mirror<Kokkos::MemoryTraits<0>>();
+    test_mirror<Kokkos::MemoryTraits<Kokkos::Unmanaged>>();
+    test_mirror_view<Kokkos::MemoryTraits<0>>();
+    test_mirror_view<Kokkos::MemoryTraits<Kokkos::Unmanaged>>();
+  }
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< typename T, class DeviceType >
+class TestViewAPI
+{
+public:
+  typedef DeviceType        device ;
+
+  enum { N0 = 1000 ,
+         N1 = 3 ,
+         N2 = 5 ,
+         N3 = 7 };
+
+  typedef Kokkos::View< T , device > dView0 ;
+  typedef Kokkos::View< T* , device > dView1 ;
+  typedef Kokkos::View< T*[N1] , device > dView2 ;
+  typedef Kokkos::View< T*[N1][N2] , device > dView3 ;
+  typedef Kokkos::View< T*[N1][N2][N3] , device > dView4 ;
+  typedef Kokkos::View< const T*[N1][N2][N3] , device > const_dView4 ;
+
+  typedef Kokkos::View< T****, device, Kokkos::MemoryUnmanaged > dView4_unmanaged ;
+
+  typedef typename dView0::host_mirror_space host ;
+
+  TestViewAPI()
+  {
+    run_test_mirror();
+    run_test();
+    run_test_scalar();
+    run_test_const();
+    run_test_subview();
+    run_test_subview_strided();
+    run_test_vector();
+
+    TestViewOperator< T , device >::testit();
+    TestViewOperator_LeftAndRight< int[2][3][4][2][3][4][2][3] , device >::testit();
+    TestViewOperator_LeftAndRight< int[2][3][4][2][3][4][2] , device >::testit();
+    TestViewOperator_LeftAndRight< int[2][3][4][2][3][4] , device >::testit();
+    TestViewOperator_LeftAndRight< int[2][3][4][2][3] , device >::testit();
+    TestViewOperator_LeftAndRight< int[2][3][4][2] , device >::testit();
+    TestViewOperator_LeftAndRight< int[2][3][4] , device >::testit();
+    TestViewOperator_LeftAndRight< int[2][3] , device >::testit();
+    TestViewOperator_LeftAndRight< int[2] , device >::testit();
+    TestViewMirror<Kokkos::LayoutLeft, device >::testit(); 
+    TestViewMirror<Kokkos::LayoutRight, device >::testit(); 
+
+  }
+
+  static void run_test_mirror()
+  {
+    typedef Kokkos::View< int , host > view_type ;
+    typedef typename view_type::HostMirror mirror_type ;
+
+    static_assert( std::is_same< typename view_type::memory_space
+                               , typename mirror_type::memory_space
+                               >::value , "" );
+
+    view_type a("a");
+    mirror_type am = Kokkos::create_mirror_view(a);
+    mirror_type ax = Kokkos::create_mirror(a);
+    ASSERT_EQ( & a() , & am() );
+  }
+
+  static void run_test_scalar()
+  {
+    typedef typename dView0::HostMirror  hView0 ;
+
+    dView0 dx , dy ;
+    hView0 hx , hy ;
+
+    dx = dView0( "dx" );
+    dy = dView0( "dy" );
+
+    hx = Kokkos::create_mirror( dx );
+    hy = Kokkos::create_mirror( dy );
+
+    hx() = 1 ;
+
+    Kokkos::deep_copy( dx , hx );
+    Kokkos::deep_copy( dy , dx );
+    Kokkos::deep_copy( hy , dy );
+
+    ASSERT_EQ( hx(), hy() );
+  }
+
+  static void run_test()
+  {
+    // mfh 14 Feb 2014: This test doesn't actually create instances of
+    // these types.  In order to avoid "declared but unused typedef"
+    // warnings, we declare empty instances of these types, with the
+    // usual "(void)" marker to avoid compiler warnings for unused
+    // variables.
+
+    typedef typename dView0::HostMirror  hView0 ;
+    typedef typename dView1::HostMirror  hView1 ;
+    typedef typename dView2::HostMirror  hView2 ;
+    typedef typename dView3::HostMirror  hView3 ;
+    typedef typename dView4::HostMirror  hView4 ;
+
+    {
+      hView0 thing;
+      (void) thing;
+    }
+    {
+      hView1 thing;
+      (void) thing;
+    }
+    {
+      hView2 thing;
+      (void) thing;
+    }
+    {
+      hView3 thing;
+      (void) thing;
+    }
+    {
+      hView4 thing;
+      (void) thing;
+    }
+
+    dView4 dx , dy , dz ;
+    hView4 hx , hy , hz ;
+
+    ASSERT_TRUE( dx.ptr_on_device() == 0 );
+    ASSERT_TRUE( dy.ptr_on_device() == 0 );
+    ASSERT_TRUE( dz.ptr_on_device() == 0 );
+    ASSERT_TRUE( hx.ptr_on_device() == 0 );
+    ASSERT_TRUE( hy.ptr_on_device() == 0 );
+    ASSERT_TRUE( hz.ptr_on_device() == 0 );
+    ASSERT_EQ( dx.dimension_0() , 0u );
+    ASSERT_EQ( dy.dimension_0() , 0u );
+    ASSERT_EQ( dz.dimension_0() , 0u );
+    ASSERT_EQ( hx.dimension_0() , 0u );
+    ASSERT_EQ( hy.dimension_0() , 0u );
+    ASSERT_EQ( hz.dimension_0() , 0u );
+    ASSERT_EQ( dx.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( dy.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( dz.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( hx.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( hy.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( hz.dimension_1() , unsigned(N1) );
+
+    dx = dView4( "dx" , N0 );
+    dy = dView4( "dy" , N0 );
+
+    #if KOKKOS_USING_EXP_VIEW
+    ASSERT_EQ( dx.use_count() , size_t(1) );
+    #else
+    ASSERT_EQ( dx.tracker().ref_count() , size_t(1) );
+    #endif
+
+    dView4_unmanaged unmanaged_dx = dx;
+    #if KOKKOS_USING_EXP_VIEW
+    ASSERT_EQ( dx.use_count() , size_t(1) );
+    #else
+    ASSERT_EQ( dx.tracker().ref_count() , size_t(1) );
+    #endif
+
+    dView4_unmanaged unmanaged_from_ptr_dx = dView4_unmanaged(dx.ptr_on_device(),
+                                                              dx.dimension_0(),
+                                                              dx.dimension_1(),
+                                                              dx.dimension_2(),
+                                                              dx.dimension_3());
+
+    {
+      // Destruction of this view should be harmless
+      const_dView4 unmanaged_from_ptr_const_dx( dx.ptr_on_device() ,
+                                                dx.dimension_0() ,
+                                                dx.dimension_1() ,
+                                                dx.dimension_2() ,
+                                                dx.dimension_3() );
+    }
+
+    const_dView4 const_dx = dx ;
+    #if KOKKOS_USING_EXP_VIEW
+    ASSERT_EQ( dx.use_count() , size_t(2) );
+    #else
+    ASSERT_EQ( dx.tracker().ref_count() , size_t(2) );
+    #endif
+
+    {
+      const_dView4 const_dx2;
+      const_dx2 = const_dx;
+      #if KOKKOS_USING_EXP_VIEW
+      ASSERT_EQ( dx.use_count() , size_t(3) );
+      #else
+      ASSERT_EQ( dx.tracker().ref_count() , size_t(3) );
+      #endif
+
+      const_dx2 = dy;
+      #if KOKKOS_USING_EXP_VIEW
+      ASSERT_EQ( dx.use_count() , size_t(2) );
+      #else
+      ASSERT_EQ( dx.tracker().ref_count() , size_t(2) );
+      #endif
+
+      const_dView4 const_dx3(dx);
+      #if KOKKOS_USING_EXP_VIEW
+      ASSERT_EQ( dx.use_count() , size_t(3) );
+      #else
+      ASSERT_EQ( dx.tracker().ref_count() , size_t(3) );
+      #endif
+      
+      dView4_unmanaged dx4_unmanaged(dx);
+      #if KOKKOS_USING_EXP_VIEW
+      ASSERT_EQ( dx.use_count() , size_t(3) );
+      #else
+      ASSERT_EQ( dx.tracker().ref_count() , size_t(3) );
+      #endif
+    }
+
+    #if KOKKOS_USING_EXP_VIEW
+    ASSERT_EQ( dx.use_count() , size_t(2) );
+    #else
+    ASSERT_EQ( dx.tracker().ref_count() , size_t(2) );
+    #endif
+
+
+    ASSERT_FALSE( dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( const_dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( unmanaged_dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( unmanaged_from_ptr_dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( dy.ptr_on_device() == 0 );
+    ASSERT_NE( dx , dy );
+
+    ASSERT_EQ( dx.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( dx.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( dx.dimension_2() , unsigned(N2) );
+    ASSERT_EQ( dx.dimension_3() , unsigned(N3) );
+
+    ASSERT_EQ( dy.dimension_0() , unsigned(N0) );
+    ASSERT_EQ( dy.dimension_1() , unsigned(N1) );
+    ASSERT_EQ( dy.dimension_2() , unsigned(N2) );
+    ASSERT_EQ( dy.dimension_3() , unsigned(N3) );
+
+    ASSERT_EQ( unmanaged_from_ptr_dx.capacity(),unsigned(N0)*unsigned(N1)*unsigned(N2)*unsigned(N3) );
+
+    hx = Kokkos::create_mirror( dx );
+    hy = Kokkos::create_mirror( dy );
+
+    // T v1 = hx() ;    // Generates compile error as intended
+    // T v2 = hx(0,0) ; // Generates compile error as intended
+    // hx(0,0) = v2 ;   // Generates compile error as intended
+
+#if ! KOKKOS_USING_EXP_VIEW
+    // Testing with asynchronous deep copy with respect to device
+    {
+      size_t count = 0 ;
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < hx.dimension_1() ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < hx.dimension_2() ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < hx.dimension_3() ; ++i3 ) {
+        hx(ip,i1,i2,i3) = ++count ;
+      }}}}
+
+
+      Kokkos::deep_copy(typename hView4::execution_space(), dx , hx );
+      Kokkos::deep_copy(typename hView4::execution_space(), dy , dx );
+      Kokkos::deep_copy(typename hView4::execution_space(), hy , dy );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , hy(ip,i1,i2,i3) ); }
+      }}}}
+
+      Kokkos::deep_copy(typename hView4::execution_space(), dx , T(0) );
+      Kokkos::deep_copy(typename hView4::execution_space(), hx , dx );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , T(0) ); }
+      }}}}
+    }
+
+    // Testing with asynchronous deep copy with respect to host
+    {
+      size_t count = 0 ;
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < hx.dimension_1() ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < hx.dimension_2() ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < hx.dimension_3() ; ++i3 ) {
+        hx(ip,i1,i2,i3) = ++count ;
+      }}}}
+
+      Kokkos::deep_copy(typename dView4::execution_space(), dx , hx );
+      Kokkos::deep_copy(typename dView4::execution_space(), dy , dx );
+      Kokkos::deep_copy(typename dView4::execution_space(), hy , dy );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , hy(ip,i1,i2,i3) ); }
+      }}}}
+
+      Kokkos::deep_copy(typename dView4::execution_space(), dx , T(0) );
+      Kokkos::deep_copy(typename dView4::execution_space(), hx , dx );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , T(0) ); }
+      }}}}
+    }
+#endif /* #if ! KOKKOS_USING_EXP_VIEW */
+
+    // Testing with synchronous deep copy
+    {
+      size_t count = 0 ;
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < hx.dimension_1() ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < hx.dimension_2() ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < hx.dimension_3() ; ++i3 ) {
+        hx(ip,i1,i2,i3) = ++count ;
+      }}}}
+
+      Kokkos::deep_copy( dx , hx );
+      Kokkos::deep_copy( dy , dx );
+      Kokkos::deep_copy( hy , dy );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , hy(ip,i1,i2,i3) ); }
+      }}}}
+
+      Kokkos::deep_copy( dx , T(0) );
+      Kokkos::deep_copy( hx , dx );
+
+      for ( size_t ip = 0 ; ip < N0 ; ++ip ) {
+      for ( size_t i1 = 0 ; i1 < N1 ; ++i1 ) {
+      for ( size_t i2 = 0 ; i2 < N2 ; ++i2 ) {
+      for ( size_t i3 = 0 ; i3 < N3 ; ++i3 ) {
+        { ASSERT_EQ( hx(ip,i1,i2,i3) , T(0) ); }
+      }}}}
+    }
+    dz = dx ; ASSERT_EQ( dx, dz); ASSERT_NE( dy, dz);
+    dz = dy ; ASSERT_EQ( dy, dz); ASSERT_NE( dx, dz);
+
+    dx = dView4();
+    ASSERT_TRUE( dx.ptr_on_device() == 0 );
+    ASSERT_FALSE( dy.ptr_on_device() == 0 );
+    ASSERT_FALSE( dz.ptr_on_device() == 0 );
+    dy = dView4();
+    ASSERT_TRUE( dx.ptr_on_device() == 0 );
+    ASSERT_TRUE( dy.ptr_on_device() == 0 );
+    ASSERT_FALSE( dz.ptr_on_device() == 0 );
+    dz = dView4();
+    ASSERT_TRUE( dx.ptr_on_device() == 0 );
+    ASSERT_TRUE( dy.ptr_on_device() == 0 );
+    ASSERT_TRUE( dz.ptr_on_device() == 0 );
+  }
+
+  typedef T DataType[2] ;
+
+  static void
+  check_auto_conversion_to_const(
+     const Kokkos::View< const DataType , device > & arg_const ,
+     const Kokkos::View< DataType , device > & arg )
+  {
+    ASSERT_TRUE( arg_const == arg );
+  }
+
+  static void run_test_const()
+  {
+    typedef Kokkos::View< DataType , device > typeX ;
+    typedef Kokkos::View< const DataType , device > const_typeX ;
+    typedef Kokkos::View< const DataType , device , Kokkos::MemoryRandomAccess > const_typeR ;
+    typeX x( "X" );
+    const_typeX xc = x ;
+    const_typeR xr = x ;
+
+    ASSERT_TRUE( xc == x );
+    ASSERT_TRUE( x == xc );
+
+    // For CUDA the constant random access View does not return
+    // an lvalue reference due to retrieving through texture cache
+    // therefore not allowed to query the underlying pointer.
+#if defined( KOKKOS_HAVE_CUDA )
+    if ( ! std::is_same< typename device::execution_space , Kokkos::Cuda >::value )
+#endif
+    {
+      ASSERT_TRUE( x.ptr_on_device() == xr.ptr_on_device() );
+    }
+
+    // typeX xf = xc ; // setting non-const from const must not compile
+
+    check_auto_conversion_to_const( x , x );
+  }
+
+  static void run_test_subview()
+  {
+    typedef Kokkos::View< const T , device > sView ;
+
+    dView0 d0( "d0" );
+    dView1 d1( "d1" , N0 );
+    dView2 d2( "d2" , N0 );
+    dView3 d3( "d3" , N0 );
+    dView4 d4( "d4" , N0 );
+
+    sView s0 = d0 ;
+    sView s1 = Kokkos::subview( d1 , 1 );
+    sView s2 = Kokkos::subview( d2 , 1 , 1 );
+    sView s3 = Kokkos::subview( d3 , 1 , 1 , 1 );
+    sView s4 = Kokkos::subview( d4 , 1 , 1 , 1 , 1 );
+  }
+
+  static void run_test_subview_strided()
+  {
+    typedef Kokkos::View< int **** , Kokkos::LayoutLeft  , host >  view_left_4 ;
+    typedef Kokkos::View< int **** , Kokkos::LayoutRight , host >  view_right_4 ;
+    typedef Kokkos::View< int **   , Kokkos::LayoutLeft  , host >  view_left_2 ;
+    typedef Kokkos::View< int **   , Kokkos::LayoutRight , host >  view_right_2 ;
+
+    typedef Kokkos::View< int * ,  Kokkos::LayoutStride , host >  view_stride_1 ;
+    typedef Kokkos::View< int ** ,  Kokkos::LayoutStride , host >  view_stride_2 ;
+
+    view_left_2  xl2("xl2", 100 , 200 );
+    view_right_2 xr2("xr2", 100 , 200 );
+    view_stride_1  yl1 = Kokkos::subview( xl2 , 0 , Kokkos::ALL() );
+    view_stride_1  yl2 = Kokkos::subview( xl2 , 1 , Kokkos::ALL() );
+    view_stride_1  yr1 = Kokkos::subview( xr2 , 0 , Kokkos::ALL() );
+    view_stride_1  yr2 = Kokkos::subview( xr2 , 1 , Kokkos::ALL() );
+
+    ASSERT_EQ( yl1.dimension_0() , xl2.dimension_1() );
+    ASSERT_EQ( yl2.dimension_0() , xl2.dimension_1() );
+    ASSERT_EQ( yr1.dimension_0() , xr2.dimension_1() );
+    ASSERT_EQ( yr2.dimension_0() , xr2.dimension_1() );
+
+    ASSERT_EQ( & yl1(0) - & xl2(0,0) , 0 );
+    ASSERT_EQ( & yl2(0) - & xl2(1,0) , 0 );
+    ASSERT_EQ( & yr1(0) - & xr2(0,0) , 0 );
+    ASSERT_EQ( & yr2(0) - & xr2(1,0) , 0 );
+
+    view_left_4 xl4( "xl4" , 10 , 20 , 30 , 40 );
+    view_right_4 xr4( "xr4" , 10 , 20 , 30 , 40 );
+
+    view_stride_2 yl4 = Kokkos::subview( xl4 , 1 , Kokkos::ALL() , 2 , Kokkos::ALL() );
+    view_stride_2 yr4 = Kokkos::subview( xr4 , 1 , Kokkos::ALL() , 2 , Kokkos::ALL() );
+
+    ASSERT_EQ( yl4.dimension_0() , xl4.dimension_1() );
+    ASSERT_EQ( yl4.dimension_1() , xl4.dimension_3() );
+    ASSERT_EQ( yr4.dimension_0() , xr4.dimension_1() );
+    ASSERT_EQ( yr4.dimension_1() , xr4.dimension_3() );
+
+    ASSERT_EQ( & yl4(4,4) - & xl4(1,4,2,4) , 0 );
+    ASSERT_EQ( & yr4(4,4) - & xr4(1,4,2,4) , 0 );
+  }
+
+  static void run_test_vector()
+  {
+    static const unsigned Length = 1000 , Count = 8 ;
+
+    typedef Kokkos::View< T* ,  Kokkos::LayoutLeft , host > vector_type ;
+    typedef Kokkos::View< T** , Kokkos::LayoutLeft , host > multivector_type ;
+
+    typedef Kokkos::View< T* ,  Kokkos::LayoutRight , host > vector_right_type ;
+    typedef Kokkos::View< T** , Kokkos::LayoutRight , host > multivector_right_type ;
+
+    typedef Kokkos::View< const T* , Kokkos::LayoutRight, host > const_vector_right_type ;
+    typedef Kokkos::View< const T* , Kokkos::LayoutLeft , host > const_vector_type ;
+    typedef Kokkos::View< const T** , Kokkos::LayoutLeft , host > const_multivector_type ;
+
+    multivector_type mv = multivector_type( "mv" , Length , Count );
+    multivector_right_type mv_right = multivector_right_type( "mv" , Length , Count );
+
+    vector_type v1 = Kokkos::subview( mv , Kokkos::ALL() , 0 );
+    vector_type v2 = Kokkos::subview( mv , Kokkos::ALL() , 1 );
+    vector_type v3 = Kokkos::subview( mv , Kokkos::ALL() , 2 );
+
+    vector_type rv1 = Kokkos::subview( mv_right , 0 , Kokkos::ALL() );
+    vector_type rv2 = Kokkos::subview( mv_right , 1 , Kokkos::ALL() );
+    vector_type rv3 = Kokkos::subview( mv_right , 2 , Kokkos::ALL() );
+
+    multivector_type mv1 = Kokkos::subview( mv , std::make_pair( 1 , 998 ) ,
+                                                 std::make_pair( 2 , 5 ) );
+
+    multivector_right_type mvr1 =
+      Kokkos::subview( mv_right ,
+                       std::make_pair( 1 , 998 ) ,
+                       std::make_pair( 2 , 5 ) );
+
+    const_vector_type cv1 = Kokkos::subview( mv , Kokkos::ALL(), 0 );
+    const_vector_type cv2 = Kokkos::subview( mv , Kokkos::ALL(), 1 );
+    const_vector_type cv3 = Kokkos::subview( mv , Kokkos::ALL(), 2 );
+
+    vector_right_type vr1 = Kokkos::subview( mv , Kokkos::ALL() , 0 );
+    vector_right_type vr2 = Kokkos::subview( mv , Kokkos::ALL() , 1 );
+    vector_right_type vr3 = Kokkos::subview( mv , Kokkos::ALL() , 2 );
+
+    const_vector_right_type cvr1 = Kokkos::subview( mv , Kokkos::ALL() , 0 );
+    const_vector_right_type cvr2 = Kokkos::subview( mv , Kokkos::ALL() , 1 );
+    const_vector_right_type cvr3 = Kokkos::subview( mv , Kokkos::ALL() , 2 );
+
+    ASSERT_TRUE( & v1[0] == & v1(0) );
+    ASSERT_TRUE( & v1[0] == & mv(0,0) );
+    ASSERT_TRUE( & v2[0] == & mv(0,1) );
+    ASSERT_TRUE( & v3[0] == & mv(0,2) );
+
+    ASSERT_TRUE( & cv1[0] == & mv(0,0) );
+    ASSERT_TRUE( & cv2[0] == & mv(0,1) );
+    ASSERT_TRUE( & cv3[0] == & mv(0,2) );
+
+    ASSERT_TRUE( & vr1[0] == & mv(0,0) );
+    ASSERT_TRUE( & vr2[0] == & mv(0,1) );
+    ASSERT_TRUE( & vr3[0] == & mv(0,2) );
+
+    ASSERT_TRUE( & cvr1[0] == & mv(0,0) );
+    ASSERT_TRUE( & cvr2[0] == & mv(0,1) );
+    ASSERT_TRUE( & cvr3[0] == & mv(0,2) );
+
+    ASSERT_TRUE( & mv1(0,0) == & mv( 1 , 2 ) );
+    ASSERT_TRUE( & mv1(1,1) == & mv( 2 , 3 ) );
+    ASSERT_TRUE( & mv1(3,2) == & mv( 4 , 4 ) );
+    ASSERT_TRUE( & mvr1(0,0) == & mv_right( 1 , 2 ) );
+    ASSERT_TRUE( & mvr1(1,1) == & mv_right( 2 , 3 ) );
+    ASSERT_TRUE( & mvr1(3,2) == & mv_right( 4 , 4 ) );
+
+    const_vector_type c_cv1( v1 );
+    typename vector_type::const_type c_cv2( v2 );
+    typename const_vector_type::const_type c_ccv2( v2 );
+
+    const_multivector_type cmv( mv );
+    typename multivector_type::const_type cmvX( cmv );
+    typename const_multivector_type::const_type ccmvX( cmv );
+  }
+};
+
+} // namespace Test
+
+/*--------------------------------------------------------------------------*/
+
diff --git a/lib/kokkos/core/unit_test/TestViewImpl.hpp b/lib/kokkos/core/unit_test/TestViewImpl.hpp
new file mode 100644
index 0000000000..c34ef759d1
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestViewImpl.hpp
@@ -0,0 +1,289 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+#if KOKKOS_USING_EXP_VIEW
+
+namespace Test {
+
+template < class Device >
+void test_view_impl() {}
+
+}
+
+#else
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+struct DummyMemorySpace
+{
+  typedef DummyMemorySpace memory_space ;
+  typedef unsigned size_type ;
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< class Type >
+struct DefineShape {
+  typedef typename Kokkos::Impl::AnalyzeShape<Type>::shape type ;
+};
+
+template< class Type >
+struct ExtractValueType {
+  typedef typename Kokkos::Impl::AnalyzeShape<Type>::value_type type ;
+};
+
+template< class Type >
+struct ArrayType { typedef Type type ; };
+
+template < class Device >
+void test_view_impl()
+{
+  //typedef typename Device::memory_space memory_space ; // unused
+
+  typedef ArrayType< int[100]                >::type type_01 ;
+  typedef ArrayType< int*                    >::type type_11 ;
+  typedef ArrayType< int[5][6][700]          >::type type_03 ;
+  typedef ArrayType< double*[8][9][900]      >::type type_14 ;
+  typedef ArrayType< long**                  >::type type_22 ;
+  typedef ArrayType< short **[5][6][7]       >::type type_25 ;
+  typedef ArrayType< const short **[5][6][7] >::type const_type_25 ;
+  typedef ArrayType< short***[5][6][7]       >::type type_36 ;
+  typedef ArrayType< const short***[5][6][7] >::type const_type_36 ;
+
+  // mfh 14 Feb 2014: With gcc 4.8.2 -Wall, this emits a warning:
+  //
+  // typedef ‘ok_const_25’ locally defined but not used [-Wunused-local-typedefs]
+  //
+  // It's unfortunate that this is the case, because the typedef is
+  // being used for a compile-time check!  We deal with this by
+  // declaring an instance of ok_const_25, and marking it with
+  // "(void)" so that instance doesn't emit an "unused variable"
+  // warning.
+  //
+  // typedef typename Kokkos::Impl::StaticAssertSame<
+  //    typename Kokkos::Impl::AnalyzeShape<type_25>::const_type ,
+  //    typename Kokkos::Impl::AnalyzeShape<const_type_25>::type
+  //      > ok_const_25 ;
+
+  typedef typename Kokkos::Impl::StaticAssertSame<
+    typename Kokkos::Impl::AnalyzeShape<type_25>::const_type,
+    typename Kokkos::Impl::AnalyzeShape<const_type_25>::type
+      > ok_const_25 ;
+
+  typedef typename Kokkos::Impl::StaticAssertSame<
+    typename Kokkos::Impl::AnalyzeShape<type_36>::const_type,
+    typename Kokkos::Impl::AnalyzeShape<const_type_36>::type
+      > ok_const_36 ;
+  {
+    ok_const_25 thing_25 ;
+    ok_const_36 thing_36 ;
+    (void) thing_25 ; // silence warning for unused variable
+    (void) thing_36 ; // silence warning for unused variable
+  }
+
+  ASSERT_TRUE( ( Kokkos::Impl::is_same< ExtractValueType<type_03>::type , int >::value ) );
+  ASSERT_TRUE( ( Kokkos::Impl::is_same< ExtractValueType<type_14>::type , double >::value ) );
+  ASSERT_TRUE( ( Kokkos::Impl::is_same< ExtractValueType<type_22>::type , long >::value ) );
+  ASSERT_TRUE( ( Kokkos::Impl::is_same< ExtractValueType<type_36>::type , short >::value ) );
+
+  ASSERT_FALSE( ( Kokkos::Impl::is_same< ExtractValueType<type_36>::type , int >::value ) );
+
+  typedef typename DefineShape< type_01 >::type  shape_01_type ;
+  typedef typename DefineShape< type_11 >::type  shape_11_type ;
+  typedef typename DefineShape< type_03 >::type  shape_03_type ;
+  typedef typename DefineShape< type_14 >::type  shape_14_type ;
+  typedef typename DefineShape< type_22 >::type  shape_22_type ;
+  typedef typename DefineShape< type_36 >::type  shape_36_type ;
+
+  ASSERT_TRUE( ( Kokkos::Impl::StaticAssert< shape_36_type::rank == 6 >::value ) );
+  ASSERT_TRUE( ( Kokkos::Impl::StaticAssert< shape_03_type::rank == 3 >::value ) );
+
+  shape_01_type shape_01 ; shape_01_type::assign( shape_01 );
+  shape_11_type shape_11 ; shape_11_type::assign( shape_11, 1000 );
+  shape_03_type shape_03 ; shape_03_type::assign( shape_03 );
+  shape_14_type shape_14 ; shape_14_type::assign( shape_14 , 0 );
+  shape_22_type shape_22 ; shape_22_type::assign( shape_22 , 0 , 0 );
+  shape_36_type shape_36 ; shape_36_type::assign( shape_36 , 10 , 20 , 30 );
+
+  ASSERT_TRUE( shape_01.rank_dynamic == 0u );
+  ASSERT_TRUE( shape_01.rank         == 1u );
+  ASSERT_TRUE( shape_01.N0           == 100u );
+
+  ASSERT_TRUE( shape_11.rank_dynamic == 1u );
+  ASSERT_TRUE( shape_11.rank         == 1u );
+  ASSERT_TRUE( shape_11.N0           == 1000u );
+
+  ASSERT_TRUE( shape_03.rank_dynamic == 0u );
+  ASSERT_TRUE( shape_03.rank         == 3u );
+  ASSERT_TRUE( shape_03.N0           == 5u );
+  ASSERT_TRUE( shape_03.N1           == 6u );
+  ASSERT_TRUE( shape_03.N2           == 700u );
+
+  ASSERT_TRUE( shape_14.rank_dynamic == 1u );
+  ASSERT_TRUE( shape_14.rank         == 4u );
+  ASSERT_TRUE( shape_14.N0           == 0u );
+  ASSERT_TRUE( shape_14.N1           == 8u );
+  ASSERT_TRUE( shape_14.N2           == 9u );
+  ASSERT_TRUE( shape_14.N3           == 900u );
+
+  ASSERT_TRUE( shape_22.rank_dynamic == 2u );
+  ASSERT_TRUE( shape_22.rank         == 2u );
+  ASSERT_TRUE( shape_22.N0           == 0u );
+  ASSERT_TRUE( shape_22.N1           == 0u );
+
+  ASSERT_TRUE( shape_36.rank_dynamic == 3u );
+  ASSERT_TRUE( shape_36.rank         == 6u );
+  ASSERT_TRUE( shape_36.N0           == 10u );
+  ASSERT_TRUE( shape_36.N1           == 20u );
+  ASSERT_TRUE( shape_36.N2           == 30u );
+  ASSERT_TRUE( shape_36.N3           == 5u  );
+  ASSERT_TRUE( shape_36.N4           == 6u  );
+  ASSERT_TRUE( shape_36.N5           == 7u  );
+
+
+  ASSERT_TRUE( shape_01 == shape_01 );
+  ASSERT_TRUE( shape_11 == shape_11 );
+  ASSERT_TRUE( shape_36 == shape_36 );
+  ASSERT_TRUE( shape_01 != shape_36 );
+  ASSERT_TRUE( shape_22 != shape_36 );
+
+  //------------------------------------------------------------------------
+
+  typedef Kokkos::Impl::ViewOffset< shape_01_type , Kokkos::LayoutLeft > shape_01_left_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_11_type , Kokkos::LayoutLeft > shape_11_left_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_03_type , Kokkos::LayoutLeft > shape_03_left_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_14_type , Kokkos::LayoutLeft > shape_14_left_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_22_type , Kokkos::LayoutLeft > shape_22_left_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_36_type , Kokkos::LayoutLeft > shape_36_left_offset ;
+
+  typedef Kokkos::Impl::ViewOffset< shape_01_type , Kokkos::LayoutRight > shape_01_right_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_11_type , Kokkos::LayoutRight > shape_11_right_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_03_type , Kokkos::LayoutRight > shape_03_right_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_14_type , Kokkos::LayoutRight > shape_14_right_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_22_type , Kokkos::LayoutRight > shape_22_right_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_36_type , Kokkos::LayoutRight > shape_36_right_offset ;
+
+  ASSERT_TRUE( ! shape_01_left_offset::has_padding );
+  ASSERT_TRUE( ! shape_11_left_offset::has_padding );
+  ASSERT_TRUE( ! shape_03_left_offset::has_padding );
+  ASSERT_TRUE(   shape_14_left_offset::has_padding );
+  ASSERT_TRUE(   shape_22_left_offset::has_padding );
+  ASSERT_TRUE(   shape_36_left_offset::has_padding );
+
+  ASSERT_TRUE( ! shape_01_right_offset::has_padding );
+  ASSERT_TRUE( ! shape_11_right_offset::has_padding );
+  ASSERT_TRUE( ! shape_03_right_offset::has_padding );
+  ASSERT_TRUE( ! shape_14_right_offset::has_padding );
+  ASSERT_TRUE(   shape_22_right_offset::has_padding );
+  ASSERT_TRUE(   shape_36_right_offset::has_padding );
+
+  //------------------------------------------------------------------------
+
+  typedef Kokkos::Impl::ViewOffset< shape_01_type , Kokkos::LayoutStride > shape_01_stride_offset ;
+  typedef Kokkos::Impl::ViewOffset< shape_36_type , Kokkos::LayoutStride > shape_36_stride_offset ;
+
+  {
+    shape_01_stride_offset stride_offset_01 ;
+
+    stride_offset_01.assign( 1, stride_offset_01.N0, 0,0,0,0,0,0,0 );
+
+    ASSERT_EQ( int(stride_offset_01.S[0]) , int(1) );
+    ASSERT_EQ( int(stride_offset_01.S[1]) , int(stride_offset_01.N0) );
+  }
+
+  {
+    shape_36_stride_offset stride_offset_36 ;
+
+    size_t str[7] ;
+    str[5] = 1 ;
+    str[4] = str[5] * stride_offset_36.N5 ;
+    str[3] = str[4] * stride_offset_36.N4 ;
+    str[2] = str[3] * stride_offset_36.N3 ;
+    str[1] = str[2] * 100 ;
+    str[0] = str[1] * 200 ;
+    str[6] = str[0] * 300 ;
+
+    stride_offset_36.assign( str[0] , str[1] , str[2] , str[3] , str[4] , str[5] , str[6] , 0 , 0 );
+
+    ASSERT_EQ( size_t(stride_offset_36.S[6]) , size_t(str[6]) );
+    ASSERT_EQ( size_t(stride_offset_36.N2)   , size_t(100) );
+    ASSERT_EQ( size_t(stride_offset_36.N1)   , size_t(200) );
+    ASSERT_EQ( size_t(stride_offset_36.N0)   , size_t(300) );
+  }
+
+  //------------------------------------------------------------------------
+
+  {
+    const int rank = 6 ;
+    const int order[] = { 5 , 3 , 1 , 0 , 2 , 4 };
+    const unsigned dim[] = { 2 , 3 , 5 , 7 , 11 , 13 };
+    Kokkos::LayoutStride stride_6 = Kokkos::LayoutStride::order_dimensions( rank , order , dim );
+    size_t n = 1 ;
+    for ( int i = 0 ; i < rank ; ++i ) {
+      ASSERT_EQ( size_t(dim[i]) , size_t( stride_6.dimension[i] ) );
+      ASSERT_EQ( size_t(n) , size_t( stride_6.stride[ order[i] ] ) );
+      n *= dim[order[i]] ;
+    }
+  }
+
+  //------------------------------------------------------------------------
+}
+
+} /* namespace Test */
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
diff --git a/lib/kokkos/core/unit_test/TestViewMapping.hpp b/lib/kokkos/core/unit_test/TestViewMapping.hpp
new file mode 100644
index 0000000000..eddb81bed5
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestViewMapping.hpp
@@ -0,0 +1,1307 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+template< class Space >
+void test_view_mapping()
+{
+  typedef typename Space::execution_space ExecSpace ;
+
+  typedef Kokkos::Experimental::Impl::ViewDimension<>  dim_0 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<2> dim_s2 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<2,3> dim_s2_s3 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<2,3,4> dim_s2_s3_s4 ;
+
+  typedef Kokkos::Experimental::Impl::ViewDimension<0> dim_s0 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,3> dim_s0_s3 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,3,4> dim_s0_s3_s4 ;
+
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,0> dim_s0_s0 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,0,4> dim_s0_s0_s4 ;
+
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,0,0> dim_s0_s0_s0 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,0,0,0> dim_s0_s0_s0_s0 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,0,0,0,0> dim_s0_s0_s0_s0_s0 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,0,0,0,0,0> dim_s0_s0_s0_s0_s0_s0 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,0,0,0,0,0,0> dim_s0_s0_s0_s0_s0_s0_s0 ;
+  typedef Kokkos::Experimental::Impl::ViewDimension<0,0,0,0,0,0,0,0> dim_s0_s0_s0_s0_s0_s0_s0_s0 ;
+
+  // Fully static dimensions should not be larger than an int
+  ASSERT_LE( sizeof(dim_0) , sizeof(int) );
+  ASSERT_LE( sizeof(dim_s2) , sizeof(int) );
+  ASSERT_LE( sizeof(dim_s2_s3) , sizeof(int) );
+  ASSERT_LE( sizeof(dim_s2_s3_s4) , sizeof(int) );
+
+  // Rank 1 is size_t
+  ASSERT_EQ( sizeof(dim_s0) , sizeof(size_t) );
+  ASSERT_EQ( sizeof(dim_s0_s3) , sizeof(size_t) );
+  ASSERT_EQ( sizeof(dim_s0_s3_s4) , sizeof(size_t) );
+
+  // Allow for padding
+  ASSERT_LE( sizeof(dim_s0_s0) , 2 * sizeof(size_t) );
+  ASSERT_LE( sizeof(dim_s0_s0_s4) , 2 * sizeof(size_t) );
+
+  ASSERT_LE( sizeof(dim_s0_s0_s0) , 4 * sizeof(size_t) );
+  ASSERT_EQ( sizeof(dim_s0_s0_s0_s0) , 4 * sizeof(unsigned) );
+  ASSERT_LE( sizeof(dim_s0_s0_s0_s0_s0) , 6 * sizeof(unsigned) );
+  ASSERT_EQ( sizeof(dim_s0_s0_s0_s0_s0_s0) , 6 * sizeof(unsigned) );
+  ASSERT_LE( sizeof(dim_s0_s0_s0_s0_s0_s0_s0) , 8 * sizeof(unsigned) );
+  ASSERT_EQ( sizeof(dim_s0_s0_s0_s0_s0_s0_s0_s0) , 8 * sizeof(unsigned) );
+
+  ASSERT_EQ( int(dim_0::rank) , int(0) );
+  ASSERT_EQ( int(dim_0::rank_dynamic) , int(0) );
+
+  ASSERT_EQ( int(dim_s2::rank) , int(1) );
+  ASSERT_EQ( int(dim_s2::rank_dynamic) , int(0) );
+
+  ASSERT_EQ( int(dim_s2_s3::rank) , int(2) );
+  ASSERT_EQ( int(dim_s2_s3::rank_dynamic) , int(0) );
+
+  ASSERT_EQ( int(dim_s2_s3_s4::rank) , int(3) );
+  ASSERT_EQ( int(dim_s2_s3_s4::rank_dynamic) , int(0) );
+
+  ASSERT_EQ( int(dim_s0::rank) , int(1) );
+  ASSERT_EQ( int(dim_s0::rank_dynamic) , int(1) );
+
+  ASSERT_EQ( int(dim_s0_s3::rank) , int(2) );
+  ASSERT_EQ( int(dim_s0_s3::rank_dynamic) , int(1) );
+
+  ASSERT_EQ( int(dim_s0_s3_s4::rank) , int(3) );
+  ASSERT_EQ( int(dim_s0_s3_s4::rank_dynamic) , int(1) );
+
+  ASSERT_EQ( int(dim_s0_s0_s4::rank) , int(3) );
+  ASSERT_EQ( int(dim_s0_s0_s4::rank_dynamic) , int(2) );
+
+  ASSERT_EQ( int(dim_s0_s0_s0::rank) , int(3) );
+  ASSERT_EQ( int(dim_s0_s0_s0::rank_dynamic) , int(3) );
+
+  ASSERT_EQ( int(dim_s0_s0_s0_s0::rank) , int(4) );
+  ASSERT_EQ( int(dim_s0_s0_s0_s0::rank_dynamic) , int(4) );
+
+  ASSERT_EQ( int(dim_s0_s0_s0_s0_s0::rank) , int(5) );
+  ASSERT_EQ( int(dim_s0_s0_s0_s0_s0::rank_dynamic) , int(5) );
+
+  ASSERT_EQ( int(dim_s0_s0_s0_s0_s0_s0::rank) , int(6) );
+  ASSERT_EQ( int(dim_s0_s0_s0_s0_s0_s0::rank_dynamic) , int(6) );
+
+  ASSERT_EQ( int(dim_s0_s0_s0_s0_s0_s0_s0::rank) , int(7) );
+  ASSERT_EQ( int(dim_s0_s0_s0_s0_s0_s0_s0::rank_dynamic) , int(7) );
+
+  ASSERT_EQ( int(dim_s0_s0_s0_s0_s0_s0_s0_s0::rank) , int(8) );
+  ASSERT_EQ( int(dim_s0_s0_s0_s0_s0_s0_s0_s0::rank_dynamic) , int(8) );
+
+  dim_s0          d1( 2, 3, 4, 5, 6, 7, 8, 9 ); 
+  dim_s0_s0       d2( 2, 3, 4, 5, 6, 7, 8, 9 );
+  dim_s0_s0_s0    d3( 2, 3, 4, 5, 6, 7, 8, 9 );
+  dim_s0_s0_s0_s0 d4( 2, 3, 4, 5, 6, 7, 8, 9 );
+
+  ASSERT_EQ( d1.N0 , 2 );
+  ASSERT_EQ( d2.N0 , 2 );
+  ASSERT_EQ( d3.N0 , 2 );
+  ASSERT_EQ( d4.N0 , 2 );
+
+  ASSERT_EQ( d1.N1 , 1 );
+  ASSERT_EQ( d2.N1 , 3 );
+  ASSERT_EQ( d3.N1 , 3 );
+  ASSERT_EQ( d4.N1 , 3 );
+
+  ASSERT_EQ( d1.N2 , 1 );
+  ASSERT_EQ( d2.N2 , 1 );
+  ASSERT_EQ( d3.N2 , 4 );
+  ASSERT_EQ( d4.N2 , 4 );
+
+  ASSERT_EQ( d1.N3 , 1 );
+  ASSERT_EQ( d2.N3 , 1 );
+  ASSERT_EQ( d3.N3 , 1 );
+  ASSERT_EQ( d4.N3 , 5 );
+
+  //----------------------------------------
+
+  typedef Kokkos::Experimental::Impl::ViewOffset< dim_s0_s0_s0 , Kokkos::LayoutStride >  stride_s0_s0_s0 ;
+
+  //----------------------------------------
+  // Static dimension
+  {
+    typedef Kokkos::Experimental::Impl::ViewOffset< dim_s2_s3_s4 , Kokkos::LayoutLeft > left_s2_s3_s4 ;
+
+    ASSERT_EQ( sizeof(left_s2_s3_s4) , sizeof(dim_s2_s3_s4) );
+
+    left_s2_s3_s4 off3 ;
+
+    stride_s0_s0_s0  stride3( off3 );
+
+    ASSERT_EQ( off3.stride_0() , 1 );
+    ASSERT_EQ( off3.stride_1() , 2 );
+    ASSERT_EQ( off3.stride_2() , 6 );
+    ASSERT_EQ( off3.span() , 24 );
+
+    ASSERT_EQ( off3.stride_0() , stride3.stride_0() );
+    ASSERT_EQ( off3.stride_1() , stride3.stride_1() );
+    ASSERT_EQ( off3.stride_2() , stride3.stride_2() );
+    ASSERT_EQ( off3.span() , stride3.span() );
+
+    int offset = 0 ;
+
+    for ( int k = 0 ; k < 4 ; ++k ){
+    for ( int j = 0 ; j < 3 ; ++j ){
+    for ( int i = 0 ; i < 2 ; ++i , ++offset ){
+      ASSERT_EQ( off3(i,j,k) , offset );
+      ASSERT_EQ( stride3(i,j,k) , off3(i,j,k) );
+    }}}
+  }
+
+  //----------------------------------------
+  // Small dimension is unpadded
+  {
+    typedef Kokkos::Experimental::Impl::ViewOffset< dim_s0_s0_s4 , Kokkos::LayoutLeft > left_s0_s0_s4 ;
+
+    left_s0_s0_s4 dyn_off3( std::integral_constant<unsigned,sizeof(int)>()
+                          , Kokkos::LayoutLeft( 2, 3, 0, 0, 0, 0, 0, 0 ) );
+
+    stride_s0_s0_s0  stride3( dyn_off3 );
+
+    ASSERT_EQ( dyn_off3.m_dim.rank , 3 );
+    ASSERT_EQ( dyn_off3.m_dim.N0 , 2 );
+    ASSERT_EQ( dyn_off3.m_dim.N1 , 3 );
+    ASSERT_EQ( dyn_off3.m_dim.N2 , 4 );
+    ASSERT_EQ( dyn_off3.m_dim.N3 , 1 );
+    ASSERT_EQ( dyn_off3.size() , 2 * 3 * 4 );
+
+    const Kokkos::LayoutLeft layout = dyn_off3.layout();
+
+    ASSERT_EQ( layout.dimension[0] , 2 );
+    ASSERT_EQ( layout.dimension[1] , 3 );
+    ASSERT_EQ( layout.dimension[2] , 4 );
+    ASSERT_EQ( layout.dimension[3] , 1 );
+    ASSERT_EQ( layout.dimension[4] , 1 );
+    ASSERT_EQ( layout.dimension[5] , 1 );
+    ASSERT_EQ( layout.dimension[6] , 1 );
+    ASSERT_EQ( layout.dimension[7] , 1 );
+
+    ASSERT_EQ( stride3.m_dim.rank , 3 );
+    ASSERT_EQ( stride3.m_dim.N0 , 2 );
+    ASSERT_EQ( stride3.m_dim.N1 , 3 );
+    ASSERT_EQ( stride3.m_dim.N2 , 4 );
+    ASSERT_EQ( stride3.m_dim.N3 , 1 );
+    ASSERT_EQ( stride3.size() , 2 * 3 * 4 );
+
+    int offset = 0 ;
+
+    for ( int k = 0 ; k < 4 ; ++k ){
+    for ( int j = 0 ; j < 3 ; ++j ){
+    for ( int i = 0 ; i < 2 ; ++i , ++offset ){
+      ASSERT_EQ( offset , dyn_off3(i,j,k) );
+      ASSERT_EQ( stride3(i,j,k) , dyn_off3(i,j,k) );
+    }}}
+
+    ASSERT_EQ( dyn_off3.span() , offset );
+    ASSERT_EQ( stride3.span() , dyn_off3.span() );
+  }
+
+  // Large dimension is likely padded
+  {
+    constexpr int N0 = 2000 ;
+    constexpr int N1 = 300 ;
+
+    typedef Kokkos::Experimental::Impl::ViewOffset< dim_s0_s0_s4 , Kokkos::LayoutLeft > left_s0_s0_s4 ;
+
+    left_s0_s0_s4 dyn_off3( std::integral_constant<unsigned,sizeof(int)>()
+                          , Kokkos::LayoutLeft( N0, N1, 0, 0, 0, 0, 0, 0 ) );
+
+    stride_s0_s0_s0  stride3( dyn_off3 );
+
+    ASSERT_EQ( dyn_off3.m_dim.rank , 3 );
+    ASSERT_EQ( dyn_off3.m_dim.N0 , N0 );
+    ASSERT_EQ( dyn_off3.m_dim.N1 , N1 );
+    ASSERT_EQ( dyn_off3.m_dim.N2 , 4 );
+    ASSERT_EQ( dyn_off3.m_dim.N3 , 1 );
+    ASSERT_EQ( dyn_off3.size() , N0 * N1 * 4 );
+
+    ASSERT_EQ( stride3.m_dim.rank , 3 );
+    ASSERT_EQ( stride3.m_dim.N0 , N0 );
+    ASSERT_EQ( stride3.m_dim.N1 , N1 );
+    ASSERT_EQ( stride3.m_dim.N2 , 4 );
+    ASSERT_EQ( stride3.m_dim.N3 , 1 );
+    ASSERT_EQ( stride3.size() , N0 * N1 * 4 );
+    ASSERT_EQ( stride3.span() , dyn_off3.span() );
+
+    int offset = 0 ;
+
+    for ( int k = 0 ; k < 4 ; ++k ){
+    for ( int j = 0 ; j < N1 ; ++j ){
+    for ( int i = 0 ; i < N0 ; ++i ){
+      ASSERT_LE( offset , dyn_off3(i,j,k) );
+      ASSERT_EQ( stride3(i,j,k) , dyn_off3(i,j,k) );
+      offset = dyn_off3(i,j,k) + 1 ;
+    }}}
+
+    ASSERT_LE( offset , dyn_off3.span() );
+  }
+
+  //----------------------------------------
+  // Static dimension
+  {
+    typedef Kokkos::Experimental::Impl::ViewOffset< dim_s2_s3_s4 , Kokkos::LayoutRight > right_s2_s3_s4 ;
+
+    ASSERT_EQ( sizeof(right_s2_s3_s4) , sizeof(dim_s2_s3_s4) );
+
+    right_s2_s3_s4 off3 ;
+
+    stride_s0_s0_s0  stride3( off3 );
+
+    ASSERT_EQ( off3.stride_0() , 12 );
+    ASSERT_EQ( off3.stride_1() , 4 );
+    ASSERT_EQ( off3.stride_2() , 1 );
+
+    ASSERT_EQ( off3.dimension_0() , stride3.dimension_0() );
+    ASSERT_EQ( off3.dimension_1() , stride3.dimension_1() );
+    ASSERT_EQ( off3.dimension_2() , stride3.dimension_2() );
+    ASSERT_EQ( off3.stride_0() , stride3.stride_0() );
+    ASSERT_EQ( off3.stride_1() , stride3.stride_1() );
+    ASSERT_EQ( off3.stride_2() , stride3.stride_2() );
+    ASSERT_EQ( off3.span() , stride3.span() );
+
+    int offset = 0 ;
+
+    for ( int i = 0 ; i < 2 ; ++i ){
+    for ( int j = 0 ; j < 3 ; ++j ){
+    for ( int k = 0 ; k < 4 ; ++k , ++offset ){
+      ASSERT_EQ( off3(i,j,k) , offset );
+      ASSERT_EQ( off3(i,j,k) , stride3(i,j,k) );
+    }}}
+
+    ASSERT_EQ( off3.span() , offset );
+  }
+
+  //----------------------------------------
+  // Small dimension is unpadded
+  {
+    typedef Kokkos::Experimental::Impl::ViewOffset< dim_s0_s0_s4 , Kokkos::LayoutRight > right_s0_s0_s4 ;
+
+    right_s0_s0_s4 dyn_off3( std::integral_constant<unsigned,sizeof(int)>()
+                           , Kokkos::LayoutRight( 2, 3, 0, 0, 0, 0, 0, 0 ) );
+
+    stride_s0_s0_s0  stride3( dyn_off3 );
+
+    ASSERT_EQ( dyn_off3.m_dim.rank , 3 );
+    ASSERT_EQ( dyn_off3.m_dim.N0 , 2 );
+    ASSERT_EQ( dyn_off3.m_dim.N1 , 3 );
+    ASSERT_EQ( dyn_off3.m_dim.N2 , 4 );
+    ASSERT_EQ( dyn_off3.m_dim.N3 , 1 );
+    ASSERT_EQ( dyn_off3.size() , 2 * 3 * 4 );
+
+    ASSERT_EQ( dyn_off3.dimension_0() , stride3.dimension_0() );
+    ASSERT_EQ( dyn_off3.dimension_1() , stride3.dimension_1() );
+    ASSERT_EQ( dyn_off3.dimension_2() , stride3.dimension_2() );
+    ASSERT_EQ( dyn_off3.stride_0() , stride3.stride_0() );
+    ASSERT_EQ( dyn_off3.stride_1() , stride3.stride_1() );
+    ASSERT_EQ( dyn_off3.stride_2() , stride3.stride_2() );
+    ASSERT_EQ( dyn_off3.span() , stride3.span() );
+
+    int offset = 0 ;
+
+    for ( int i = 0 ; i < 2 ; ++i ){
+    for ( int j = 0 ; j < 3 ; ++j ){
+    for ( int k = 0 ; k < 4 ; ++k , ++offset ){
+      ASSERT_EQ( offset , dyn_off3(i,j,k) );
+      ASSERT_EQ( dyn_off3(i,j,k) , stride3(i,j,k) );
+    }}}
+
+    ASSERT_EQ( dyn_off3.span() , offset );
+  }
+
+  // Large dimension is likely padded
+  {
+    constexpr int N0 = 2000 ;
+    constexpr int N1 = 300 ;
+
+    typedef Kokkos::Experimental::Impl::ViewOffset< dim_s0_s0_s4 , Kokkos::LayoutRight > right_s0_s0_s4 ;
+
+    right_s0_s0_s4 dyn_off3( std::integral_constant<unsigned,sizeof(int)>()
+                           , Kokkos::LayoutRight( N0, N1, 0, 0, 0, 0, 0, 0 ) );
+
+    stride_s0_s0_s0  stride3( dyn_off3 );
+
+    ASSERT_EQ( dyn_off3.m_dim.rank , 3 );
+    ASSERT_EQ( dyn_off3.m_dim.N0 , N0 );
+    ASSERT_EQ( dyn_off3.m_dim.N1 , N1 );
+    ASSERT_EQ( dyn_off3.m_dim.N2 , 4 );
+    ASSERT_EQ( dyn_off3.m_dim.N3 , 1 );
+    ASSERT_EQ( dyn_off3.size() , N0 * N1 * 4 );
+
+    ASSERT_EQ( dyn_off3.dimension_0() , stride3.dimension_0() );
+    ASSERT_EQ( dyn_off3.dimension_1() , stride3.dimension_1() );
+    ASSERT_EQ( dyn_off3.dimension_2() , stride3.dimension_2() );
+    ASSERT_EQ( dyn_off3.stride_0() , stride3.stride_0() );
+    ASSERT_EQ( dyn_off3.stride_1() , stride3.stride_1() );
+    ASSERT_EQ( dyn_off3.stride_2() , stride3.stride_2() );
+    ASSERT_EQ( dyn_off3.span() , stride3.span() );
+
+    int offset = 0 ;
+
+    for ( int i = 0 ; i < N0 ; ++i ){
+    for ( int j = 0 ; j < N1 ; ++j ){
+    for ( int k = 0 ; k < 4 ; ++k ){
+      ASSERT_LE( offset , dyn_off3(i,j,k) );
+      ASSERT_EQ( dyn_off3(i,j,k) , stride3(i,j,k) );
+      offset = dyn_off3(i,j,k) + 1 ;
+    }}}
+
+    ASSERT_LE( offset , dyn_off3.span() );
+  }
+
+  //----------------------------------------
+  // Subview
+  {
+    // Mapping rank 4 to rank 3
+    typedef Kokkos::Experimental::Impl::SubviewExtents<4,3> SubviewExtents ;
+
+    constexpr int N0 = 1000 ;
+    constexpr int N1 = 2000 ;
+    constexpr int N2 = 3000 ;
+    constexpr int N3 = 4000 ;
+
+    Kokkos::Experimental::Impl::ViewDimension<N0,N1,N2,N3> dim ;
+
+    SubviewExtents tmp( dim
+                      , N0 / 2
+                      , Kokkos::Experimental::ALL
+                      , std::pair<int,int>( N2 / 4 , 10 + N2 / 4 )
+                      , Kokkos::pair<int,int>( N3 / 4 , 20 + N3 / 4 )
+                      );
+
+    ASSERT_EQ( tmp.domain_offset(0) , N0 / 2 );
+    ASSERT_EQ( tmp.domain_offset(1) , 0 );
+    ASSERT_EQ( tmp.domain_offset(2) , N2 / 4 );
+    ASSERT_EQ( tmp.domain_offset(3) , N3 / 4 );
+
+    ASSERT_EQ( tmp.range_index(0) , 1 );
+    ASSERT_EQ( tmp.range_index(1) , 2 );
+    ASSERT_EQ( tmp.range_index(2) , 3 );
+
+    ASSERT_EQ( tmp.range_extent(0) , N1 );
+    ASSERT_EQ( tmp.range_extent(1) , 10 );
+    ASSERT_EQ( tmp.range_extent(2) , 20 );
+  }
+  //----------------------------------------
+  {
+    constexpr int N0 = 2000 ;
+    constexpr int N1 = 300 ;
+
+    constexpr int sub_N0 = 1000 ;
+    constexpr int sub_N1 = 200 ;
+    constexpr int sub_N2 = 4 ;
+
+    typedef Kokkos::Experimental::Impl::ViewOffset< dim_s0_s0_s4 , Kokkos::LayoutLeft > left_s0_s0_s4 ;
+
+    left_s0_s0_s4 dyn_off3( std::integral_constant<unsigned,sizeof(int)>()
+                          , Kokkos::LayoutLeft( N0, N1, 0, 0, 0, 0, 0, 0 ) );
+
+    Kokkos::Experimental::Impl::SubviewExtents< 3 , 3 >
+      sub( dyn_off3.m_dim
+         , Kokkos::pair<int,int>(0,sub_N0)
+         , Kokkos::pair<int,int>(0,sub_N1)
+         , Kokkos::pair<int,int>(0,sub_N2)
+         );
+
+    stride_s0_s0_s0  stride3( dyn_off3 , sub );
+
+    ASSERT_EQ( stride3.dimension_0() , sub_N0 );
+    ASSERT_EQ( stride3.dimension_1() , sub_N1 );
+    ASSERT_EQ( stride3.dimension_2() , sub_N2 );
+    ASSERT_EQ( stride3.size() , sub_N0 * sub_N1 * sub_N2 );
+
+    ASSERT_EQ( dyn_off3.stride_0() , stride3.stride_0() );
+    ASSERT_EQ( dyn_off3.stride_1() , stride3.stride_1() );
+    ASSERT_EQ( dyn_off3.stride_2() , stride3.stride_2() );
+    ASSERT_GE( dyn_off3.span()   , stride3.span() );
+
+    for ( int k = 0 ; k < sub_N2 ; ++k ){
+    for ( int j = 0 ; j < sub_N1 ; ++j ){
+    for ( int i = 0 ; i < sub_N0 ; ++i ){
+      ASSERT_EQ( stride3(i,j,k) , dyn_off3(i,j,k) );
+    }}}
+  }
+
+  {
+    constexpr int N0 = 2000 ;
+    constexpr int N1 = 300 ;
+
+    constexpr int sub_N0 = 1000 ;
+    constexpr int sub_N1 = 200 ;
+    constexpr int sub_N2 = 4 ;
+
+    typedef Kokkos::Experimental::Impl::ViewOffset< dim_s0_s0_s4 , Kokkos::LayoutRight > right_s0_s0_s4 ;
+
+    right_s0_s0_s4 dyn_off3( std::integral_constant<unsigned,sizeof(int)>()
+                           , Kokkos::LayoutRight( N0, N1, 0, 0, 0, 0, 0, 0 ) );
+
+    Kokkos::Experimental::Impl::SubviewExtents< 3 , 3 >
+      sub( dyn_off3.m_dim
+         , Kokkos::pair<int,int>(0,sub_N0)
+         , Kokkos::pair<int,int>(0,sub_N1)
+         , Kokkos::pair<int,int>(0,sub_N2)
+         );
+
+    stride_s0_s0_s0  stride3( dyn_off3 , sub );
+
+    ASSERT_EQ( stride3.dimension_0() , sub_N0 );
+    ASSERT_EQ( stride3.dimension_1() , sub_N1 );
+    ASSERT_EQ( stride3.dimension_2() , sub_N2 );
+    ASSERT_EQ( stride3.size() , sub_N0 * sub_N1 * sub_N2 );
+
+    ASSERT_EQ( dyn_off3.stride_0() , stride3.stride_0() );
+    ASSERT_EQ( dyn_off3.stride_1() , stride3.stride_1() );
+    ASSERT_EQ( dyn_off3.stride_2() , stride3.stride_2() );
+    ASSERT_GE( dyn_off3.span()   , stride3.span() );
+
+    for ( int i = 0 ; i < sub_N0 ; ++i ){
+    for ( int j = 0 ; j < sub_N1 ; ++j ){
+    for ( int k = 0 ; k < sub_N2 ; ++k ){
+      ASSERT_EQ( stride3(i,j,k) , dyn_off3(i,j,k) );
+    }}}
+  }
+
+  //----------------------------------------
+  // view data analysis
+  {
+    using namespace Kokkos::Experimental::Impl ;
+    static_assert( rank_dynamic<>::value == 0 , "" );
+    static_assert( rank_dynamic<1>::value == 0 , "" );
+    static_assert( rank_dynamic<0>::value == 1 , "" );
+    static_assert( rank_dynamic<0,1>::value == 1 , "" );
+    static_assert( rank_dynamic<0,0,1>::value == 2 , "" );
+  }
+
+  {
+    using namespace Kokkos::Experimental::Impl ;
+
+    typedef ViewArrayAnalysis< int[] >                 a_int_r1 ;
+    typedef ViewArrayAnalysis< int**[4][5][6] >        a_int_r5 ;
+    typedef ViewArrayAnalysis< const int[] >           a_const_int_r1 ;
+    typedef ViewArrayAnalysis< const int**[4][5][6] >  a_const_int_r5 ;
+
+    static_assert( a_int_r1::dimension::rank == 1 , "" );
+    static_assert( a_int_r1::dimension::rank_dynamic == 1 , "" );
+    static_assert( std::is_same< typename a_int_r1::dimension , ViewDimension<0> >::value , "" );
+    static_assert( std::is_same< typename a_int_r1::non_const_value_type , int >::value , "" );
+
+    static_assert( a_const_int_r1::dimension::rank == 1 , "" );
+    static_assert( a_const_int_r1::dimension::rank_dynamic == 1 , "" );
+    static_assert( std::is_same< typename a_const_int_r1::dimension , ViewDimension<0> >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r1::non_const_value_type , int >::value , "" );
+
+    static_assert( a_const_int_r5::dimension::rank == 5 , "" );
+    static_assert( a_const_int_r5::dimension::rank_dynamic == 2 , "" );
+
+    static_assert( std::is_same< typename a_const_int_r5::dimension , ViewDimension<0,0,4,5,6> >::value , "" );
+
+    static_assert( std::is_same< typename a_const_int_r5::non_const_value_type , int >::value , "" );
+
+    static_assert( a_int_r5::dimension::rank == 5 , "" );
+    static_assert( a_int_r5::dimension::rank_dynamic == 2 , "" );
+    static_assert( std::is_same< typename a_int_r5::dimension , ViewDimension<0,0,4,5,6> >::value , "" );
+    static_assert( std::is_same< typename a_int_r5::non_const_value_type , int >::value , "" );
+  }
+
+  {
+    using namespace Kokkos::Experimental::Impl ;
+
+    typedef int t_i4[4] ;
+
+    // Dimensions of t_i4 are appended to the multdimensional array.
+    typedef ViewArrayAnalysis< t_i4 ***[3] > a_int_r5 ;
+
+    static_assert( a_int_r5::dimension::rank == 5 , "" );
+    static_assert( a_int_r5::dimension::rank_dynamic == 3 , "" );
+    static_assert( a_int_r5::dimension::ArgN0 == 0 , "" );
+    static_assert( a_int_r5::dimension::ArgN1 == 0 , "" );
+    static_assert( a_int_r5::dimension::ArgN2 == 0 , "" );
+    static_assert( a_int_r5::dimension::ArgN3 == 3 , "" );
+    static_assert( a_int_r5::dimension::ArgN4 == 4 , "" );
+    static_assert( std::is_same< typename a_int_r5::non_const_value_type , int >::value , "" );
+  }
+
+  {
+    using namespace Kokkos::Experimental::Impl ;
+
+    typedef ViewDataAnalysis< const int[] , void >  a_const_int_r1 ;
+
+    static_assert( std::is_same< typename a_const_int_r1::specialize , void >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r1::dimension , Kokkos::Experimental::Impl::ViewDimension<0> >::value , "" );
+
+    static_assert( std::is_same< typename a_const_int_r1::type , const int * >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r1::value_type , const int >::value , "" );
+
+    static_assert( std::is_same< typename a_const_int_r1::scalar_array_type , const int * >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r1::const_type , const int * >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r1::const_value_type , const int >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r1::const_scalar_array_type , const int * >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r1::non_const_type , int * >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r1::non_const_value_type , int >::value , "" );
+
+    typedef ViewDataAnalysis< const int**[4] , void >  a_const_int_r3 ;
+
+    static_assert( std::is_same< typename a_const_int_r3::specialize , void >::value , "" );
+
+    static_assert( std::is_same< typename a_const_int_r3::dimension , Kokkos::Experimental::Impl::ViewDimension<0,0,4> >::value , "" );
+
+    static_assert( std::is_same< typename a_const_int_r3::type , const int**[4] >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r3::value_type , const int >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r3::scalar_array_type , const int**[4] >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r3::const_type , const int**[4] >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r3::const_value_type , const int >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r3::const_scalar_array_type , const int**[4] >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r3::non_const_type , int**[4] >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r3::non_const_value_type , int >::value , "" );
+    static_assert( std::is_same< typename a_const_int_r3::non_const_scalar_array_type , int**[4] >::value , "" );
+
+
+    // std::cout << "typeid(const int**[4]).name() = " << typeid(const int**[4]).name() << std::endl ;
+  }
+
+  //----------------------------------------
+
+  {
+    constexpr int N = 10 ;
+
+    typedef Kokkos::Experimental::View<int*,Space>        T ;
+    typedef Kokkos::Experimental::View<const int*,Space>  C ;
+
+    int data[N] ;
+
+    T vr1(data,N); // view of non-const
+    C cr1(vr1);    // view of const from view of non-const
+    C cr2( (const int *) data , N );
+
+    // Generate static_assert error:
+    // T tmp( cr1 );
+
+    ASSERT_EQ( vr1.span() , N );
+    ASSERT_EQ( cr1.span() , N );
+    ASSERT_EQ( vr1.data() , & data[0] );
+    ASSERT_EQ( cr1.data() , & data[0] );
+
+    ASSERT_TRUE( ( std::is_same< typename T::data_type           , int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::const_data_type     , const int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::non_const_data_type , int* >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename T::scalar_array_type           , int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::const_scalar_array_type     , const int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::non_const_scalar_array_type , int* >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename T::value_type           , int >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::const_value_type     , const int >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::non_const_value_type , int >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename T::memory_space , typename Space::memory_space >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::reference_type , int & >::value ) );
+
+    ASSERT_EQ( T::Rank , 1 );
+
+    ASSERT_TRUE( ( std::is_same< typename C::data_type           , const int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename C::const_data_type     , const int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename C::non_const_data_type , int* >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename C::scalar_array_type           , const int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename C::const_scalar_array_type     , const int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename C::non_const_scalar_array_type , int* >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename C::value_type           , const int >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename C::const_value_type     , const int >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename C::non_const_value_type , int >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename C::memory_space , typename Space::memory_space >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename C::reference_type , const int & >::value ) );
+
+    ASSERT_EQ( C::Rank , 1 );
+
+    ASSERT_EQ( vr1.dimension_0() , N );
+
+    if ( Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename Space::memory_space , Kokkos::HostSpace >::value ) {
+      for ( int i = 0 ; i < N ; ++i ) data[i] = i + 1 ;
+      for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( vr1[i] , i + 1 );
+      for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( cr1[i] , i + 1 );
+
+      {
+        T tmp( vr1 );
+        for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( tmp[i] , i + 1 );
+        for ( int i = 0 ; i < N ; ++i ) vr1(i) = i + 2 ;
+        for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( tmp[i] , i + 2 );
+      }
+
+      for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( vr1[i] , i + 2 );
+    }
+  }
+
+
+  {
+    constexpr int N = 10 ;
+    typedef Kokkos::Experimental::View<int*,Space>        T ;
+    typedef Kokkos::Experimental::View<const int*,Space>  C ;
+
+    T vr1("vr1",N);
+    C cr1(vr1);
+
+    ASSERT_TRUE( ( std::is_same< typename T::data_type           , int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::const_data_type     , const int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::non_const_data_type , int* >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename T::scalar_array_type           , int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::const_scalar_array_type     , const int* >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::non_const_scalar_array_type , int* >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename T::value_type           , int >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::const_value_type     , const int >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::non_const_value_type , int >::value ) );
+
+    ASSERT_TRUE( ( std::is_same< typename T::memory_space , typename Space::memory_space >::value ) );
+    ASSERT_TRUE( ( std::is_same< typename T::reference_type , int & >::value ) );
+    ASSERT_EQ( T::Rank , 1 );
+ 
+    ASSERT_EQ( vr1.dimension_0() , N );
+
+    if ( Kokkos::Impl::VerifyExecutionCanAccessMemorySpace< typename Space::memory_space , Kokkos::HostSpace >::value ) {
+      for ( int i = 0 ; i < N ; ++i ) vr1(i) = i + 1 ;
+      for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( vr1[i] , i + 1 );
+      for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( cr1[i] , i + 1 );
+
+      {
+        T tmp( vr1 );
+        for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( tmp[i] , i + 1 );
+        for ( int i = 0 ; i < N ; ++i ) vr1(i) = i + 2 ;
+        for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( tmp[i] , i + 2 );
+      }
+
+      for ( int i = 0 ; i < N ; ++i ) ASSERT_EQ( vr1[i] , i + 2 );
+    }
+  }
+
+  // Testing proper handling of zero-length allocations
+  {
+    constexpr int N = 0 ;
+    typedef Kokkos::Experimental::View<int*,Space>        T ;
+    typedef Kokkos::Experimental::View<const int*,Space>  C ;
+
+    T vr1("vr1",N);
+    C cr1(vr1);
+
+    ASSERT_EQ( vr1.dimension_0() , 0 );
+    ASSERT_EQ( cr1.dimension_0() , 0 );
+  }
+
+
+  // Testing using space instance for allocation.
+  // The execution space of the memory space must be available for view data initialization
+
+  if ( std::is_same< ExecSpace , typename ExecSpace::memory_space::execution_space >::value ) {
+
+    using namespace Kokkos::Experimental ;
+
+    typedef typename ExecSpace::memory_space  memory_space ;
+    typedef View<int*,memory_space>           V ;
+
+    constexpr int N = 10 ;
+
+    memory_space mem_space ;
+
+    V v( "v" , N );
+    V va( view_alloc() , N );
+    V vb( view_alloc( "vb" ) , N );
+    V vc( view_alloc( "vc" , AllowPadding ) , N );
+    V vd( view_alloc( "vd" , WithoutInitializing ) , N );
+    V ve( view_alloc( "ve" , WithoutInitializing , AllowPadding ) , N );
+    V vf( view_alloc( "vf" , mem_space , WithoutInitializing , AllowPadding ) , N );
+    V vg( view_alloc( mem_space , "vg" , WithoutInitializing , AllowPadding ) , N );
+    V vh( view_alloc( WithoutInitializing , AllowPadding ) , N );
+    V vi( view_alloc( WithoutInitializing ) , N );
+    V vj( view_alloc( std::string("vj") , AllowPadding ) , N );
+    V vk( view_alloc( mem_space , std::string("vk") , AllowPadding ) , N );
+  }
+
+  {
+    typedef Kokkos::Experimental::ViewTraits<int***,Kokkos::LayoutStride,ExecSpace>  traits_t ;
+    typedef Kokkos::Experimental::Impl::ViewDimension<0,0,0>                         dims_t ;
+    typedef Kokkos::Experimental::Impl::ViewOffset< dims_t , Kokkos::LayoutStride >  offset_t ;
+
+    Kokkos::LayoutStride stride ;
+
+    stride.dimension[0] = 3 ;
+    stride.dimension[1] = 4 ;
+    stride.dimension[2] = 5 ;
+    stride.stride[0] = 4 ;
+    stride.stride[1] = 1 ;
+    stride.stride[2] = 12 ;
+
+    const offset_t offset( std::integral_constant<unsigned,0>() , stride );
+
+    ASSERT_EQ( offset.dimension_0() , 3 );
+    ASSERT_EQ( offset.dimension_1() , 4 );
+    ASSERT_EQ( offset.dimension_2() , 5 );
+
+    ASSERT_EQ( offset.stride_0() , 4 );
+    ASSERT_EQ( offset.stride_1() , 1 );
+    ASSERT_EQ( offset.stride_2() , 12 );
+
+    ASSERT_EQ( offset.span() , 60 );
+    ASSERT_TRUE( offset.span_is_contiguous() );
+
+    Kokkos::Experimental::Impl::ViewMapping< traits_t , void >
+      v( Kokkos::Experimental::Impl::ViewCtorProp<int*>((int*)0), stride );
+  }
+
+  {
+    typedef Kokkos::Experimental::View<int**,Space>  V ;
+    typedef typename V::HostMirror  M ;
+
+    constexpr int N0 = 10 ;
+    constexpr int N1 = 11 ;
+
+    V a("a",N0,N1);
+    M b = Kokkos::Experimental::create_mirror(a);
+    M c = Kokkos::Experimental::create_mirror_view(a);
+    M d ;
+
+    for ( int i0 = 0 ; i0 < N0 ; ++i0 )
+    for ( int i1 = 0 ; i1 < N1 ; ++i1 )
+      b(i0,i1) = 1 + i0 + i1 * N0 ;
+
+    Kokkos::Experimental::deep_copy( a , b );
+    Kokkos::Experimental::deep_copy( c , a );
+
+    for ( int i0 = 0 ; i0 < N0 ; ++i0 )
+    for ( int i1 = 0 ; i1 < N1 ; ++i1 )
+      ASSERT_EQ( b(i0,i1) , c(i0,i1) );
+
+    Kokkos::Experimental::resize( b , 5 , 6 );
+    Kokkos::Experimental::realloc( c , 5 , 6 );
+    Kokkos::Experimental::realloc( d , 5 , 6 );
+
+    ASSERT_EQ( b.dimension_0() , 5 );
+    ASSERT_EQ( b.dimension_1() , 6 );
+    ASSERT_EQ( c.dimension_0() , 5 );
+    ASSERT_EQ( c.dimension_1() , 6 );
+    ASSERT_EQ( d.dimension_0() , 5 );
+    ASSERT_EQ( d.dimension_1() , 6 );
+  }
+
+  {
+    typedef Kokkos::Experimental::View<int*,Space> V ;
+    typedef Kokkos::Experimental::View<int*,Space,Kokkos::MemoryUnmanaged> U ;
+
+
+    V a("a",10);
+
+    ASSERT_EQ( a.use_count() , 1 );
+
+    V b = a ;
+
+    ASSERT_EQ( a.use_count() , 2 );
+    ASSERT_EQ( b.use_count() , 2 );
+
+    {
+      U c = b ; // 'c' is compile-time unmanaged
+
+      ASSERT_EQ( a.use_count() , 2 );
+      ASSERT_EQ( b.use_count() , 2 );
+      ASSERT_EQ( c.use_count() , 2 );
+
+      V d = c ; // 'd' is run-time unmanaged
+
+      ASSERT_EQ( a.use_count() , 2 );
+      ASSERT_EQ( b.use_count() , 2 );
+      ASSERT_EQ( c.use_count() , 2 );
+      ASSERT_EQ( d.use_count() , 2 );
+    }
+
+    ASSERT_EQ( a.use_count() , 2 );
+    ASSERT_EQ( b.use_count() , 2 );
+
+    b = V();
+
+    ASSERT_EQ( a.use_count() , 1 );
+    ASSERT_EQ( b.use_count() , 0 );
+
+#if KOKKOS_USING_EXP_VIEW && ! defined ( KOKKOS_CUDA_USE_LAMBDA )
+    /* Cannot launch host lambda when CUDA lambda is enabled */
+
+    typedef typename Kokkos::Impl::is_space< Space >::host_execution_space
+      host_exec_space ;
+
+    Kokkos::parallel_for(
+      Kokkos::RangePolicy< host_exec_space >(0,10) ,
+      KOKKOS_LAMBDA( int i ){
+        // 'a' is captured by copy and the capture mechanism
+        // converts 'a' to an unmanaged copy.
+        // When the parallel dispatch accepts a move for the lambda
+        // this count should become 1
+        ASSERT_EQ( a.use_count() , 2 );
+        V x = a ;
+        ASSERT_EQ( a.use_count() , 2 );
+        ASSERT_EQ( x.use_count() , 2 );
+      });
+#endif /* #if ! defined ( KOKKOS_CUDA_USE_LAMBDA ) */
+  }
+}
+
+template< class Space >
+struct TestViewMappingSubview
+{
+  typedef typename Space::execution_space ExecSpace ;
+  typedef typename Space::memory_space    MemSpace ;
+
+  typedef Kokkos::pair<int,int> range ;
+
+  enum { AN = 10 };
+  typedef Kokkos::Experimental::View<int*,ExecSpace>  AT ;
+  typedef Kokkos::Experimental::View<const int*,ExecSpace>  ACT ;
+  typedef Kokkos::Experimental::Subview< AT , range >  AS ;
+
+  enum { BN0 = 10 , BN1 = 11 , BN2 = 12 };
+  typedef Kokkos::Experimental::View<int***,ExecSpace>  BT ;
+  typedef Kokkos::Experimental::Subview< BT , range , range , range >  BS ;
+
+  enum { CN0 = 10 , CN1 = 11 , CN2 = 12 };
+  typedef Kokkos::Experimental::View<int***[13][14],ExecSpace>  CT ;
+  typedef Kokkos::Experimental::Subview< CT , range , range , range , int , int >  CS ;
+
+  enum { DN0 = 10 , DN1 = 11 , DN2 = 12 , DN3 = 13 , DN4 = 14 };
+  typedef Kokkos::Experimental::View<int***[DN3][DN4],ExecSpace>  DT ;
+  typedef Kokkos::Experimental::Subview< DT , int , range , range , range , int >  DS ;
+
+
+  typedef Kokkos::Experimental::View<int***[13][14],Kokkos::LayoutLeft,ExecSpace>  DLT ;
+  typedef Kokkos::Experimental::Subview< DLT , range , int , int , int , int >  DLS1 ;
+
+  static_assert( DLS1::rank == 1 && std::is_same< typename DLS1::array_layout , Kokkos::LayoutLeft >::value
+               , "Subview layout error for rank 1 subview of left-most range of LayoutLeft" );
+
+  typedef Kokkos::Experimental::View<int***[13][14],Kokkos::LayoutRight,ExecSpace>  DRT ;
+  typedef Kokkos::Experimental::Subview< DRT , int , int , int , int , range >  DRS1 ;
+
+  static_assert( DRS1::rank == 1 && std::is_same< typename DRS1::array_layout , Kokkos::LayoutRight >::value
+               , "Subview layout error for rank 1 subview of right-most range of LayoutRight" );
+
+  AT Aa ;
+  AS Ab ;
+  ACT Ac ;
+  BT Ba ;
+  BS Bb ;
+  CT Ca ;
+  CS Cb ;
+  DT Da ;
+  DS Db ;
+
+  TestViewMappingSubview()
+    : Aa("Aa",AN)
+    , Ab( Kokkos::Experimental::subview( Aa , std::pair<int,int>(1,AN-1) ) )
+    , Ac( Aa , std::pair<int,int>(1,AN-1) )
+    , Ba("Ba",BN0,BN1,BN2)
+    , Bb( Kokkos::Experimental::subview( Ba
+                                        , std::pair<int,int>(1,BN0-1)
+                                        , std::pair<int,int>(1,BN1-1)
+                                        , std::pair<int,int>(1,BN2-1)
+                                        ) )
+    , Ca("Ca",CN0,CN1,CN2)
+    , Cb( Kokkos::Experimental::subview( Ca
+                                        , std::pair<int,int>(1,CN0-1)
+                                        , std::pair<int,int>(1,CN1-1)
+                                        , std::pair<int,int>(1,CN2-1)
+                                        , 1
+                                        , 2
+                                        ) )
+    , Da("Da",DN0,DN1,DN2)
+    , Db( Kokkos::Experimental::subview( Da
+                                        , 1
+                                        , std::pair<int,int>(1,DN1-1)
+                                        , std::pair<int,int>(1,DN2-1)
+                                        , std::pair<int,int>(1,DN3-1)
+                                        , 2
+                                        ) )
+    {
+    }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int , long & error_count ) const
+    {
+      auto Ad = Kokkos::Experimental::subview< Kokkos::MemoryUnmanaged >( Aa , Kokkos::pair<int,int>(1,AN-1) );
+
+      for ( int i = 1 ; i < AN-1 ; ++i ) if( & Aa[i] != & Ab[i-1] ) ++error_count ;
+      for ( int i = 1 ; i < AN-1 ; ++i ) if( & Aa[i] != & Ac[i-1] ) ++error_count ;
+      for ( int i = 1 ; i < AN-1 ; ++i ) if( & Aa[i] != & Ad[i-1] ) ++error_count ;
+
+      for ( int i2 = 1 ; i2 < BN2-1 ; ++i2 ) {
+      for ( int i1 = 1 ; i1 < BN1-1 ; ++i1 ) {
+      for ( int i0 = 1 ; i0 < BN0-1 ; ++i0 ) {
+        if ( & Ba(i0,i1,i2) != & Bb(i0-1,i1-1,i2-1) ) ++error_count ;
+      }}}
+
+      for ( int i2 = 1 ; i2 < CN2-1 ; ++i2 ) {
+      for ( int i1 = 1 ; i1 < CN1-1 ; ++i1 ) {
+      for ( int i0 = 1 ; i0 < CN0-1 ; ++i0 ) {
+        if ( & Ca(i0,i1,i2,1,2) != & Cb(i0-1,i1-1,i2-1) ) ++error_count ;
+      }}}
+
+      for ( int i2 = 1 ; i2 < DN3-1 ; ++i2 ) {
+      for ( int i1 = 1 ; i1 < DN2-1 ; ++i1 ) {
+      for ( int i0 = 1 ; i0 < DN1-1 ; ++i0 ) {
+        if ( & Da(1,i0,i1,i2,2) != & Db(i0-1,i1-1,i2-1) ) ++error_count ;
+      }}}
+    }
+
+  static void run()
+  {
+    TestViewMappingSubview self ;
+
+    ASSERT_EQ( self.Aa.dimension_0() , AN );
+    ASSERT_EQ( self.Ab.dimension_0() , AN - 2 );
+    ASSERT_EQ( self.Ac.dimension_0() , AN - 2 );
+    ASSERT_EQ( self.Ba.dimension_0() , BN0 );
+    ASSERT_EQ( self.Ba.dimension_1() , BN1 );
+    ASSERT_EQ( self.Ba.dimension_2() , BN2 );
+    ASSERT_EQ( self.Bb.dimension_0() , BN0 - 2 );
+    ASSERT_EQ( self.Bb.dimension_1() , BN1 - 2 );
+    ASSERT_EQ( self.Bb.dimension_2() , BN2 - 2 );
+
+    ASSERT_EQ( self.Ca.dimension_0() , CN0 );
+    ASSERT_EQ( self.Ca.dimension_1() , CN1 );
+    ASSERT_EQ( self.Ca.dimension_2() , CN2 );
+    ASSERT_EQ( self.Ca.dimension_3() , 13 );
+    ASSERT_EQ( self.Ca.dimension_4() , 14 );
+    ASSERT_EQ( self.Cb.dimension_0() , CN0 - 2 );
+    ASSERT_EQ( self.Cb.dimension_1() , CN1 - 2 );
+    ASSERT_EQ( self.Cb.dimension_2() , CN2 - 2 );
+
+    ASSERT_EQ( self.Da.dimension_0() , DN0 );
+    ASSERT_EQ( self.Da.dimension_1() , DN1 );
+    ASSERT_EQ( self.Da.dimension_2() , DN2 );
+    ASSERT_EQ( self.Da.dimension_3() , DN3 );
+    ASSERT_EQ( self.Da.dimension_4() , DN4 );
+
+    ASSERT_EQ( self.Db.dimension_0() , DN1 - 2 );
+    ASSERT_EQ( self.Db.dimension_1() , DN2 - 2 );
+    ASSERT_EQ( self.Db.dimension_2() , DN3 - 2 );
+
+    ASSERT_EQ( self.Da.stride_1() , self.Db.stride_0() );
+    ASSERT_EQ( self.Da.stride_2() , self.Db.stride_1() );
+    ASSERT_EQ( self.Da.stride_3() , self.Db.stride_2() );
+
+    long error_count = -1 ;
+    Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace >(0,1) , self , error_count );
+    ASSERT_EQ( error_count , 0 );
+  }
+
+};
+
+template< class Space >
+void test_view_mapping_subview()
+{
+  typedef typename Space::execution_space ExecSpace ;
+
+  TestViewMappingSubview< ExecSpace >::run();
+}
+
+/*--------------------------------------------------------------------------*/
+
+template< class ViewType >
+struct TestViewMapOperator {
+
+  static_assert( ViewType::reference_type_is_lvalue_reference
+               , "Test only valid for lvalue reference type" );
+
+  const ViewType v ;
+
+  KOKKOS_INLINE_FUNCTION
+  void test_left( size_t i0 , long & error_count ) const
+    {
+      typename ViewType::value_type * const base_ptr = & v(0,0,0,0,0,0,0,0);
+      const size_t n1 = v.dimension_1();
+      const size_t n2 = v.dimension_2();
+      const size_t n3 = v.dimension_3();
+      const size_t n4 = v.dimension_4();
+      const size_t n5 = v.dimension_5();
+      const size_t n6 = v.dimension_6();
+      const size_t n7 = v.dimension_7();
+
+      long offset = 0 ;
+
+      for ( size_t i7 = 0 ; i7 < n7 ; ++i7 )
+      for ( size_t i6 = 0 ; i6 < n6 ; ++i6 )
+      for ( size_t i5 = 0 ; i5 < n5 ; ++i5 )
+      for ( size_t i4 = 0 ; i4 < n4 ; ++i4 )
+      for ( size_t i3 = 0 ; i3 < n3 ; ++i3 )
+      for ( size_t i2 = 0 ; i2 < n2 ; ++i2 )
+      for ( size_t i1 = 0 ; i1 < n1 ; ++i1 )
+      {
+        const long d = & v(i0,i1,i2,i3,i4,i5,i6,i7) - base_ptr ;
+        if ( d < offset ) ++error_count ;
+        offset = d ;
+      }
+
+      if ( v.span() <= size_t(offset) ) ++error_count ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void test_right( size_t i0 , long & error_count ) const
+    {
+      typename ViewType::value_type * const base_ptr = & v(0,0,0,0,0,0,0,0);
+      const size_t n1 = v.dimension_1();
+      const size_t n2 = v.dimension_2();
+      const size_t n3 = v.dimension_3();
+      const size_t n4 = v.dimension_4();
+      const size_t n5 = v.dimension_5();
+      const size_t n6 = v.dimension_6();
+      const size_t n7 = v.dimension_7();
+
+      long offset = 0 ;
+
+      for ( size_t i1 = 0 ; i1 < n1 ; ++i1 )
+      for ( size_t i2 = 0 ; i2 < n2 ; ++i2 )
+      for ( size_t i3 = 0 ; i3 < n3 ; ++i3 )
+      for ( size_t i4 = 0 ; i4 < n4 ; ++i4 )
+      for ( size_t i5 = 0 ; i5 < n5 ; ++i5 )
+      for ( size_t i6 = 0 ; i6 < n6 ; ++i6 )
+      for ( size_t i7 = 0 ; i7 < n7 ; ++i7 )
+      {
+        const long d = & v(i0,i1,i2,i3,i4,i5,i6,i7) - base_ptr ;
+        if ( d < offset ) ++error_count ;
+        offset = d ;
+      }
+
+      if ( v.span() <= size_t(offset) ) ++error_count ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_t i , long & error_count ) const
+    {
+      if ( std::is_same< typename ViewType::array_layout , Kokkos::LayoutLeft >::value )
+        test_left(i,error_count);
+      else if ( std::is_same< typename ViewType::array_layout , Kokkos::LayoutRight >::value )
+        test_right(i,error_count);
+    }
+
+  constexpr static size_t N0 = 10 ;
+  constexpr static size_t N1 =  9 ;
+  constexpr static size_t N2 =  8 ;
+  constexpr static size_t N3 =  7 ;
+  constexpr static size_t N4 =  6 ;
+  constexpr static size_t N5 =  5 ;
+  constexpr static size_t N6 =  4 ;
+  constexpr static size_t N7 =  3 ;
+
+  TestViewMapOperator() : v( "Test" , N0, N1, N2, N3, N4, N5, N6, N7 ) {}
+
+  static void run()
+    {
+      TestViewMapOperator self ;
+
+      ASSERT_EQ( self.v.dimension_0() , ( 0 < ViewType::rank ? N0 : 1 ) );
+      ASSERT_EQ( self.v.dimension_1() , ( 1 < ViewType::rank ? N1 : 1 ) );
+      ASSERT_EQ( self.v.dimension_2() , ( 2 < ViewType::rank ? N2 : 1 ) );
+      ASSERT_EQ( self.v.dimension_3() , ( 3 < ViewType::rank ? N3 : 1 ) );
+      ASSERT_EQ( self.v.dimension_4() , ( 4 < ViewType::rank ? N4 : 1 ) );
+      ASSERT_EQ( self.v.dimension_5() , ( 5 < ViewType::rank ? N5 : 1 ) );
+      ASSERT_EQ( self.v.dimension_6() , ( 6 < ViewType::rank ? N6 : 1 ) );
+      ASSERT_EQ( self.v.dimension_7() , ( 7 < ViewType::rank ? N7 : 1 ) );
+
+      ASSERT_LE( self.v.dimension_0()*
+                 self.v.dimension_1()*
+                 self.v.dimension_2()*
+                 self.v.dimension_3()*
+                 self.v.dimension_4()*
+                 self.v.dimension_5()*
+                 self.v.dimension_6()*
+                 self.v.dimension_7()
+               , self.v.span() );
+
+      long error_count ;
+      Kokkos::RangePolicy< typename ViewType::execution_space > range(0,self.v.dimension_0());
+      Kokkos::parallel_reduce( range , self , error_count );
+      ASSERT_EQ( 0 , error_count );
+    }
+};
+
+
+template< class Space >
+void test_view_mapping_operator()
+{
+  typedef typename Space::execution_space ExecSpace ;
+
+  TestViewMapOperator< Kokkos::Experimental::View<int,Kokkos::LayoutLeft,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int*,Kokkos::LayoutLeft,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int**,Kokkos::LayoutLeft,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int***,Kokkos::LayoutLeft,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int****,Kokkos::LayoutLeft,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int*****,Kokkos::LayoutLeft,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int******,Kokkos::LayoutLeft,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int*******,Kokkos::LayoutLeft,ExecSpace> >::run();
+
+  TestViewMapOperator< Kokkos::Experimental::View<int,Kokkos::LayoutRight,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int*,Kokkos::LayoutRight,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int**,Kokkos::LayoutRight,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int***,Kokkos::LayoutRight,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int****,Kokkos::LayoutRight,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int*****,Kokkos::LayoutRight,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int******,Kokkos::LayoutRight,ExecSpace> >::run();
+  TestViewMapOperator< Kokkos::Experimental::View<int*******,Kokkos::LayoutRight,ExecSpace> >::run();
+}
+
+/*--------------------------------------------------------------------------*/
+
+template< class Space >
+struct TestViewMappingAtomic {
+  typedef typename Space::execution_space ExecSpace ;
+  typedef typename Space::memory_space    MemSpace ;
+
+  typedef Kokkos::MemoryTraits< Kokkos::Atomic >  mem_trait ;
+
+  typedef Kokkos::Experimental::View< int * , ExecSpace > T ;
+  typedef Kokkos::Experimental::View< int * , ExecSpace , mem_trait >  T_atom ;
+
+  T      x ;
+  T_atom x_atom ;
+
+  constexpr static size_t N = 100000 ;
+
+  struct TagInit {};
+  struct TagUpdate {};
+  struct TagVerify {};
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TagInit & , const int i ) const
+    { x(i) = i ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TagUpdate & , const int i ) const
+    { x_atom(i%2) += 1 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TagVerify & , const int i , long & error_count ) const
+    {
+       if ( i < 2 ) { if ( x(i) != int(i + N / 2) ) ++error_count ; }
+       else         { if ( x(i) != int(i) ) ++error_count ; }
+    }
+
+  TestViewMappingAtomic()
+    : x("x",N)
+    , x_atom( x )
+    {}
+
+  static void run()
+    {
+      ASSERT_TRUE( T::reference_type_is_lvalue_reference );
+      ASSERT_FALSE( T_atom::reference_type_is_lvalue_reference );
+
+      TestViewMappingAtomic self ;
+      Kokkos::parallel_for( Kokkos::RangePolicy< ExecSpace , TagInit >(0,N) , self );
+      Kokkos::parallel_for( Kokkos::RangePolicy< ExecSpace , TagUpdate >(0,N) , self );
+      long error_count = -1 ;
+      Kokkos::parallel_reduce( Kokkos::RangePolicy< ExecSpace , TagVerify >(0,N) , self , error_count );
+      ASSERT_EQ( 0 , error_count );
+    }
+};
+
+/*--------------------------------------------------------------------------*/
+
+template< class Space >
+struct TestViewMappingClassValue {
+  typedef typename Space::execution_space ExecSpace ;
+  typedef typename Space::memory_space    MemSpace ;
+
+  struct ValueType {
+    KOKKOS_INLINE_FUNCTION
+    ValueType()
+    {
+#if 0
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_CUDA )
+      printf("TestViewMappingClassValue construct on Cuda\n");
+#elif defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      printf("TestViewMappingClassValue construct on Host\n");
+#else
+      printf("TestViewMappingClassValue construct unknown\n");
+#endif
+#endif
+    }
+    KOKKOS_INLINE_FUNCTION
+    ~ValueType()
+    {
+#if 0
+#if defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_CUDA )
+      printf("TestViewMappingClassValue destruct on Cuda\n");
+#elif defined( KOKKOS_ACTIVE_EXECUTION_MEMORY_SPACE_HOST )
+      printf("TestViewMappingClassValue destruct on Host\n");
+#else
+      printf("TestViewMappingClassValue destruct unknown\n");
+#endif
+#endif
+    }
+  };
+
+  static void run()
+  {
+    using namespace Kokkos::Experimental ;
+    ExecSpace::fence();
+    {
+      View< ValueType , ExecSpace > a("a");
+      ExecSpace::fence();
+    }
+    ExecSpace::fence();
+  }
+};
+
+} /* namespace Test */
+
+/*--------------------------------------------------------------------------*/
+
diff --git a/lib/kokkos/core/unit_test/TestViewOfClass.hpp b/lib/kokkos/core/unit_test/TestViewOfClass.hpp
new file mode 100644
index 0000000000..9b23a5d559
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestViewOfClass.hpp
@@ -0,0 +1,163 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+/*--------------------------------------------------------------------------*/
+
+namespace Test {
+
+template< class Space >
+struct NestedView {
+
+  Kokkos::View<int*,Space> member ;
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  NestedView() : member()
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  NestedView & operator = ( const Kokkos::View<int*,Space> & lhs )
+    {
+      member = lhs ;
+      if ( member.dimension_0() ) Kokkos::atomic_add( & member(0) , 1 );
+      return *this ;
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  ~NestedView()
+  { 
+    if ( member.dimension_0() ) {
+      Kokkos::atomic_add( & member(0) , -1 );
+    }
+  }
+};
+
+template< class Space >
+struct NestedViewFunctor {
+
+  Kokkos::View< NestedView<Space> * , Space > nested ;
+  Kokkos::View<int*,Space>                    array ;
+
+  NestedViewFunctor( 
+    const Kokkos::View< NestedView<Space> * , Space > & arg_nested ,
+    const Kokkos::View<int*,Space>                    & arg_array )
+  : nested( arg_nested )
+  , array(  arg_array )
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int i ) const
+    { nested[i] = array ; }
+};
+
+
+template< class Space >
+void view_nested_view()
+{
+  Kokkos::View<int*,Space> tracking("tracking",1);
+
+  typename Kokkos::View<int*,Space>::HostMirror
+     host_tracking = Kokkos::create_mirror( tracking );
+
+  {
+    Kokkos::View< NestedView<Space> * , Space > a("a_nested_view",2);
+
+    Kokkos::parallel_for( Kokkos::RangePolicy<Space>(0,2) , NestedViewFunctor<Space>( a , tracking ) );
+    Kokkos::deep_copy( host_tracking , tracking );
+    ASSERT_EQ( 2 , host_tracking(0) );
+
+    Kokkos::View< NestedView<Space> * , Space > b("b_nested_view",2);
+    Kokkos::parallel_for( Kokkos::RangePolicy<Space>(0,2) , NestedViewFunctor<Space>( b , tracking ) );
+    Kokkos::deep_copy( host_tracking , tracking );
+    ASSERT_EQ( 4 , host_tracking(0) );
+
+  }
+  Kokkos::deep_copy( host_tracking , tracking );
+
+#if KOKKOS_USING_EXP_VIEW
+  ASSERT_EQ( 0 , host_tracking(0) );
+#endif
+
+}
+
+}
+
+#if ! KOKKOS_USING_EXP_VIEW
+
+namespace Kokkos {
+namespace Impl {
+
+template< class ExecSpace , class S >
+struct ViewDefaultConstruct< ExecSpace , Test::NestedView<S> , true >
+{
+  typedef Test::NestedView<S> type ;
+  type * const m_ptr ;
+
+  KOKKOS_FORCEINLINE_FUNCTION
+  void operator()( const typename ExecSpace::size_type& i ) const
+    { new(m_ptr+i) type(); }
+
+  ViewDefaultConstruct( type * pointer , size_t capacity )
+    : m_ptr( pointer )
+    {
+      Kokkos::RangePolicy< ExecSpace > range( 0 , capacity );
+      parallel_for( range , *this );
+      ExecSpace::fence();
+    }
+};
+
+} // namespace Impl
+} // namespace Kokkos
+
+#endif
+
+/*--------------------------------------------------------------------------*/
+
diff --git a/lib/kokkos/core/unit_test/TestViewSubview.hpp b/lib/kokkos/core/unit_test/TestViewSubview.hpp
new file mode 100644
index 0000000000..3846354b8c
--- /dev/null
+++ b/lib/kokkos/core/unit_test/TestViewSubview.hpp
@@ -0,0 +1,874 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+#include <Kokkos_Core.hpp>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+
+/*--------------------------------------------------------------------------*/
+
+namespace TestViewSubview {
+
+template<class Layout, class Space>
+struct getView {
+  static
+    Kokkos::View<double**,Layout,Space> get(int n, int m) {
+      return Kokkos::View<double**,Layout,Space>("G",n,m);
+  }
+};
+
+template<class Space>
+struct getView<Kokkos::LayoutStride,Space> {
+  static
+    Kokkos::View<double**,Kokkos::LayoutStride,Space> get(int n, int m) {
+      const int rank = 2 ;
+      const int order[] = { 0, 1 };
+      const unsigned dim[] = { unsigned(n), unsigned(m) };
+      Kokkos::LayoutStride stride = Kokkos::LayoutStride::order_dimensions( rank , order , dim );
+      return Kokkos::View<double**,Kokkos::LayoutStride,Space>("G",stride);
+  }
+};
+
+template<class ViewType, class Space>
+struct fill_1D {
+  typedef typename Space::execution_space execution_space;
+  typedef typename ViewType::size_type size_type;
+  ViewType a;
+  double val;
+  fill_1D(ViewType a_, double val_):a(a_),val(val_) {
+  }
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int i) const {
+    a(i) = val;
+  }
+};
+
+template<class ViewType, class Space>
+struct fill_2D {
+  typedef typename Space::execution_space execution_space;
+  typedef typename ViewType::size_type size_type;
+  ViewType a;
+  double val;
+  fill_2D(ViewType a_, double val_):a(a_),val(val_) {
+  }
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int i) const{
+    for(int j = 0; j < static_cast<int>(a.dimension_1()); j++)
+      a(i,j) = val;
+  }
+};
+
+template<class Layout, class Space>
+void test_auto_1d ()
+{
+  typedef Kokkos::View<double**, Layout, Space> mv_type;
+  typedef typename mv_type::size_type size_type;
+  const double ZERO = 0.0;
+  const double ONE = 1.0;
+  const double TWO = 2.0;
+
+  const size_type numRows = 10;
+  const size_type numCols = 3;
+
+  mv_type X = getView<Layout,Space>::get(numRows, numCols);
+  typename mv_type::HostMirror X_h = Kokkos::create_mirror_view (X);
+
+  fill_2D<mv_type,Space> f1(X, ONE);
+  Kokkos::parallel_for(X.dimension_0(),f1);
+  Kokkos::deep_copy (X_h, X);
+  for (size_type j = 0; j < numCols; ++j) {
+    for (size_type i = 0; i < numRows; ++i) {
+      ASSERT_TRUE(X_h(i,j) == ONE);
+    }
+  }
+
+  fill_2D<mv_type,Space> f2(X, 0.0);
+  Kokkos::parallel_for(X.dimension_0(),f2);
+  Kokkos::deep_copy (X_h, X);
+  for (size_type j = 0; j < numCols; ++j) {
+    for (size_type i = 0; i < numRows; ++i) {
+      ASSERT_TRUE(X_h(i,j) == ZERO);
+    }
+  }
+
+  fill_2D<mv_type,Space> f3(X, TWO);
+  Kokkos::parallel_for(X.dimension_0(),f3);
+  Kokkos::deep_copy (X_h, X);
+  for (size_type j = 0; j < numCols; ++j) {
+    for (size_type i = 0; i < numRows; ++i) {
+      ASSERT_TRUE(X_h(i,j) == TWO);
+    }
+  }
+
+  for (size_type j = 0; j < numCols; ++j) {
+    auto X_j = Kokkos::subview (X, Kokkos::ALL(), j);
+
+    fill_1D<decltype(X_j),Space> f4(X_j, ZERO);
+    Kokkos::parallel_for(X_j.dimension_0(),f4);
+    Kokkos::deep_copy (X_h, X);
+    for (size_type i = 0; i < numRows; ++i) {
+      ASSERT_TRUE(X_h(i,j) == ZERO);
+    }
+
+    for (size_type jj = 0; jj < numCols; ++jj) {
+      auto X_jj = Kokkos::subview (X, Kokkos::ALL(), jj);
+      fill_1D<decltype(X_jj),Space> f5(X_jj, ONE);
+      Kokkos::parallel_for(X_jj.dimension_0(),f5);
+      Kokkos::deep_copy (X_h, X);
+      for (size_type i = 0; i < numRows; ++i) {
+        ASSERT_TRUE(X_h(i,jj) == ONE);
+      }
+    }
+  }
+}
+
+template<class LD, class LS, class Space>
+void test_1d_strided_assignment_impl(bool a, bool b, bool c, bool d, int n, int m) {
+  Kokkos::View<double**,LS,Space> l2d("l2d",n,m);
+
+  int col = n>2?2:0;
+  int row = m>2?2:0;
+
+  if(Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<Kokkos::HostSpace,Space>::value) {
+  if(a) {
+    Kokkos::View<double*,LD,Space> l1da = Kokkos::subview(l2d,Kokkos::ALL(),row);
+    ASSERT_TRUE( & l1da(0) == & l2d(0,row) );
+    if(n>1)
+      ASSERT_TRUE( & l1da(1) == & l2d(1,row) );
+  }
+  if(b && n>13) {
+    Kokkos::View<double*,LD,Space> l1db = Kokkos::subview(l2d,std::pair<unsigned,unsigned>(2,13),row);
+    ASSERT_TRUE( & l1db(0) == & l2d(2,row) );
+    ASSERT_TRUE( & l1db(1) == & l2d(3,row) );
+  }
+  if(c) {
+    Kokkos::View<double*,LD,Space> l1dc = Kokkos::subview(l2d,col,Kokkos::ALL());
+    ASSERT_TRUE( & l1dc(0) == & l2d(col,0) );
+    if(m>1)
+      ASSERT_TRUE( & l1dc(1) == & l2d(col,1) );
+  }
+  if(d && m>13) {
+    Kokkos::View<double*,LD,Space> l1dd = Kokkos::subview(l2d,col,std::pair<unsigned,unsigned>(2,13));
+    ASSERT_TRUE( & l1dd(0) == & l2d(col,2) );
+    ASSERT_TRUE( & l1dd(1) == & l2d(col,3) );
+  }
+  }
+
+}
+
+template<class Space >
+void test_1d_strided_assignment() {
+  test_1d_strided_assignment_impl<Kokkos::LayoutStride,Kokkos::LayoutLeft,Space>(true,true,true,true,17,3);
+  test_1d_strided_assignment_impl<Kokkos::LayoutStride,Kokkos::LayoutRight,Space>(true,true,true,true,17,3);
+
+  test_1d_strided_assignment_impl<Kokkos::LayoutLeft,Kokkos::LayoutLeft,Space>(true,true,false,false,17,3);
+  test_1d_strided_assignment_impl<Kokkos::LayoutRight,Kokkos::LayoutLeft,Space>(true,true,false,false,17,3);
+  test_1d_strided_assignment_impl<Kokkos::LayoutLeft,Kokkos::LayoutRight,Space>(false,false,true,true,17,3);
+  test_1d_strided_assignment_impl<Kokkos::LayoutRight,Kokkos::LayoutRight,Space>(false,false,true,true,17,3);
+
+  test_1d_strided_assignment_impl<Kokkos::LayoutLeft,Kokkos::LayoutLeft,Space>(true,true,false,false,17,1);
+  test_1d_strided_assignment_impl<Kokkos::LayoutLeft,Kokkos::LayoutLeft,Space>(true,true,true,true,1,17);
+  test_1d_strided_assignment_impl<Kokkos::LayoutRight,Kokkos::LayoutLeft,Space>(true,true,true,true,1,17);
+  test_1d_strided_assignment_impl<Kokkos::LayoutRight,Kokkos::LayoutLeft,Space>(true,true,false,false,17,1);
+
+  test_1d_strided_assignment_impl<Kokkos::LayoutLeft,Kokkos::LayoutRight,Space>(true,true,true,true,17,1);
+  test_1d_strided_assignment_impl<Kokkos::LayoutLeft,Kokkos::LayoutRight,Space>(false,false,true,true,1,17);
+  test_1d_strided_assignment_impl<Kokkos::LayoutRight,Kokkos::LayoutRight,Space>(false,false,true,true,1,17);
+  test_1d_strided_assignment_impl<Kokkos::LayoutRight,Kokkos::LayoutRight,Space>(true,true,true,true,17,1);
+}
+
+template< class Space >
+void test_left_0()
+{
+  typedef Kokkos::View< int [2][3][4][5][2][3][4][5] , Kokkos::LayoutLeft , Space >
+    view_static_8_type ;
+
+  if(Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<Kokkos::HostSpace,Space>::value) {
+
+  view_static_8_type  x_static_8("x_static_left_8");
+
+  ASSERT_TRUE( x_static_8.is_contiguous() );
+
+  Kokkos::View<int,Kokkos::LayoutLeft,Space> x0 = Kokkos::subview( x_static_8 , 0, 0, 0, 0, 0, 0, 0, 0 );
+
+  ASSERT_TRUE( x0.is_contiguous() );
+  ASSERT_TRUE( & x0() == & x_static_8(0,0,0,0,0,0,0,0) );
+
+  Kokkos::View<int*,Kokkos::LayoutLeft,Space> x1 =
+    Kokkos::subview( x_static_8, Kokkos::pair<int,int>(0,2), 1, 2, 3, 0, 1, 2, 3 );
+
+  ASSERT_TRUE( x1.is_contiguous() );
+  ASSERT_TRUE( & x1(0) == & x_static_8(0,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & x1(1) == & x_static_8(1,1,2,3,0,1,2,3) );
+
+  Kokkos::View<int**,Kokkos::LayoutLeft,Space> x2 =
+    Kokkos::subview( x_static_8, Kokkos::pair<int,int>(0,2), 1, 2, 3
+                               , Kokkos::pair<int,int>(0,2), 1, 2, 3 );
+
+  ASSERT_TRUE( ! x2.is_contiguous() );
+  ASSERT_TRUE( & x2(0,0) == & x_static_8(0,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & x2(1,0) == & x_static_8(1,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & x2(0,1) == & x_static_8(0,1,2,3,1,1,2,3) );
+  ASSERT_TRUE( & x2(1,1) == & x_static_8(1,1,2,3,1,1,2,3) );
+
+  // Kokkos::View<int**,Kokkos::LayoutLeft,Space> error_2 =
+  Kokkos::View<int**,Kokkos::LayoutStride,Space> sx2 =
+    Kokkos::subview( x_static_8, 1, Kokkos::pair<int,int>(0,2), 2, 3
+                               , Kokkos::pair<int,int>(0,2), 1, 2, 3 );
+
+  ASSERT_TRUE( ! sx2.is_contiguous() );
+  ASSERT_TRUE( & sx2(0,0) == & x_static_8(1,0,2,3,0,1,2,3) );
+  ASSERT_TRUE( & sx2(1,0) == & x_static_8(1,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & sx2(0,1) == & x_static_8(1,0,2,3,1,1,2,3) );
+  ASSERT_TRUE( & sx2(1,1) == & x_static_8(1,1,2,3,1,1,2,3) );
+
+  Kokkos::View<int****,Kokkos::LayoutStride,Space> sx4 =
+    Kokkos::subview( x_static_8, 0, Kokkos::pair<int,int>(0,2) /* of [3] */
+                               , 1, Kokkos::pair<int,int>(1,3) /* of [5] */
+                               , 1, Kokkos::pair<int,int>(0,2) /* of [3] */
+                               , 2, Kokkos::pair<int,int>(2,4) /* of [5] */
+                   );
+
+  ASSERT_TRUE( ! sx4.is_contiguous() );
+
+  for ( int i0 = 0 ; i0 < (int) sx4.dimension_0() ; ++i0 )
+  for ( int i1 = 0 ; i1 < (int) sx4.dimension_1() ; ++i1 )
+  for ( int i2 = 0 ; i2 < (int) sx4.dimension_2() ; ++i2 )
+  for ( int i3 = 0 ; i3 < (int) sx4.dimension_3() ; ++i3 ) {
+    ASSERT_TRUE( & sx4(i0,i1,i2,i3) == & x_static_8(0,0+i0, 1,1+i1, 1,0+i2, 2,2+i3) );
+  }
+
+  }
+}
+
+template< class Space >
+void test_left_1()
+{
+  typedef Kokkos::View< int ****[2][3][4][5] , Kokkos::LayoutLeft , Space >
+    view_type ;
+
+  if(Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<Kokkos::HostSpace,Space>::value) {
+
+  view_type  x8("x_left_8",2,3,4,5);
+
+  ASSERT_TRUE( x8.is_contiguous() );
+
+  Kokkos::View<int,Kokkos::LayoutLeft,Space> x0 = Kokkos::subview( x8 , 0, 0, 0, 0, 0, 0, 0, 0 );
+
+  ASSERT_TRUE( x0.is_contiguous() );
+  ASSERT_TRUE( & x0() == & x8(0,0,0,0,0,0,0,0) );
+
+  Kokkos::View<int*,Kokkos::LayoutLeft,Space> x1 =
+    Kokkos::subview( x8, Kokkos::pair<int,int>(0,2), 1, 2, 3, 0, 1, 2, 3 );
+
+  ASSERT_TRUE( x1.is_contiguous() );
+  ASSERT_TRUE( & x1(0) == & x8(0,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & x1(1) == & x8(1,1,2,3,0,1,2,3) );
+
+  Kokkos::View<int**,Kokkos::LayoutLeft,Space> x2 =
+    Kokkos::subview( x8, Kokkos::pair<int,int>(0,2), 1, 2, 3
+                               , Kokkos::pair<int,int>(0,2), 1, 2, 3 );
+
+  ASSERT_TRUE( ! x2.is_contiguous() );
+  ASSERT_TRUE( & x2(0,0) == & x8(0,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & x2(1,0) == & x8(1,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & x2(0,1) == & x8(0,1,2,3,1,1,2,3) );
+  ASSERT_TRUE( & x2(1,1) == & x8(1,1,2,3,1,1,2,3) );
+
+  // Kokkos::View<int**,Kokkos::LayoutLeft,Space> error_2 =
+  Kokkos::View<int**,Kokkos::LayoutStride,Space> sx2 =
+    Kokkos::subview( x8, 1, Kokkos::pair<int,int>(0,2), 2, 3
+                               , Kokkos::pair<int,int>(0,2), 1, 2, 3 );
+
+  ASSERT_TRUE( ! sx2.is_contiguous() );
+  ASSERT_TRUE( & sx2(0,0) == & x8(1,0,2,3,0,1,2,3) );
+  ASSERT_TRUE( & sx2(1,0) == & x8(1,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & sx2(0,1) == & x8(1,0,2,3,1,1,2,3) );
+  ASSERT_TRUE( & sx2(1,1) == & x8(1,1,2,3,1,1,2,3) );
+
+  Kokkos::View<int****,Kokkos::LayoutStride,Space> sx4 =
+    Kokkos::subview( x8, 0, Kokkos::pair<int,int>(0,2) /* of [3] */
+                       , 1, Kokkos::pair<int,int>(1,3) /* of [5] */
+                       , 1, Kokkos::pair<int,int>(0,2) /* of [3] */
+                       , 2, Kokkos::pair<int,int>(2,4) /* of [5] */
+                   );
+
+  ASSERT_TRUE( ! sx4.is_contiguous() );
+
+  for ( int i0 = 0 ; i0 < (int) sx4.dimension_0() ; ++i0 )
+  for ( int i1 = 0 ; i1 < (int) sx4.dimension_1() ; ++i1 )
+  for ( int i2 = 0 ; i2 < (int) sx4.dimension_2() ; ++i2 )
+  for ( int i3 = 0 ; i3 < (int) sx4.dimension_3() ; ++i3 ) {
+    ASSERT_TRUE( & sx4(i0,i1,i2,i3) == & x8(0,0+i0, 1,1+i1, 1,0+i2, 2,2+i3) );
+  }
+
+  }
+}
+
+template< class Space >
+void test_left_2()
+{
+  typedef Kokkos::View< int **** , Kokkos::LayoutLeft , Space > view_type ;
+
+  if(Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<Kokkos::HostSpace,Space>::value) {
+
+  view_type  x4("x4",2,3,4,5);
+
+  ASSERT_TRUE( x4.is_contiguous() );
+
+  Kokkos::View<int,Kokkos::LayoutLeft,Space> x0 = Kokkos::subview( x4 , 0, 0, 0, 0 );
+
+  ASSERT_TRUE( x0.is_contiguous() );
+  ASSERT_TRUE( & x0() == & x4(0,0,0,0) );
+
+  Kokkos::View<int*,Kokkos::LayoutLeft,Space> x1 =
+    Kokkos::subview( x4, Kokkos::pair<int,int>(0,2), 1, 2, 3 );
+
+  ASSERT_TRUE( x1.is_contiguous() );
+  ASSERT_TRUE( & x1(0) == & x4(0,1,2,3) );
+  ASSERT_TRUE( & x1(1) == & x4(1,1,2,3) );
+
+  Kokkos::View<int**,Kokkos::LayoutLeft,Space> x2 =
+    Kokkos::subview( x4, Kokkos::pair<int,int>(0,2), 1, Kokkos::pair<int,int>(1,3), 2 );
+
+  ASSERT_TRUE( ! x2.is_contiguous() );
+  ASSERT_TRUE( & x2(0,0) == & x4(0,1,1,2) );
+  ASSERT_TRUE( & x2(1,0) == & x4(1,1,1,2) );
+  ASSERT_TRUE( & x2(0,1) == & x4(0,1,2,2) );
+  ASSERT_TRUE( & x2(1,1) == & x4(1,1,2,2) );
+
+  // Kokkos::View<int**,Kokkos::LayoutLeft,Space> error_2 =
+  Kokkos::View<int**,Kokkos::LayoutStride,Space> sx2 =
+    Kokkos::subview( x4, 1, Kokkos::pair<int,int>(0,2)
+                       , 2, Kokkos::pair<int,int>(1,4) );
+
+  ASSERT_TRUE( ! sx2.is_contiguous() );
+  ASSERT_TRUE( & sx2(0,0) == & x4(1,0,2,1) );
+  ASSERT_TRUE( & sx2(1,0) == & x4(1,1,2,1) );
+  ASSERT_TRUE( & sx2(0,1) == & x4(1,0,2,2) );
+  ASSERT_TRUE( & sx2(1,1) == & x4(1,1,2,2) );
+  ASSERT_TRUE( & sx2(0,2) == & x4(1,0,2,3) );
+  ASSERT_TRUE( & sx2(1,2) == & x4(1,1,2,3) );
+
+  Kokkos::View<int****,Kokkos::LayoutStride,Space> sx4 =
+    Kokkos::subview( x4, Kokkos::pair<int,int>(1,2) /* of [2] */
+                       , Kokkos::pair<int,int>(1,3) /* of [3] */
+                       , Kokkos::pair<int,int>(0,4) /* of [4] */
+                       , Kokkos::pair<int,int>(2,4) /* of [5] */
+                   );
+
+  ASSERT_TRUE( ! sx4.is_contiguous() );
+
+  for ( int i0 = 0 ; i0 < (int) sx4.dimension_0() ; ++i0 )
+  for ( int i1 = 0 ; i1 < (int) sx4.dimension_1() ; ++i1 )
+  for ( int i2 = 0 ; i2 < (int) sx4.dimension_2() ; ++i2 )
+  for ( int i3 = 0 ; i3 < (int) sx4.dimension_3() ; ++i3 ) {
+    ASSERT_TRUE( & sx4(i0,i1,i2,i3) == & x4( 1+i0, 1+i1, 0+i2, 2+i3 ) );
+  }
+
+  }
+}
+
+template< class Space >
+void test_left_3()
+{
+  typedef Kokkos::View< int ** , Kokkos::LayoutLeft , Space > view_type ;
+
+  if(Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<Kokkos::HostSpace,Space>::value) {
+
+  view_type  xm("x4",10,5);
+
+  ASSERT_TRUE( xm.is_contiguous() );
+
+  Kokkos::View<int,Kokkos::LayoutLeft,Space> x0 = Kokkos::subview( xm , 5, 3 );
+
+  ASSERT_TRUE( x0.is_contiguous() );
+  ASSERT_TRUE( & x0() == & xm(5,3) );
+
+  Kokkos::View<int*,Kokkos::LayoutLeft,Space> x1 =
+    Kokkos::subview( xm, Kokkos::ALL(), 3 );
+
+  ASSERT_TRUE( x1.is_contiguous() );
+  for ( int i = 0 ; i < int(xm.dimension_0()) ; ++i ) {
+    ASSERT_TRUE( & x1(i) == & xm(i,3) );
+  }
+
+  Kokkos::View<int**,Kokkos::LayoutLeft,Space> x2 =
+    Kokkos::subview( xm, Kokkos::pair<int,int>(1,9), Kokkos::ALL() );
+
+  ASSERT_TRUE( ! x2.is_contiguous() );
+  for ( int j = 0 ; j < int(x2.dimension_1()) ; ++j )
+  for ( int i = 0 ; i < int(x2.dimension_0()) ; ++i ) {
+    ASSERT_TRUE( & x2(i,j) == & xm(1+i,j) );
+  }
+
+  Kokkos::View<int**,Kokkos::LayoutLeft,Space> x2c =
+    Kokkos::subview( xm, Kokkos::ALL(), std::pair<int,int>(2,4) );
+
+  ASSERT_TRUE( x2c.is_contiguous() );
+  for ( int j = 0 ; j < int(x2c.dimension_1()) ; ++j )
+  for ( int i = 0 ; i < int(x2c.dimension_0()) ; ++i ) {
+    ASSERT_TRUE( & x2c(i,j) == & xm(i,2+j) );
+  }
+
+  Kokkos::View<int**,Kokkos::LayoutLeft,Space> x2_n1 =
+    Kokkos::subview( xm , std::pair<int,int>(1,1) , Kokkos::ALL() );
+
+  ASSERT_TRUE( x2_n1.dimension_0() == 0 );
+  ASSERT_TRUE( x2_n1.dimension_1() == xm.dimension_1() );
+
+  Kokkos::View<int**,Kokkos::LayoutLeft,Space> x2_n2 =
+    Kokkos::subview( xm , Kokkos::ALL() , std::pair<int,int>(1,1) );
+
+  ASSERT_TRUE( x2_n2.dimension_0() == xm.dimension_0() );
+  ASSERT_TRUE( x2_n2.dimension_1() == 0 );
+
+  }
+}
+
+//----------------------------------------------------------------------------
+
+template< class Space >
+void test_right_0()
+{
+  typedef Kokkos::View< int [2][3][4][5][2][3][4][5] , Kokkos::LayoutRight , Space >
+    view_static_8_type ;
+
+  if(Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<Kokkos::HostSpace,Space>::value) {
+
+  view_static_8_type  x_static_8("x_static_right_8");
+
+  Kokkos::View<int,Kokkos::LayoutRight,Space> x0 = Kokkos::subview( x_static_8 , 0, 0, 0, 0, 0, 0, 0, 0 );
+
+  ASSERT_TRUE( & x0() == & x_static_8(0,0,0,0,0,0,0,0) );
+
+  Kokkos::View<int*,Kokkos::LayoutRight,Space> x1 =
+    Kokkos::subview( x_static_8, 0, 1, 2, 3, 0, 1, 2, Kokkos::pair<int,int>(1,3) );
+
+  ASSERT_TRUE( x1.dimension_0() == 2 );
+  ASSERT_TRUE( & x1(0) == & x_static_8(0,1,2,3,0,1,2,1) );
+  ASSERT_TRUE( & x1(1) == & x_static_8(0,1,2,3,0,1,2,2) );
+
+  Kokkos::View<int**,Kokkos::LayoutRight,Space> x2 =
+    Kokkos::subview( x_static_8, 0, 1, 2, Kokkos::pair<int,int>(1,3)
+                               , 0, 1, 2, Kokkos::pair<int,int>(1,3) );
+
+  ASSERT_TRUE( x2.dimension_0() == 2 );
+  ASSERT_TRUE( x2.dimension_1() == 2 );
+  ASSERT_TRUE( & x2(0,0) == & x_static_8(0,1,2,1,0,1,2,1) );
+  ASSERT_TRUE( & x2(1,0) == & x_static_8(0,1,2,2,0,1,2,1) );
+  ASSERT_TRUE( & x2(0,1) == & x_static_8(0,1,2,1,0,1,2,2) );
+  ASSERT_TRUE( & x2(1,1) == & x_static_8(0,1,2,2,0,1,2,2) );
+
+  // Kokkos::View<int**,Kokkos::LayoutRight,Space> error_2 =
+  Kokkos::View<int**,Kokkos::LayoutStride,Space> sx2 =
+    Kokkos::subview( x_static_8, 1, Kokkos::pair<int,int>(0,2), 2, 3
+                               , Kokkos::pair<int,int>(0,2), 1, 2, 3 );
+
+  ASSERT_TRUE( sx2.dimension_0() == 2 );
+  ASSERT_TRUE( sx2.dimension_1() == 2 );
+  ASSERT_TRUE( & sx2(0,0) == & x_static_8(1,0,2,3,0,1,2,3) );
+  ASSERT_TRUE( & sx2(1,0) == & x_static_8(1,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & sx2(0,1) == & x_static_8(1,0,2,3,1,1,2,3) );
+  ASSERT_TRUE( & sx2(1,1) == & x_static_8(1,1,2,3,1,1,2,3) );
+
+  Kokkos::View<int****,Kokkos::LayoutStride,Space> sx4 =
+    Kokkos::subview( x_static_8, 0, Kokkos::pair<int,int>(0,2) /* of [3] */
+                               , 1, Kokkos::pair<int,int>(1,3) /* of [5] */
+                               , 1, Kokkos::pair<int,int>(0,2) /* of [3] */
+                               , 2, Kokkos::pair<int,int>(2,4) /* of [5] */
+                   );
+
+  ASSERT_TRUE( sx4.dimension_0() == 2 );
+  ASSERT_TRUE( sx4.dimension_1() == 2 );
+  ASSERT_TRUE( sx4.dimension_2() == 2 );
+  ASSERT_TRUE( sx4.dimension_3() == 2 );
+  for ( int i0 = 0 ; i0 < (int) sx4.dimension_0() ; ++i0 )
+  for ( int i1 = 0 ; i1 < (int) sx4.dimension_1() ; ++i1 )
+  for ( int i2 = 0 ; i2 < (int) sx4.dimension_2() ; ++i2 )
+  for ( int i3 = 0 ; i3 < (int) sx4.dimension_3() ; ++i3 ) {
+    ASSERT_TRUE( & sx4(i0,i1,i2,i3) == & x_static_8(0, 0+i0, 1, 1+i1, 1, 0+i2, 2, 2+i3) );
+  }
+
+  }
+}
+
+template< class Space >
+void test_right_1()
+{
+  typedef Kokkos::View< int ****[2][3][4][5] , Kokkos::LayoutRight , Space >
+    view_type ;
+
+  if(Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<Kokkos::HostSpace,Space>::value) {
+
+  view_type  x8("x_right_8",2,3,4,5);
+
+  Kokkos::View<int,Kokkos::LayoutRight,Space> x0 = Kokkos::subview( x8 , 0, 0, 0, 0, 0, 0, 0, 0 );
+
+  ASSERT_TRUE( & x0() == & x8(0,0,0,0,0,0,0,0) );
+
+  Kokkos::View<int*,Kokkos::LayoutRight,Space> x1 =
+    Kokkos::subview( x8, 0, 1, 2, 3, 0, 1, 2, Kokkos::pair<int,int>(1,3) );
+
+  ASSERT_TRUE( & x1(0) == & x8(0,1,2,3,0,1,2,1) );
+  ASSERT_TRUE( & x1(1) == & x8(0,1,2,3,0,1,2,2) );
+
+  Kokkos::View<int**,Kokkos::LayoutRight,Space> x2 =
+    Kokkos::subview( x8, 0, 1, 2, Kokkos::pair<int,int>(1,3)
+                               , 0, 1, 2, Kokkos::pair<int,int>(1,3) );
+
+  ASSERT_TRUE( & x2(0,0) == & x8(0,1,2,1,0,1,2,1) );
+  ASSERT_TRUE( & x2(1,0) == & x8(0,1,2,2,0,1,2,1) );
+  ASSERT_TRUE( & x2(0,1) == & x8(0,1,2,1,0,1,2,2) );
+  ASSERT_TRUE( & x2(1,1) == & x8(0,1,2,2,0,1,2,2) );
+
+  // Kokkos::View<int**,Kokkos::LayoutRight,Space> error_2 =
+  Kokkos::View<int**,Kokkos::LayoutStride,Space> sx2 =
+    Kokkos::subview( x8, 1, Kokkos::pair<int,int>(0,2), 2, 3
+                               , Kokkos::pair<int,int>(0,2), 1, 2, 3 );
+
+  ASSERT_TRUE( & sx2(0,0) == & x8(1,0,2,3,0,1,2,3) );
+  ASSERT_TRUE( & sx2(1,0) == & x8(1,1,2,3,0,1,2,3) );
+  ASSERT_TRUE( & sx2(0,1) == & x8(1,0,2,3,1,1,2,3) );
+  ASSERT_TRUE( & sx2(1,1) == & x8(1,1,2,3,1,1,2,3) );
+
+  Kokkos::View<int****,Kokkos::LayoutStride,Space> sx4 =
+    Kokkos::subview( x8, 0, Kokkos::pair<int,int>(0,2) /* of [3] */
+                       , 1, Kokkos::pair<int,int>(1,3) /* of [5] */
+                       , 1, Kokkos::pair<int,int>(0,2) /* of [3] */
+                       , 2, Kokkos::pair<int,int>(2,4) /* of [5] */
+                   );
+
+  for ( int i0 = 0 ; i0 < (int) sx4.dimension_0() ; ++i0 )
+  for ( int i1 = 0 ; i1 < (int) sx4.dimension_1() ; ++i1 )
+  for ( int i2 = 0 ; i2 < (int) sx4.dimension_2() ; ++i2 )
+  for ( int i3 = 0 ; i3 < (int) sx4.dimension_3() ; ++i3 ) {
+    ASSERT_TRUE( & sx4(i0,i1,i2,i3) == & x8(0,0+i0, 1,1+i1, 1,0+i2, 2,2+i3) );
+  }
+
+  }
+}
+
+template< class Space >
+void test_right_3()
+{
+  typedef Kokkos::View< int ** , Kokkos::LayoutRight , Space > view_type ;
+
+  if(Kokkos::Impl::VerifyExecutionCanAccessMemorySpace<Kokkos::HostSpace,Space>::value) {
+
+  view_type  xm("x4",10,5);
+
+  ASSERT_TRUE( xm.is_contiguous() );
+
+  Kokkos::View<int,Kokkos::LayoutRight,Space> x0 = Kokkos::subview( xm , 5, 3 );
+
+  ASSERT_TRUE( x0.is_contiguous() );
+  ASSERT_TRUE( & x0() == & xm(5,3) );
+
+  Kokkos::View<int*,Kokkos::LayoutRight,Space> x1 =
+    Kokkos::subview( xm, 3, Kokkos::ALL() );
+
+  ASSERT_TRUE( x1.is_contiguous() );
+  for ( int i = 0 ; i < int(xm.dimension_1()) ; ++i ) {
+    ASSERT_TRUE( & x1(i) == & xm(3,i) );
+  }
+
+  Kokkos::View<int**,Kokkos::LayoutRight,Space> x2c =
+    Kokkos::subview( xm, Kokkos::pair<int,int>(1,9), Kokkos::ALL() );
+
+  ASSERT_TRUE( x2c.is_contiguous() );
+  for ( int j = 0 ; j < int(x2c.dimension_1()) ; ++j )
+  for ( int i = 0 ; i < int(x2c.dimension_0()) ; ++i ) {
+    ASSERT_TRUE( & x2c(i,j) == & xm(1+i,j) );
+  }
+
+  Kokkos::View<int**,Kokkos::LayoutRight,Space> x2 =
+    Kokkos::subview( xm, Kokkos::ALL(), std::pair<int,int>(2,4) );
+
+  ASSERT_TRUE( ! x2.is_contiguous() );
+  for ( int j = 0 ; j < int(x2.dimension_1()) ; ++j )
+  for ( int i = 0 ; i < int(x2.dimension_0()) ; ++i ) {
+    ASSERT_TRUE( & x2(i,j) == & xm(i,2+j) );
+  }
+
+  Kokkos::View<int**,Kokkos::LayoutRight,Space> x2_n1 =
+    Kokkos::subview( xm , std::pair<int,int>(1,1) , Kokkos::ALL() );
+
+  ASSERT_TRUE( x2_n1.dimension_0() == 0 );
+  ASSERT_TRUE( x2_n1.dimension_1() == xm.dimension_1() );
+
+  Kokkos::View<int**,Kokkos::LayoutRight,Space> x2_n2 =
+    Kokkos::subview( xm , Kokkos::ALL() , std::pair<int,int>(1,1) );
+
+  ASSERT_TRUE( x2_n2.dimension_0() == xm.dimension_0() );
+  ASSERT_TRUE( x2_n2.dimension_1() == 0 );
+
+  }
+}
+
+namespace Impl {
+
+constexpr int N0=113;
+constexpr int N1=11;
+constexpr int N2=17;
+constexpr int N3=5;
+constexpr int N4=7;
+
+template<class SubView,class View>
+void test_Check1D(SubView a, View b, std::pair<int,int> range) {
+  int errors = 0;
+  for(int i=0;i<range.second-range.first;i++) {
+    if(a(i)!=b(i+range.first))
+      errors++;
+  }
+  if(errors>0)
+    std::cout << "Error Suviews test_Check1D: " << errors <<std::endl;
+  ASSERT_TRUE( errors == 0 );
+}
+
+template<class SubView,class View>
+void test_Check1D2D(SubView a, View b, int i0, std::pair<int,int> range) {
+  int errors = 0;
+  for(int i1=0;i1<range.second-range.first;i1++) {
+    if(a(i1)!=b(i0,i1+range.first))
+      errors++;
+  }
+  if(errors>0)
+    std::cout << "Error Suviews test_Check1D2D: " << errors <<std::endl;
+  ASSERT_TRUE( errors == 0 );
+}
+
+template<class SubView,class View>
+void test_Check2D3D(SubView a, View b, int i0, std::pair<int,int> range1, std::pair<int,int> range2) {
+  int errors = 0;
+  for(int i1=0;i1<range1.second-range1.first;i1++) {
+    for(int i2=0;i2<range2.second-range2.first;i2++) {
+      if(a(i1,i2)!=b(i0,i1+range1.first,i2+range2.first))
+        errors++;
+    }
+  }
+  if(errors>0)
+    std::cout << "Error Suviews test_Check2D3D: " << errors <<std::endl;
+  ASSERT_TRUE( errors == 0 );
+}
+
+template<class SubView,class View>
+void test_Check3D5D(SubView a, View b, int i0, int i1, std::pair<int,int> range2, std::pair<int,int> range3, std::pair<int,int> range4) {
+  int errors = 0;
+  for(int i2=0;i2<range2.second-range2.first;i2++) {
+    for(int i3=0;i3<range3.second-range3.first;i3++) {
+      for(int i4=0;i4<range4.second-range4.first;i4++) {
+        if(a(i2,i3,i4)!=b(i0,i1,i2+range2.first,i3+range3.first,i4+range4.first))
+          errors++;
+      }
+    }
+  }
+  if(errors>0)
+    std::cout << "Error Suviews test_Check3D5D: " << errors <<std::endl;
+  ASSERT_TRUE( errors == 0 );
+}
+
+template<class Space, class LayoutSub, class Layout, class LayoutOrg>
+void test_1d_assign_impl() {
+
+  { //Breaks
+    Kokkos::View<int*,LayoutOrg,Space> a("A",N0);
+    Kokkos::fence();
+    for(int i=0; i<N0; i++)
+      a(i) = i;
+
+    Kokkos::View<int[N0],Layout,Space> a1(a);
+    Kokkos::fence();
+    test_Check1D(a1,a,std::pair<int,int>(0,N0));
+
+    Kokkos::View<int[N0],LayoutSub,Space> a2(a1);
+    Kokkos::fence();
+    test_Check1D(a2,a,std::pair<int,int>(0,N0));
+    a1 = a;
+    test_Check1D(a1,a,std::pair<int,int>(0,N0));
+
+    //Runtime Fail expected
+    //Kokkos::View<int[N1]> afail1(a);
+
+    //Compile Time Fail expected
+    //Kokkos::View<int[N1]> afail2(a1);
+  }
+
+  { // Works
+    Kokkos::View<int[N0],LayoutOrg,Space> a("A");
+    Kokkos::View<int*,Layout,Space> a1(a);
+    Kokkos::fence();
+    test_Check1D(a1,a,std::pair<int,int>(0,N0));
+    a1 = a;
+    Kokkos::fence();
+    test_Check1D(a1,a,std::pair<int,int>(0,N0));
+  }
+}
+
+template<class Space, class Type, class TypeSub,class LayoutSub, class Layout, class LayoutOrg>
+void test_2d_subview_3d_impl_type() {
+  Kokkos::View<int***,LayoutOrg,Space> a_org("A",N0,N1,N2);
+  Kokkos::View<Type,Layout,Space> a(a_org);
+  for(int i0=0; i0<N0; i0++)
+    for(int i1=0; i1<N1; i1++)
+      for(int i2=0; i2<N2; i2++)
+        a(i0,i1,i2) = i0*1000000+i1*1000+i2;
+  Kokkos::View<TypeSub,LayoutSub,Space> a1;
+  a1 = Kokkos::subview(a,3,Kokkos::ALL(),Kokkos::ALL());
+  Kokkos::fence();
+  test_Check2D3D(a1,a,3,std::pair<int,int>(0,N1),std::pair<int,int>(0,N2));
+
+  Kokkos::View<TypeSub,LayoutSub,Space> a2(a,3,Kokkos::ALL(),Kokkos::ALL());
+  Kokkos::fence();
+  test_Check2D3D(a2,a,3,std::pair<int,int>(0,N1),std::pair<int,int>(0,N2));
+}
+
+template<class Space, class LayoutSub, class Layout, class LayoutOrg>
+void test_2d_subview_3d_impl_layout() {
+  test_2d_subview_3d_impl_type<Space,int[N0][N1][N2],int[N1][N2],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_3d_impl_type<Space,int[N0][N1][N2],int*   [N2],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_3d_impl_type<Space,int[N0][N1][N2],int**      ,LayoutSub, Layout, LayoutOrg>();
+
+  test_2d_subview_3d_impl_type<Space,int*   [N1][N2],int[N1][N2],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_3d_impl_type<Space,int*   [N1][N2],int*   [N2],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_3d_impl_type<Space,int*   [N1][N2],int**      ,LayoutSub, Layout, LayoutOrg>();
+
+  test_2d_subview_3d_impl_type<Space,int**      [N2],int[N1][N2],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_3d_impl_type<Space,int**      [N2],int*   [N2],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_3d_impl_type<Space,int**      [N2],int**      ,LayoutSub, Layout, LayoutOrg>();
+
+  test_2d_subview_3d_impl_type<Space,int***         ,int[N1][N2],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_3d_impl_type<Space,int***         ,int*   [N2],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_3d_impl_type<Space,int***         ,int**      ,LayoutSub, Layout, LayoutOrg>();
+}
+
+template<class Space, class Type, class TypeSub,class LayoutSub, class Layout, class LayoutOrg>
+void test_2d_subview_5d_impl_type() {
+  Kokkos::View<int*****,LayoutOrg,Space> a_org("A",N0,N1,N2,N3,N4);
+  Kokkos::View<Type,Layout,Space> a(a_org);
+  for(int i0=0; i0<N0; i0++)
+    for(int i1=0; i1<N1; i1++)
+      for(int i2=0; i2<N2; i2++)
+        for(int i3=0; i3<N3; i3++)
+          for(int i4=0; i4<N4; i4++)
+            a(i0,i1,i2,i3,i4) = i0*1000000+i1*10000+i2*100+i3*10+i4;
+  Kokkos::View<TypeSub,LayoutSub,Space> a1;
+  a1 = Kokkos::subview(a,3,5,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
+  Kokkos::fence();
+  test_Check3D5D(a1,a,3,5,std::pair<int,int>(0,N2),std::pair<int,int>(0,N3),std::pair<int,int>(0,N4));
+
+  Kokkos::View<TypeSub,LayoutSub,Space> a2(a,3,5,Kokkos::ALL(),Kokkos::ALL(),Kokkos::ALL());
+  Kokkos::fence();
+  test_Check3D5D(a2,a,3,5,std::pair<int,int>(0,N2),std::pair<int,int>(0,N3),std::pair<int,int>(0,N4));
+}
+
+template<class Space, class LayoutSub, class Layout, class LayoutOrg>
+void test_2d_subview_5d_impl_layout() {
+  test_2d_subview_5d_impl_type<Space, int[N0][N1][N2][N3][N4],int[N2][N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int[N0][N1][N2][N3][N4],int*   [N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int[N0][N1][N2][N3][N4],int**      [N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int[N0][N1][N2][N3][N4],int***         ,LayoutSub, Layout, LayoutOrg>();
+
+  test_2d_subview_5d_impl_type<Space, int*   [N1][N2][N3][N4],int[N2][N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int*   [N1][N2][N3][N4],int*   [N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int*   [N1][N2][N3][N4],int**      [N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int*   [N1][N2][N3][N4],int***         ,LayoutSub, Layout, LayoutOrg>();
+
+  test_2d_subview_5d_impl_type<Space, int**      [N2][N3][N4],int[N2][N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int**      [N2][N3][N4],int*   [N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int**      [N2][N3][N4],int**      [N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int**      [N2][N3][N4],int***         ,LayoutSub, Layout, LayoutOrg>();
+
+  test_2d_subview_5d_impl_type<Space, int***         [N3][N4],int[N2][N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int***         [N3][N4],int*   [N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int***         [N3][N4],int**      [N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int***         [N3][N4],int***         ,LayoutSub, Layout, LayoutOrg>();
+
+  test_2d_subview_5d_impl_type<Space, int****            [N4],int[N2][N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int****            [N4],int*   [N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int****            [N4],int**      [N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int****            [N4],int***         ,LayoutSub, Layout, LayoutOrg>();
+
+  test_2d_subview_5d_impl_type<Space, int*****               ,int[N2][N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int*****               ,int*   [N3][N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int*****               ,int**      [N4],LayoutSub, Layout, LayoutOrg>();
+  test_2d_subview_5d_impl_type<Space, int*****               ,int***         ,LayoutSub, Layout, LayoutOrg>();
+}
+}
+
+template< class Space >
+void test_1d_assign() {
+  Impl::test_1d_assign_impl<Space,Kokkos::LayoutLeft  ,Kokkos::LayoutLeft  ,Kokkos::LayoutLeft  >();
+  //Impl::test_1d_assign_impl<Space,Kokkos::LayoutRight ,Kokkos::LayoutLeft  ,Kokkos::LayoutLeft  >();
+  Impl::test_1d_assign_impl<Space,Kokkos::LayoutStride,Kokkos::LayoutLeft  ,Kokkos::LayoutLeft  >();
+  //Impl::test_1d_assign_impl<Space,Kokkos::LayoutLeft  ,Kokkos::LayoutRight ,Kokkos::LayoutLeft  >();
+  Impl::test_1d_assign_impl<Space,Kokkos::LayoutRight ,Kokkos::LayoutRight ,Kokkos::LayoutRight  >();
+  Impl::test_1d_assign_impl<Space,Kokkos::LayoutStride,Kokkos::LayoutRight ,Kokkos::LayoutRight  >();
+  //Impl::test_1d_assign_impl<Space,Kokkos::LayoutLeft  ,Kokkos::LayoutStride,Kokkos::LayoutLeft  >();
+  //Impl::test_1d_assign_impl<Space,Kokkos::LayoutRight ,Kokkos::LayoutStride,Kokkos::LayoutLeft  >();
+  Impl::test_1d_assign_impl<Space,Kokkos::LayoutStride,Kokkos::LayoutStride,Kokkos::LayoutLeft  >();
+}
+
+template<class Space >
+void test_2d_subview_3d() {
+  Impl::test_2d_subview_3d_impl_layout<Space,Kokkos::LayoutRight ,Kokkos::LayoutRight, Kokkos::LayoutRight>();
+  Impl::test_2d_subview_3d_impl_layout<Space,Kokkos::LayoutStride,Kokkos::LayoutRight, Kokkos::LayoutRight>();
+  Impl::test_2d_subview_3d_impl_layout<Space,Kokkos::LayoutStride,Kokkos::LayoutStride,Kokkos::LayoutRight>();
+  Impl::test_2d_subview_3d_impl_layout<Space,Kokkos::LayoutStride,Kokkos::LayoutLeft,  Kokkos::LayoutLeft>();
+  Impl::test_2d_subview_3d_impl_layout<Space,Kokkos::LayoutStride,Kokkos::LayoutStride,Kokkos::LayoutLeft>();
+}
+
+template<class Space >
+void test_2d_subview_5d() {
+  Impl::test_2d_subview_5d_impl_layout<Space,Kokkos::LayoutStride,Kokkos::LayoutRight, Kokkos::LayoutRight>();
+  Impl::test_2d_subview_5d_impl_layout<Space,Kokkos::LayoutStride,Kokkos::LayoutStride,Kokkos::LayoutRight>();
+  Impl::test_2d_subview_5d_impl_layout<Space,Kokkos::LayoutStride,Kokkos::LayoutLeft,  Kokkos::LayoutLeft>();
+  Impl::test_2d_subview_5d_impl_layout<Space,Kokkos::LayoutStride,Kokkos::LayoutStride,Kokkos::LayoutLeft>();
+}
+
+}
+//----------------------------------------------------------------------------
+
diff --git a/lib/kokkos/core/unit_test/UnitTestMain.cpp b/lib/kokkos/core/unit_test/UnitTestMain.cpp
new file mode 100644
index 0000000000..f952ab3db5
--- /dev/null
+++ b/lib/kokkos/core/unit_test/UnitTestMain.cpp
@@ -0,0 +1,50 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <gtest/gtest.h>
+
+int main(int argc, char *argv[]) {
+  ::testing::InitGoogleTest(&argc,argv);
+  return RUN_ALL_TESTS();
+}
+
diff --git a/lib/kokkos/doc/Doxyfile b/lib/kokkos/doc/Doxyfile
new file mode 100644
index 0000000000..bc5c7486b2
--- /dev/null
+++ b/lib/kokkos/doc/Doxyfile
@@ -0,0 +1,127 @@
+#
+# Include the global look and feel options
+#
+@INCLUDE               = ../../common/Doxyfile
+#
+# Package options
+#
+PROJECT_NAME           = "Kokkos Core Kernels Package"
+PROJECT_NUMBER         = "Version of the Day"
+OUTPUT_DIRECTORY       = .
+OUTPUT_LANGUAGE        = English
+
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+HIDE_UNDOC_MEMBERS     = YES
+HIDE_UNDOC_CLASSES     = YES
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = YES
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+CLASS_DIAGRAMS         = YES
+SOURCE_BROWSER         = YES
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION    = NO
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+VERBATIM_HEADERS       = YES
+SHOW_INCLUDE_FILES     = YES
+#JAVADOC_AUTOBRIEF      = YES
+INHERIT_DOCS           = YES
+INLINE_INHERITED_MEMB  = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = NO
+TAB_SIZE               = 2
+ENABLED_SECTIONS       = 
+SORT_BRIEF_DOCS        = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_FORMAT            = "$file:$line: $text"
+
+#
+# INPUT: Where to find files that Doxygen should process.  ../classic
+# has a doc/ subdirectory with its own Doxyfile that points to its own
+# files.  The other Kokkos subpackages don't currently have their own
+# Doxyfile files, so we have to do it manually here.
+#
+# mfh 26 Sep 2013: I've only added those directories in the Core
+# subpackage that constitute the "public interface" of that
+# subpackage.  Please feel free to include additional subdirectories
+# of ../core if you want to generate their documentation as well.
+#
+# mfh 26 Sep 2013: I've only added the Kokkos subpackages here that I
+# think are ready for Doxygen documentation generation.  Please feel
+# free to amend this list as you see fit.
+#
+
+INPUT                  = index.doc ../classic ../core/src ../containers/src ../linalg/src
+FILE_PATTERNS          = *.hpp *.cpp *.cuh *.cu
+RECURSIVE              = NO
+EXCLUDE_PATTERNS       = *.x *.o *.out
+EXAMPLE_PATH           = 
+EXAMPLE_RECURSIVE       = YES
+EXAMPLE_PATTERNS       = *.cpp *.hpp
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 4
+IGNORE_PREFIX          = 
+#
+# What diagrams are created
+#
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = NO
+INCLUDE_GRAPH          = NO
+INCLUDED_BY_GRAPH      = NO
+GRAPHICAL_HIERARCHY    = YES
+#
+# Preprocessing
+#
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = YES
+EXPAND_ONLY_PREDEF     = YES
+SEARCH_INCLUDES        = YES
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = DOXYGEN_SHOULD_SKIP_THIS DOXYGEN_USE_ONLY
+INCLUDE_PATH           = ../src
+EXPAND_AS_DEFINED      = 
+#
+# Links to other packages
+#
+TAGFILES               = ../../common/tag_files/teuchos.tag=../../../teuchos/doc/html ../../common/tag_files/epetra.tag=../../../epetra/doc/html \
+                         ../../common/tag_files/belos.tag=../../../belos/doc/html ../../common/tag_files/anasazi.tag=../../../anasazi/doc/html \
+                         ../../common/tag_files/kokkos.tag=../../../kokkos/doc/html 
+GENERATE_TAGFILE       = ../../common/tag_files/tpetra.tag
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = NO
+#
+# Environment
+#
+PERL_PATH              = /usr/bin/perl
+HAVE_DOT               = YES
+DOT_PATH               = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+#
+# What kind of documentation is generated
+#
+#GENERATE_HTML          = YES
+#HTML_OUTPUT            = html
+#HTML_HEADER            = includes/header.html
+#HTML_FOOTER            = includes/footer.html
+#HTML_STYLESHEET        = includes/stylesheet.css
+#HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+DISABLE_INDEX          = NO
+GENERATE_LATEX         = NO
+GENERATE_RTF           = NO
+GENERATE_MAN           = NO
+GENERATE_XML           = NO
diff --git a/lib/kokkos/doc/Kokkos_PG.pdf b/lib/kokkos/doc/Kokkos_PG.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..3c415698c0d9fec315f317b71db19f2a019b6f6e
GIT binary patch
literal 1359256
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%0DF-;mqJ@mhP
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
Stg5b}qNc$CgBe;PIQ|3DiXu4x

literal 0
HcmV?d00001

diff --git a/lib/kokkos/doc/README b/lib/kokkos/doc/README
new file mode 100644
index 0000000000..31e75f365c
--- /dev/null
+++ b/lib/kokkos/doc/README
@@ -0,0 +1,32 @@
+Kokkos uses the Doxygen tool for providing three documentation
+sources:
+- man pages
+- Latex User Guide
+- HTML Online User Guide.
+
+Man Pages
+
+Man pages are available for all files and functions in the directory
+TRILINOS_HOME/doc/kokkos/man, where TRILINOS_HOME is the location of your
+copy of Trilinos.  To use these pages with the Unix man utility, add
+the directory to your man path as follows:
+
+setenv MANPATH `echo $MANPATH`:TRILINOS_HOME/doc/kokkos/man
+
+
+LaTeX User Guide
+
+A postscript version of this guide is in
+TRILINOS_HOME/doc/kokkos/latex/user_guide.ps.  The LaTeX source is in the
+directory TRILINOS_HOME/doc/kokkos/latex.
+
+HTML Online User Guide
+
+The online guide is initiated by pointing your browser to
+TRILINOS_HOME/doc/kokkos/html/index.html
+
+Any question, comments or suggestions are welcome.  Please send to
+Mike Heroux at 
+
+320-845-7695
+maherou@sandia.gov
diff --git a/lib/kokkos/doc/build_docs b/lib/kokkos/doc/build_docs
new file mode 100755
index 0000000000..da1d3e4f6e
--- /dev/null
+++ b/lib/kokkos/doc/build_docs
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+if [ $TRILINOS_HOME ]; then
+  echo "TRILINOS_HOME has already been set!"
+else
+  echo "TRILINOS_HOME has not been set.  Setting it!"
+  export TRILINOS_HOME=`pwd`/../../..
+fi
+
+echo
+echo "Generating main Kokkos doxygen documentation ..."
+echo
+
+doxygen Doxyfile
+
diff --git a/lib/kokkos/doc/index.doc b/lib/kokkos/doc/index.doc
new file mode 100644
index 0000000000..27a9e4f2e7
--- /dev/null
+++ b/lib/kokkos/doc/index.doc
@@ -0,0 +1,72 @@
+/*! 
+\mainpage Trilinos/Kokkos: Shared-memory programming interface and computational kernels
+
+\section Kokkos_Intro Introduction
+
+The %Kokkos package has two main components.  The first, sometimes
+called "%Kokkos Array" or just "%Kokkos," implements a
+performance-portable shared-memory parallel programming model and data
+containers.  The second, called "%Kokkos Classic," consists of
+computational kernels that support the %Tpetra package.
+
+\section Kokkos_Kokkos The %Kokkos programming model
+
+%Kokkos implements a performance-portable shared-memory parallel
+programming model and data containers.  It lets you write an algorithm
+once, and just change a template parameter to get the optimal data
+layout for your hardware.  %Kokkos has back-ends for the following
+parallel programming models:
+
+- Kokkos::Threads: POSIX Threads (Pthreads)
+- Kokkos::OpenMP: OpenMP
+- Kokkos::Cuda: NVIDIA's CUDA programming model for graphics
+  processing units (GPUs)
+- Kokkos::Serial: No thread parallelism
+
+%Kokkos also has optimizations for shared-memory parallel systems with
+nonuniform memory access (NUMA).  Its containers can hold data of any
+primitive ("plain old") data type (and some aggregate types).  %Kokkos
+Array may be used as a stand-alone programming model.
+
+%Kokkos' parallel operations include the following:
+
+- parallel_for: a thread-parallel "for loop"
+- parallel_reduce: a thread-parallel reduction
+- parallel_scan: a thread-parallel prefix scan operation
+
+as well as expert-level platform-independent interfaces to thread
+"teams," per-team "shared memory," synchronization, and atomic update
+operations.
+
+%Kokkos' data containers include the following:
+
+- Kokkos::View: A multidimensional array suitable for thread-parallel
+  operations.  Its layout (e.g., row-major or column-major) is
+  optimized by default for the particular thread-parallel device.
+- Kokkos::Vector: A drop-in replacement for std::vector that eases
+  porting from standard sequential C++ data structures to %Kokkos'
+  parallel data structures.
+- Kokkos::UnorderedMap: A parallel lookup table comparable in
+  functionality to std::unordered_map.
+
+%Kokkos also uses the above basic containers to implement higher-level
+data structures, like sparse graphs and matrices.
+
+A good place to start learning about %Kokkos would be <a href="http://trilinos.sandia.gov/events/trilinos_user_group_2013/presentations/2013-11-TUG-Kokkos-Tutorial.pdf">these tutorial slides</a> from the 2013 Trilinos Users' Group meeting.
+
+\section Kokkos_Classic %Kokkos Classic
+
+"%Kokkos Classic" consists of computational kernels that support the
+%Tpetra package.  These kernels include sparse matrix-vector multiply,
+sparse triangular solve, Gauss-Seidel, and dense vector operations.
+They are templated on the type of objects (\c Scalar) on which they
+operate.  This component was not meant to be visible to users; it is
+an implementation detail of the %Tpetra distributed linear algebra
+package.  
+
+%Kokkos Classic also implements a shared-memory parallel programming
+model.  This inspired and preceded the %Kokkos programming model
+described in the previous section.  Users should consider the %Kokkos
+Classic programming model deprecated, and prefer the new %Kokkos
+programming model.
+*/
diff --git a/lib/kokkos/example/CMakeLists.txt b/lib/kokkos/example/CMakeLists.txt
new file mode 100644
index 0000000000..3809cc2ea5
--- /dev/null
+++ b/lib/kokkos/example/CMakeLists.txt
@@ -0,0 +1,20 @@
+
+
+# Subpackage name must match what appears in kokkos/cmake/Dependencies.cmake
+#
+TRIBITS_SUBPACKAGE(Example)
+
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(query_device)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(fixture)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(feint)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(fenl)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(multi_fem)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(md_skeleton)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(global_2_local_ids)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(grow_array)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(sort_array)
+if(NOT Kokkos_ENABLE_Cuda)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(tutorial)
+endif()
+TRIBITS_SUBPACKAGE_POSTPROCESS()
+
diff --git a/lib/kokkos/example/README b/lib/kokkos/example/README
new file mode 100644
index 0000000000..ec64004842
--- /dev/null
+++ b/lib/kokkos/example/README
@@ -0,0 +1,16 @@
+This directory contains example application proxies that use different
+parts of Kokkos.  If you are looking for the FENL ("finite element
+nonlinear" solve) example, it has moved into the LinAlg subpackage of
+Tpetra.
+
+MANIFEST:
+
+  - common:  Header files used by different examples
+  - feint:   Unstructured finite-element method
+  - fixture: Some other finite-element method example
+  - global_2_local_ids: Example of global-to-local index lookup
+  - grow_array:   Parallel dynamic memory allocation
+  - md_skeleton:  Molecular dynamics
+  - query_device: Kokkos' HWLOC wrapper for querying device topology
+  - sort_array:   Parallel sort
+  - tutorial:     Kokkos tutorial (START HERE)
diff --git a/lib/kokkos/example/cmake/Dependencies.cmake b/lib/kokkos/example/cmake/Dependencies.cmake
new file mode 100644
index 0000000000..0d86e78712
--- /dev/null
+++ b/lib/kokkos/example/cmake/Dependencies.cmake
@@ -0,0 +1,4 @@
+TRIBITS_PACKAGE_DEFINE_DEPENDENCIES(
+  LIB_REQUIRED_DEP_PACKAGES KokkosCore KokkosContainers KokkosAlgorithms
+  TEST_OPTIONAL_DEP_TPLS CUSPARSE MKL
+  )
diff --git a/lib/kokkos/example/common/VectorImport.hpp b/lib/kokkos/example/common/VectorImport.hpp
new file mode 100644
index 0000000000..8ecd74d463
--- /dev/null
+++ b/lib/kokkos/example/common/VectorImport.hpp
@@ -0,0 +1,294 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_VECTORIMPORT_HPP
+#define KOKKOS_VECTORIMPORT_HPP
+
+#include <utility>
+#include <limits>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+#include <Kokkos_Core.hpp>
+
+#include <WrapMPI.hpp>
+
+namespace Kokkos {
+namespace Example {
+
+template< class CommMessageType , class CommIdentType , class VectorType >
+struct VectorImport ;
+
+} // namespace Example
+} // namespace Kokkos
+
+#if ! defined( KOKKOS_HAVE_MPI )
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+template< class CommMessageType , class CommIdentType , class VectorType >
+struct VectorImport {
+
+  const MPI_Comm comm ;
+  const unsigned count_owned ;
+  const unsigned count_receive ;
+
+  VectorImport( MPI_Comm arg_comm ,
+                const CommMessageType & ,
+                const CommMessageType & ,
+                const CommIdentType   & ,
+                const unsigned arg_count_owned ,
+                const unsigned arg_count_receive )
+    : comm( arg_comm )
+    , count_owned( arg_count_owned )
+    , count_receive( arg_count_receive )
+    {}
+
+  inline
+  void operator()( const VectorType & ) const {}
+};
+
+
+} // namespace Example
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#else /* defined( KOKKOS_HAVE_MPI ) */
+
+namespace Kokkos {
+namespace Example {
+
+template< class CommMessageType , class CommIdentType , class VectorType >
+class VectorImport {
+private:
+
+  // rank == 1 or array_layout == LayoutRight
+  enum { OK = Kokkos::Impl::StaticAssert<
+           ( VectorType::rank == 1 ) ||
+           Kokkos::Impl::is_same< typename VectorType::array_layout , Kokkos::LayoutRight >::value
+         >::value };
+
+  typedef typename VectorType::HostMirror HostVectorType ;
+
+  enum { ReceiveInPlace =
+    Kokkos::Impl::is_same< typename VectorType::memory_space ,
+                           typename HostVectorType::memory_space >::value };
+
+  const CommMessageType  recv_msg ;
+  const CommMessageType  send_msg ;
+  const CommIdentType    send_nodeid ;
+  VectorType             send_buffer ;
+  HostVectorType         host_send_buffer ;
+  HostVectorType         host_recv_buffer ;
+  unsigned               chunk ;
+
+public:
+
+  const MPI_Comm         comm ;
+  const unsigned         count_owned ;
+  const unsigned         count_receive ;
+
+  struct Pack {
+    typedef typename VectorType::execution_space execution_space ;
+    const CommIdentType  index ;
+    const VectorType     source ;
+    const VectorType     buffer ;
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()( const unsigned i ) const
+      { buffer( i ) = source( index(i) ); }
+
+    Pack( const CommIdentType  & arg_index ,
+          const VectorType     & arg_source ,
+          const VectorType     & arg_buffer )
+      : index( arg_index )
+      , source( arg_source )
+      , buffer( arg_buffer )
+    {
+      Kokkos::parallel_for( index.dimension_0() , *this );
+      execution_space::fence();
+    }
+  };
+
+  VectorImport( MPI_Comm arg_comm ,
+                const CommMessageType & arg_recv_msg ,
+                const CommMessageType & arg_send_msg ,
+                const CommIdentType   & arg_send_nodeid ,
+                const unsigned arg_count_owned ,
+                const unsigned arg_count_receive )
+    : recv_msg( arg_recv_msg )
+    , send_msg( arg_send_msg )
+    , send_nodeid( arg_send_nodeid )
+    , send_buffer()
+    , host_send_buffer()
+    , host_recv_buffer()
+    , comm( arg_comm )
+    , count_owned( arg_count_owned )
+    , count_receive( arg_count_receive )
+    {
+      if ( ! ReceiveInPlace ) {
+        host_recv_buffer = HostVectorType("recv_buffer",count_receive);
+      }
+
+      unsigned send_count = 0 ;
+      for ( unsigned i = 0 ; i < send_msg.dimension_0() ; ++i ) { send_count += send_msg(i,1); }
+      send_buffer      = VectorType("send_buffer",send_count);
+      host_send_buffer = Kokkos::create_mirror_view( send_buffer );
+    }
+
+  inline
+  void operator()( const VectorType & v ) const
+  {
+    typedef typename VectorType::value_type  scalar_type ;
+
+    const int mpi_tag = 42 ;
+    const unsigned chunk = v.dimension_1();
+
+    // Subvector for receives
+    const std::pair<unsigned,unsigned> recv_range( count_owned , count_owned + count_receive );
+    const VectorType recv_vector = Kokkos::subview( v , recv_range );
+
+    std::vector< MPI_Request > recv_request( recv_msg.dimension_0() , MPI_REQUEST_NULL );
+
+    { // Post receives
+      scalar_type * ptr =
+        ReceiveInPlace ? recv_vector.ptr_on_device() : host_recv_buffer.ptr_on_device();
+
+      for ( size_t i = 0 ; i < recv_msg.dimension_0() ; ++i ) {
+        const int proc  = recv_msg(i,0);
+        const int count = recv_msg(i,1) * chunk ;
+
+        MPI_Irecv( ptr , count * sizeof(scalar_type) , MPI_BYTE ,
+                   proc , mpi_tag , comm , & recv_request[i] );
+
+        ptr += count ;
+      }
+    }
+
+    MPI_Barrier( comm );
+
+    { // Pack and send 
+      const Pack pack( send_nodeid , v , send_buffer );
+
+      Kokkos::deep_copy( host_send_buffer , send_buffer );
+
+      scalar_type * ptr = host_send_buffer.ptr_on_device();
+
+      for ( size_t i = 0 ; i < send_msg.dimension_0() ; ++i ) {
+        const int proc  = send_msg(i,0);
+        const int count = send_msg(i,1) * chunk ;
+
+        // MPI_Ssend blocks until
+        // (1) a receive is matched for the message and
+        // (2) the send buffer can be re-used.
+        //
+        // It is suggested that MPI_Ssend will have the best performance:
+        // http://www.mcs.anl.gov/research/projects/mpi/sendmode.html .
+
+        MPI_Ssend( ptr ,
+                   count * sizeof(scalar_type) , MPI_BYTE ,
+                   proc , mpi_tag , comm );
+
+        ptr += count ;
+      }
+    }
+
+    // Wait for receives and verify:
+
+    for ( size_t i = 0 ; i < recv_msg.dimension_0() ; ++i ) {
+      MPI_Status recv_status ;
+      int recv_which = 0 ;
+      int recv_size  = 0 ;
+
+      MPI_Waitany( recv_msg.dimension_0() , & recv_request[0] , & recv_which , & recv_status );
+
+      const int recv_proc = recv_status.MPI_SOURCE ;
+
+      MPI_Get_count( & recv_status , MPI_BYTE , & recv_size );
+
+      // Verify message properly received:
+
+      const int  expected_proc = recv_msg(recv_which,0);
+      const int  expected_size = recv_msg(recv_which,1) * chunk * sizeof(scalar_type);
+
+      if ( ( expected_proc != recv_proc ) ||
+           ( expected_size != recv_size ) ) {
+
+        int local_rank  = 0 ;
+
+        MPI_Comm_rank( comm , & local_rank );
+
+        std::ostringstream msg ;
+        msg << "VectorImport error:"
+            << " P" << local_rank
+            << " received from P" << recv_proc
+            << " size "     << recv_size
+            << " expected " << expected_size
+            << " from P"    << expected_proc ;
+        throw std::runtime_error( msg.str() );
+      }
+    }
+
+    // Copy received data to device memory.
+
+    if ( ! ReceiveInPlace ) { Kokkos::deep_copy( recv_vector , host_recv_buffer ); }
+  }
+};
+
+} // namespace Example
+} // namespace Kokkos
+
+#endif
+
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_VECTORIMPORT_HPP */
+
+
diff --git a/lib/kokkos/example/common/WrapMPI.hpp b/lib/kokkos/example/common/WrapMPI.hpp
new file mode 100644
index 0000000000..c75e4bc5c7
--- /dev/null
+++ b/lib/kokkos/example/common/WrapMPI.hpp
@@ -0,0 +1,103 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_WRAP_MPI
+#define KOKKOS_EXAMPLE_WRAP_MPI
+
+#include <Kokkos_Macros.hpp>
+#include <string>
+
+#if defined( KOKKOS_HAVE_MPI )
+
+#include <mpi.h>
+
+namespace Kokkos {
+namespace Example {
+
+inline
+double all_reduce( double value , MPI_Comm comm )
+{
+  double local = value ;
+  MPI_Allreduce( & local , & value , 1 , MPI_DOUBLE , MPI_SUM , comm );
+  return value ;
+}
+
+inline
+double all_reduce_max( double value , MPI_Comm comm )
+{
+  double local = value ;
+  MPI_Allreduce( & local , & value , 1 , MPI_DOUBLE , MPI_MAX , comm );
+  return value ;
+}
+
+} // namespace Example
+} // namespace Kokkos
+
+#elif ! defined( KOKKOS_HAVE_MPI )
+
+/* Wrap the the MPI_Comm type and heavily used MPI functions
+ * to reduce the number of '#if defined( KOKKOS_HAVE_MPI )'
+ * blocks which have to be sprinkled throughout the examples.
+ */
+
+typedef int MPI_Comm ;
+
+inline int MPI_Comm_size( MPI_Comm , int * size ) { *size = 1 ; return 0 ; }
+inline int MPI_Comm_rank( MPI_Comm , int * rank ) { *rank = 0 ; return 0 ; }
+inline int MPI_Barrier( MPI_Comm ) { return 0; }
+
+namespace Kokkos {
+namespace Example {
+
+inline
+double all_reduce( double value , MPI_Comm ) { return value ; }
+
+inline
+double all_reduce_max( double value , MPI_Comm ) { return value ; }
+
+} // namespace Example
+} // namespace Kokkos
+
+#endif /* ! defined( KOKKOS_HAVE_MPI ) */
+#endif /* #ifndef KOKKOS_EXAMPLE_WRAP_MPI */
+
diff --git a/lib/kokkos/example/feint/CMakeLists.txt b/lib/kokkos/example/feint/CMakeLists.txt
new file mode 100644
index 0000000000..0018b9f9f5
--- /dev/null
+++ b/lib/kokkos/example/feint/CMakeLists.txt
@@ -0,0 +1,18 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../common)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../fixture)
+
+SET(SOURCES "")
+
+FILE(GLOB SOURCES *.cpp)
+
+LIST( APPEND SOURCES ../fixture/BoxElemPart.cpp)
+
+TRIBITS_ADD_EXECUTABLE(
+  feint
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  )
+
diff --git a/lib/kokkos/example/feint/ElemFunctor.hpp b/lib/kokkos/example/feint/ElemFunctor.hpp
new file mode 100644
index 0000000000..651e34c2ee
--- /dev/null
+++ b/lib/kokkos/example/feint/ElemFunctor.hpp
@@ -0,0 +1,489 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_FEINT_FUNCTORS_HPP
+#define KOKKOS_EXAMPLE_FEINT_FUNCTORS_HPP
+
+#include <stdio.h>
+#include <Kokkos_Core.hpp>
+#include <BoxElemFixture.hpp>
+
+namespace Kokkos {
+namespace Example {
+
+/** \brief  Numerically integrate a function on a finite element mesh and
+ *          project the integrated values to nodes.
+ */
+template< class FixtureType ,
+          class FunctionType ,
+          bool PerformScatterAddWithAtomic >
+struct FiniteElementIntegration ;
+
+// Specialized for an 'Example::BoxElemFixture' finite element mesh
+template< class Device , BoxElemPart::ElemOrder ElemOrder , class GridMap ,
+          class FunctionType ,
+          bool PerformScatterAddWithAtomic >
+struct FiniteElementIntegration<
+  Kokkos::Example::BoxElemFixture< Device , ElemOrder , GridMap > ,
+  FunctionType ,
+  PerformScatterAddWithAtomic >
+{
+  // Element mesh types:
+  typedef Kokkos::Example::BoxElemFixture< Device , ElemOrder >
+    BoxFixtureType ;
+
+  typedef Kokkos::Example::HexElement_Data< BoxFixtureType::ElemNode >
+    HexElemDataType ;
+
+  enum { ElemNodeCount    = HexElemDataType::element_node_count  };
+  enum { IntegrationCount = HexElemDataType::integration_count };
+  enum { ValueCount       = FunctionType::value_count };
+
+  // Dictionary of view types:
+  typedef View<int*,                              Device> ElemErrorType ;
+  typedef View<double*[ElemNodeCount][ValueCount],Device> ElemValueType ;
+  typedef View<double*[ValueCount],               Device> NodeValueType ;
+
+  // Data members for this Functor:
+  const HexElemDataType  m_hex_elem_data ; ///< Master element
+  const BoxFixtureType   m_box_fixture ;   ///< Unstructured mesh data
+  const FunctionType     m_function ;      ///< Function to integrate
+  const ElemErrorType    m_elem_error ;    ///< Flags for element errors
+  const ElemValueType    m_elem_integral ; ///< Per-element quantities
+  const NodeValueType    m_node_lumped ;   ///< Quantities lumped to nodes
+
+  //----------------------------------------
+
+  FiniteElementIntegration(
+    const BoxFixtureType & box_fixture ,
+    const FunctionType   & function )
+    : m_hex_elem_data()
+    , m_box_fixture( box_fixture ) // Shallow copy of the mesh fixture
+    , m_function( function )
+    , m_elem_error(    "elem_error"    , box_fixture.elem_count() )
+    , m_elem_integral( "elem_integral" , box_fixture.elem_count() )
+    , m_node_lumped(   "node_lumped"   , box_fixture.node_count() )
+    {}
+
+  //----------------------------------------
+  // Device for parallel dispatch.
+  typedef typename Device::execution_space execution_space;
+
+  // Value type for global parallel reduction.
+  struct value_type {
+    double value[ ValueCount ]; ///< Integrated quantitie
+    int    error ;              ///< Element inversion flag
+  };
+
+  //----------------------------------------
+  // Transform element interpolation function gradients and
+  // compute determinant of spatial jacobian.
+  KOKKOS_INLINE_FUNCTION
+  float transform_gradients(
+    const float  grad[][  ElemNodeCount ] , // Gradient of bases master element
+    const double coord[][ ElemNodeCount ] ,
+          float  dpsi[][  ElemNodeCount ] ) const
+  {
+    enum { TensorDim = 9 };
+    enum { j11 = 0 , j12 = 1 , j13 = 2 ,
+           j21 = 3 , j22 = 4 , j23 = 5 ,
+           j31 = 6 , j32 = 7 , j33 = 8 };
+
+    // Temporary for jacobian accumulation is double for summation accuracy.
+    double J[ TensorDim ] = { 0, 0, 0,  0, 0, 0,  0, 0, 0 };
+
+    for( int i = 0; i < ElemNodeCount ; ++i ) {
+      J[j11] += grad[0][i] * coord[0][i] ;
+      J[j12] += grad[0][i] * coord[1][i] ;
+      J[j13] += grad[0][i] * coord[2][i] ;
+
+      J[j21] += grad[1][i] * coord[0][i] ;
+      J[j22] += grad[1][i] * coord[1][i] ;
+      J[j23] += grad[1][i] * coord[2][i] ;
+
+      J[j31] += grad[2][i] * coord[0][i] ;
+      J[j32] += grad[2][i] * coord[1][i] ;
+      J[j33] += grad[2][i] * coord[2][i] ;
+    }
+
+    // Inverse jacobian, compute as double and store as float.
+    float invJ[ TensorDim ] = {
+      float( J[j22] * J[j33] - J[j23] * J[j32] ) ,
+      float( J[j13] * J[j32] - J[j12] * J[j33] ) ,
+      float( J[j12] * J[j23] - J[j13] * J[j22] ) ,
+
+      float( J[j23] * J[j31] - J[j21] * J[j33] ) ,
+      float( J[j11] * J[j33] - J[j13] * J[j31] ) ,
+      float( J[j13] * J[j21] - J[j11] * J[j23] ) ,
+
+      float( J[j21] * J[j32] - J[j22] * J[j31] ) ,
+      float( J[j12] * J[j31] - J[j11] * J[j32] ) ,
+      float( J[j11] * J[j22] - J[j12] * J[j21] ) };
+
+    const float detJ = J[j11] * invJ[j11] +
+                       J[j21] * invJ[j12] +
+                       J[j31] * invJ[j13] ;
+
+    {
+      const float detJinv = 1.0 / detJ ;
+      for ( int i = 0 ; i < TensorDim ; ++i ) { invJ[i] *= detJinv ; }
+    }
+
+    // Transform gradients:
+    for ( int i = 0; i < ElemNodeCount ; ++i ) {
+      dpsi[0][i] = grad[0][i] * invJ[j11] +
+                   grad[1][i] * invJ[j12] +
+                   grad[2][i] * invJ[j13];
+      dpsi[1][i] = grad[0][i] * invJ[j21] +
+                   grad[1][i] * invJ[j22] +
+                   grad[2][i] * invJ[j23];
+      dpsi[2][i] = grad[0][i] * invJ[j31] +
+                   grad[1][i] * invJ[j32] +
+                   grad[2][i] * invJ[j33];
+    }
+
+    return detJ ;
+  }
+
+  // Functor's function called for each element in the mesh
+  // to numerically integrate the function and add element quantities
+  // to the global integral.
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int ielem , value_type & update ) const
+  {
+    // Local temporaries for gathering nodal data.
+    double node_coord[3][ ElemNodeCount ];
+
+    int inode[ ElemNodeCount ] ;
+
+    // Gather indices of element's node from global memory to local memory.
+    for ( int i = 0 ; i < ElemNodeCount ; ++i ) {
+      inode[i] = m_box_fixture.elem_node( ielem , i );
+    }
+
+    // Gather coordinates of element's nodes from global memory to local memory.
+    for ( int i = 0 ; i < ElemNodeCount ; ++i ) {
+      node_coord[0][i] = m_box_fixture.node_coord( inode[i] , 0 );
+      node_coord[1][i] = m_box_fixture.node_coord( inode[i] , 1 );
+      node_coord[2][i] = m_box_fixture.node_coord( inode[i] , 2 );
+    }
+
+    // Local temporary to accumulate numerical integration
+    // of vector valued function.
+    double accum[ ValueCount ];
+
+    for ( int j = 0 ; j < ValueCount ; ++j ) { accum[j] = 0 ; }
+
+    int error = 0 ;
+
+    // Numerical integration loop for this element:
+    for ( int k = 0 ; k < IntegrationCount ; ++k ) {
+
+      // Integration point in space as interpolated from nodal coordinates:
+      double point[3] = { 0 , 0 , 0 };
+      for ( int i = 0 ; i < ElemNodeCount ; ++i ) {
+        point[0] += node_coord[0][i] * m_hex_elem_data.values[k][i] ;
+        point[1] += node_coord[1][i] * m_hex_elem_data.values[k][i] ;
+        point[2] += node_coord[2][i] * m_hex_elem_data.values[k][i] ;
+      }
+
+      // Example function vector value at cubature point:
+      double val_at_pt[ ValueCount ];
+      m_function( point , val_at_pt );
+
+      // Temporary array for transformed element basis functions' gradient.
+      // Not used in this example, but computed anyway by the more general
+      // deformation function.
+      float dpsi[3][ ElemNodeCount ];
+
+      // Compute deformation jacobian, transform basis function gradient,
+      // and return determinant of deformation jacobian.
+      float detJ = transform_gradients( m_hex_elem_data.gradients[k] ,
+                                        node_coord , dpsi );
+
+      // Check for inverted spatial jacobian
+      if ( detJ <= 0 ) { error = 1 ; detJ = 0 ; }
+
+      // Integration weight.
+      const float w = m_hex_elem_data.weights[k] * detJ ;
+
+      // Cubature of function.
+      for ( int j = 0 ; j < ValueCount ; ++j ) {
+        accum[j] += val_at_pt[j] * w ;
+      }
+    }
+
+    m_elem_error(ielem) = error ;
+
+
+    // Element contribution to global integral:
+
+    if ( error ) { update.error = 1 ; }
+
+    for ( int j = 0 ; j < ValueCount ; ++j ) { update.value[j] += accum[j] ; }
+
+    // Element-node quantity for lumping to nodes:
+    for ( int i = 0 ; i < ElemNodeCount ; ++i ) {
+      for ( int j = 0 ; j < ValueCount ; ++j ) {
+        // Save element's integral apportionment to nodes to global memory
+        m_elem_integral( ielem , i , j ) = accum[j] / ElemNodeCount ;
+      }
+    }
+
+    if ( PerformScatterAddWithAtomic ) {
+      // Option to immediately scatter-add the integrated quantities to nodes.
+      // This is a race condition as two or more threads could attempt
+      // concurrent update of nodal values.  The atomic_fetch_add (+=)
+      // function guarantees that the summation will occur correctly;
+      // however, there can be no guarantee for the order of summation.
+      // Due to non-associativity of floating point arithmetic the result
+      // is non-deterministic within bounds of floating point round-off.
+
+      for ( int i = 0 ; i < ElemNodeCount ; ++i ) {
+        for ( int j = 0 ; j < ValueCount ; ++j ) {
+          Kokkos::atomic_fetch_add( & m_node_lumped( inode[i] , j ) ,
+                                    m_elem_integral( ielem , i , j ) );
+        }
+      }
+    }
+  }
+  //--------------------------------------------------------------------------
+
+  // Initialization of the global reduction value.
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & update ) const
+  {
+    for ( int j = 0 ; j < ValueCount ; ++j ) update.value[j] = 0 ;
+    update.error = 0 ;
+  }
+
+  // Join two contributions to global reduction value.
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile       value_type & update ,
+             volatile const value_type & input ) const
+  {
+    for ( int j = 0 ; j < ValueCount ; ++j ) update.value[j] += input.value[j] ;
+    if ( input.error ) update.error = 1 ;
+  }
+};
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+template< class ViewElemNode ,
+          class ViewNodeScan ,
+          class ViewNodeElem >
+void map_node_to_elem( const ViewElemNode & elem_node ,
+                       const ViewNodeScan & node_scan ,
+                       const ViewNodeElem & node_elem );
+
+/** \brief  Functor to gather-sum elements' per-node quantities
+ *          to element nodes.  Gather-sum is thread safe and
+ *          does not require atomic updates.
+ */
+template< class ViewNodeValue ,
+          class ViewElemValue ,
+          bool  AlreadyUsedAtomic >
+struct LumpElemToNode {
+
+  typedef typename ViewElemValue::execution_space execution_space ;
+
+  // In this example we know that the ViewElemValue
+  // array specification is < double*[nNode][nValue] >
+
+#if KOKKOS_USING_EXP_VIEW
+  enum { value_count = ViewElemValue::dimension::N2 };
+#else
+  enum { value_count = ViewElemValue::shape_type::N2 };
+#endif
+
+  ViewNodeValue             m_node_value ; ///< Integrated values at nodes
+  ViewElemValue             m_elem_value ; ///< Values apportioned to nodes
+  View<int*,   execution_space> m_node_scan ;  ///< Offsets for nodes->element
+  View<int*[2],execution_space> m_node_elem ;  ///< Node->element connectivity
+
+  // Only allocate node->element connectivity if have
+  // not already used atomic updates for the nodes.
+  template< class ViewElemNode >
+  LumpElemToNode( const ViewNodeValue & node_value ,
+                  const ViewElemValue & elem_value ,
+                  const ViewElemNode  & elem_node )
+    : m_node_value( node_value )
+    , m_elem_value( elem_value )
+    , m_node_scan( "node_scan" ,
+                   AlreadyUsedAtomic ? 0 : node_value.dimension_0() + 1 )
+    , m_node_elem( "node_elem" ,
+                   AlreadyUsedAtomic ? 0 : elem_node.dimension_0() *
+                                           elem_node.dimension_1() )
+    {
+      if ( ! AlreadyUsedAtomic ) {
+        map_node_to_elem( elem_node , m_node_scan , m_node_elem );
+      }
+    }
+
+  //----------------------------------------
+
+  struct value_type { double value[ value_count ]; };
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int inode , value_type & update ) const
+  {
+    if ( ! AlreadyUsedAtomic ) {
+      // Sum element quantities to a local variable.
+      value_type local ;
+      for ( int j = 0 ; j < value_count ; ++j ) { local.value[j] = 0 ; }
+
+      {
+        // nodes' element ids span [i,end)
+        int i = m_node_scan(inode);
+        const int end = m_node_scan(inode+1);
+
+        for ( ; i < end ; ++i ) {
+          // element #ielem , local node #ielem_node is this node:
+          const int ielem      = m_node_elem(i,0);
+          const int ielem_node = m_node_elem(i,1);
+          // Sum the vector-values quantity
+          for ( int j = 0 ; j < value_count ; ++j ) {
+            local.value[j] += m_elem_value( ielem , ielem_node , j );
+          }
+        }
+      }
+
+      // Assign nodal quantity (no race condition).
+      // Sum global value.
+      for ( int j = 0 ; j < value_count ; ++j ) {
+        m_node_value( inode , j ) = local.value[j] ;
+        update.value[j] += local.value[j] ;
+      }
+    }
+    else {
+      // Already used atomic update of the nodal quantity,
+      // query and sum the value.
+      for ( int j = 0 ; j < value_count ; ++j ) {
+        update.value[j] += m_node_value( inode , j );
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & update ) const
+    { for ( int j = 0 ; j < value_count ; ++j ) { update.value[j] = 0 ; } }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile       value_type & update ,
+             volatile const value_type & input ) const
+    {
+      for ( int j = 0 ; j < value_count ; ++j ) {
+        update.value[j] += input.value[j] ;
+      }
+    }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+template< class ViewElemNode ,
+          class ViewNodeScan ,
+          class ViewNodeElem >
+void map_node_to_elem( const ViewElemNode & elem_node ,
+                       const ViewNodeScan & node_scan ,
+                       const ViewNodeElem & node_elem )
+{
+  typedef typename ViewElemNode::host_mirror_space host_mirror_space ;
+
+  const typename ViewElemNode::HostMirror host_elem_node =
+    Kokkos::create_mirror_view(elem_node);
+
+  const typename ViewNodeScan::HostMirror host_node_scan =
+    Kokkos::create_mirror_view(node_scan);
+
+  const typename ViewNodeElem::HostMirror host_node_elem =
+    Kokkos::create_mirror_view(node_elem);
+
+  const int elem_count      = host_elem_node.dimension_0();
+  const int elem_node_count = host_elem_node.dimension_1();
+  const int node_count      = host_node_scan.dimension_0() - 1 ;
+
+  const View<int*, host_mirror_space >
+    node_elem_count( "node_elem_count" , node_count );
+
+  Kokkos::deep_copy( host_elem_node , elem_node );
+
+  for ( int i = 0 ; i < elem_count ; ++i ) {
+    for ( int j = 0 ; j < elem_node_count ; ++j ) {
+      ++node_elem_count( host_elem_node(i,j) );
+    }
+  }
+
+  for ( int i = 0 ; i < node_count ; ++i ) {
+    host_node_scan(i+1) += host_node_scan(i) + node_elem_count(i);
+    node_elem_count(i) = 0 ;
+  }
+
+  for ( int i = 0 ; i < elem_count ; ++i ) {
+    for ( int j = 0 ; j < elem_node_count ; ++j ) {
+      const int inode  = host_elem_node(i,j);
+      const int offset = host_node_scan(inode) + node_elem_count(inode);
+
+      host_node_elem( offset , 0 ) = i ;
+      host_node_elem( offset , 1 ) = j ;
+
+      ++node_elem_count(inode);
+    }
+  }
+
+  Kokkos::deep_copy( node_scan , host_node_scan );
+  Kokkos::deep_copy( node_elem , host_node_elem );
+}
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_EXAMPLE_FEINT_FUNCTORS_HPP */
+
diff --git a/lib/kokkos/example/feint/Makefile b/lib/kokkos/example/feint/Makefile
new file mode 100644
index 0000000000..f198a974c1
--- /dev/null
+++ b/lib/kokkos/example/feint/Makefile
@@ -0,0 +1,61 @@
+KOKKOS_PATH = ../..
+
+vpath %.cpp ${KOKKOS_PATH}/example/fixture ${KOKKOS_PATH}/example/feint
+
+EXAMPLE_HEADERS = $(wildcard $(KOKKOS_PATH)/example/common/*.hpp ${KOKKOS_PATH}/example/fixture/*.hpp ${KOKKOS_PATH}/example/feint/*.hpp)
+
+default: build_all
+	echo "End Build"
+        
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?= -lpthread
+endif
+
+KOKKOS_CXXFLAGS +=	\
+	-I${KOKKOS_PATH}/example/common	\
+	-I${KOKKOS_PATH}/example/fixture	\
+	-I${KOKKOS_PATH}/example/feint
+
+EXE_EXAMPLE_FEINT = KokkosExample_Feint
+OBJ_EXAMPLE_FEINT = BoxElemPart.o main.o
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+  OBJ_EXAMPLE_FEINT += feint_cuda.o
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_PTHREADS), 1)
+  OBJ_EXAMPLE_FEINT += feint_threads.o
+endif
+
+ifeq ($(KOKKOS_INTERNAL_USE_OPENMP), 1)
+  OBJ_EXAMPLE_FEINT += feint_openmp.o
+endif
+
+TARGETS = $(EXE_EXAMPLE_FEINT)
+
+#TEST_TARGETS =
+
+$(EXE_EXAMPLE_FEINT) : $(OBJ_EXAMPLE_FEINT) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_EXAMPLE_FEINT) $(KOKKOS_LIBS) $(LIB) -o $(EXE_EXAMPLE_FEINT)
+
+build_all : $(TARGETS)
+
+test : build_all
+
+clean: kokkos-clean
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS) $(EXAMPLE_HEADERS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/feint/feint.hpp b/lib/kokkos/example/feint/feint.hpp
new file mode 100644
index 0000000000..4b7196c4c7
--- /dev/null
+++ b/lib/kokkos/example/feint/feint.hpp
@@ -0,0 +1,165 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_FEINT_HPP
+#define KOKKOS_EXAMPLE_FEINT_HPP
+
+#include <iostream>
+#include <BoxElemFixture.hpp>
+#include <ElemFunctor.hpp>
+#include <feint_fwd.hpp>
+
+namespace Kokkos {
+namespace Example {
+
+/** \brief  Vector valued function to numerically integrate.
+ *
+ *  F(X) = { 1 , x , y , z , x*y , y*z , z*x , x*y*z }
+ *
+ *  Integrates on a unit cube to:
+ *    { 1 , 1/2 , 1/2 , 1/2 , 1/4 , 1/4 , 1/4 , 1/8 }
+ */
+struct MyFunctionType {
+
+  enum { value_count = 8 };
+
+  // Evaluate function at coordinate.
+  template< typename CoordType , typename ValueType >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const CoordType point[] , ValueType value[] ) const
+    {
+      value[0] = 1 ;
+      value[1] = point[0] ;
+      value[2] = point[1] ;
+      value[3] = point[2] ;
+      value[4] = point[0] * point[1] ;
+      value[5] = point[1] * point[2] ;
+      value[6] = point[2] * point[0] ;
+      value[7] = point[0] * point[1] * point[2] ;
+    }
+};
+
+template < class Device , bool UseAtomic >
+void feint(
+  const unsigned global_elem_nx ,
+  const unsigned global_elem_ny ,
+  const unsigned global_elem_nz )
+{
+  //----------------------------------------
+  // Create the unstructured finite element mesh box fixture on the device:
+
+  typedef Kokkos::Example::
+    BoxElemFixture< Device , Kokkos::Example::BoxElemPart::ElemLinear >
+    // BoxElemFixture< Device , Kokkos::Example::BoxElemPart::ElemQuadratic >
+      BoxFixtureType ;
+
+  // MPI distributed parallel domain decomposition of the fixture.
+  // Either by element (DecomposeElem) or by node (DecomposeNode)
+  // with ghosted elements.
+
+  static const Kokkos::Example::BoxElemPart::Decompose
+    decompose = Kokkos::Example::BoxElemPart:: DecomposeElem ;
+    // decompose = Kokkos::Example::BoxElemPart:: DecomposeNode ;
+
+  // Not using MPI in this example.
+  const unsigned mpi_rank = 0 ;
+  const unsigned mpi_size = 1 ;
+
+  const BoxFixtureType fixture( decompose , mpi_size , mpi_rank ,
+                                global_elem_nx ,
+                                global_elem_ny ,
+                                global_elem_nz );
+
+  //----------------------------------------
+  // Create and execute the numerical integration functor on the device:
+
+  typedef Kokkos::Example::
+    FiniteElementIntegration< BoxFixtureType , MyFunctionType , UseAtomic >
+      FeintType ;
+
+  const FeintType feint( fixture , MyFunctionType() );
+
+  typename FeintType::value_type elem_integral ;
+
+  // A reduction for the global integral:
+  Kokkos::parallel_reduce( fixture.elem_count() , feint , elem_integral );
+
+  if ( elem_integral.error ) {
+    std::cout << "An element had a spatial jacobian error" << std::endl ;
+    return ;
+  }
+
+  std::cout << "Elem integral =" ;
+  for ( int i = 0 ; i < MyFunctionType::value_count ; ++i ) {
+    std::cout << " " << elem_integral.value[i] ;
+  }
+  std::cout << std::endl ;
+ 
+  //----------------------------------------
+  // Create and execute the nodal lumped value projection and reduction functor:
+
+  typedef Kokkos::Example::
+    LumpElemToNode< typename FeintType::NodeValueType ,
+                    typename FeintType::ElemValueType ,
+                    UseAtomic > LumpType ;
+
+  const LumpType lump( feint.m_node_lumped ,
+                       feint.m_elem_integral ,
+                       fixture.elem_node() );
+
+  typename LumpType ::value_type node_sum ;
+
+  Kokkos::parallel_reduce( fixture.node_count() , lump , node_sum );
+
+  std::cout << "Node lumped sum =" ;
+  for ( int i = 0 ; i < MyFunctionType::value_count ; ++i ) {
+    std::cout << " " << node_sum.value[i] ;
+  }
+  std::cout << std::endl ;
+}
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_EXAMPLE_FEINT_HPP */
+
diff --git a/lib/kokkos/example/feint/feint_cuda.cpp b/lib/kokkos/example/feint/feint_cuda.cpp
new file mode 100644
index 0000000000..1370822feb
--- /dev/null
+++ b/lib/kokkos/example/feint/feint_cuda.cpp
@@ -0,0 +1,67 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+#include <feint.hpp>
+
+namespace Kokkos {
+namespace Example {
+
+template void feint<Kokkos::Cuda,false>(
+  const unsigned global_elem_nx ,
+  const unsigned global_elem_ny ,
+  const unsigned global_elem_nz );
+
+template void feint<Kokkos::Cuda,true>(
+  const unsigned global_elem_nx ,
+  const unsigned global_elem_ny ,
+  const unsigned global_elem_nz );
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif
+
diff --git a/lib/kokkos/example/feint/feint_fwd.hpp b/lib/kokkos/example/feint/feint_fwd.hpp
new file mode 100644
index 0000000000..f02e547cfc
--- /dev/null
+++ b/lib/kokkos/example/feint/feint_fwd.hpp
@@ -0,0 +1,60 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_FEINT_FWD_HPP
+#define KOKKOS_EXAMPLE_FEINT_FWD_HPP
+
+namespace Kokkos {
+namespace Example {
+
+template < class Device , bool UseAtomic >
+void feint(
+  const unsigned global_elem_nx = 100 ,
+  const unsigned global_elem_ny = 115 ,
+  const unsigned global_elem_nz = 130 );
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_EXAMPLE_FEINT_FWD_HPP */
+
diff --git a/lib/kokkos/example/feint/feint_openmp.cpp b/lib/kokkos/example/feint/feint_openmp.cpp
new file mode 100644
index 0000000000..cf2fdca5ba
--- /dev/null
+++ b/lib/kokkos/example/feint/feint_openmp.cpp
@@ -0,0 +1,67 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#ifdef KOKKOS_HAVE_OPENMP
+
+#include <feint.hpp>
+
+namespace Kokkos {
+namespace Example {
+
+template void feint<Kokkos::OpenMP,false>(
+  const unsigned global_elem_nx ,
+  const unsigned global_elem_ny ,
+  const unsigned global_elem_nz );
+
+template void feint<Kokkos::OpenMP,true>(
+  const unsigned global_elem_nx ,
+  const unsigned global_elem_ny ,
+  const unsigned global_elem_nz );
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif
+
diff --git a/lib/kokkos/example/feint/feint_threads.cpp b/lib/kokkos/example/feint/feint_threads.cpp
new file mode 100644
index 0000000000..5dcf5654f1
--- /dev/null
+++ b/lib/kokkos/example/feint/feint_threads.cpp
@@ -0,0 +1,66 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+
+#include <feint.hpp>
+
+namespace Kokkos {
+namespace Example {
+
+template void feint< Kokkos::Threads ,false>(
+  const unsigned global_elem_nx ,
+  const unsigned global_elem_ny ,
+  const unsigned global_elem_nz );
+
+template void feint< Kokkos::Threads ,true>(
+  const unsigned global_elem_nx ,
+  const unsigned global_elem_ny ,
+  const unsigned global_elem_nz );
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif /* #if defined( KOKKOS_HAVE_PTHREAD ) */
diff --git a/lib/kokkos/example/feint/main.cpp b/lib/kokkos/example/feint/main.cpp
new file mode 100644
index 0000000000..c45d483e76
--- /dev/null
+++ b/lib/kokkos/example/feint/main.cpp
@@ -0,0 +1,110 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#include <utility>
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+#include <feint_fwd.hpp>
+
+int main()
+{
+#if defined( KOKKOS_HAVE_PTHREAD )
+  {
+    // Use 4 cores per NUMA region, unless fewer available
+
+    const unsigned use_numa_count     = Kokkos::hwloc::get_available_numa_count();
+    const unsigned use_cores_per_numa = std::min( 4u , Kokkos::hwloc::get_available_cores_per_numa() );
+
+    Kokkos::Threads::initialize( use_numa_count * use_cores_per_numa );
+
+    std::cout << "feint< Threads , NotUsingAtomic >" << std::endl ;
+    Kokkos::Example::feint< Kokkos::Threads , false >();
+
+    std::cout << "feint< Threads , Usingtomic >" << std::endl ;
+    Kokkos::Example::feint< Kokkos::Threads , true  >();
+
+    Kokkos::Threads::finalize();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_OPENMP )
+  {
+    // Use 4 cores per NUMA region, unless fewer available
+
+    const unsigned use_numa_count     = Kokkos::hwloc::get_available_numa_count();
+    const unsigned use_cores_per_numa = std::min( 4u , Kokkos::hwloc::get_available_cores_per_numa() );
+
+    Kokkos::OpenMP::initialize( use_numa_count * use_cores_per_numa );
+
+    std::cout << "feint< OpenMP , NotUsingAtomic >" << std::endl ;
+    Kokkos::Example::feint< Kokkos::OpenMP , false >();
+
+    std::cout << "feint< OpenMP , Usingtomic >" << std::endl ;
+    Kokkos::Example::feint< Kokkos::OpenMP , true  >();
+
+    Kokkos::OpenMP::finalize();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_CUDA )
+  {
+    // Initialize Host mirror device
+    Kokkos::HostSpace::execution_space::initialize(1);
+    const unsigned device_count = Kokkos::Cuda::detect_device_count();
+
+    // Use the last device:
+    Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice(device_count-1) );
+
+    std::cout << "feint< Cuda , NotUsingAtomic >" << std::endl ;
+    Kokkos::Example::feint< Kokkos::Cuda , false >();
+
+    std::cout << "feint< Cuda , UsingAtomic >" << std::endl ;
+    Kokkos::Example::feint< Kokkos::Cuda , true  >();
+
+    Kokkos::Cuda::finalize();
+    Kokkos::HostSpace::execution_space::finalize();
+
+  }
+#endif
+}
+
diff --git a/lib/kokkos/example/fenl/CGSolve.hpp b/lib/kokkos/example/fenl/CGSolve.hpp
new file mode 100644
index 0000000000..06a0030e09
--- /dev/null
+++ b/lib/kokkos/example/fenl/CGSolve.hpp
@@ -0,0 +1,296 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_CG_SOLVE
+#define KOKKOS_EXAMPLE_CG_SOLVE
+
+#include <cmath>
+#include <limits>
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Timer.hpp>
+
+#include <WrapMPI.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+template< typename ValueType , class Space >
+struct CrsMatrix {
+  typedef Kokkos::StaticCrsGraph< unsigned , Space , void , unsigned >  StaticCrsGraphType ;
+  typedef View< ValueType * , Space > coeff_type ;
+
+  StaticCrsGraphType  graph ;
+  coeff_type          coeff ;
+
+  CrsMatrix() : graph(), coeff() {}
+
+  CrsMatrix( const StaticCrsGraphType & arg_graph )
+    : graph( arg_graph )
+    , coeff( "crs_matrix_coeff" , arg_graph.entries.dimension_0() )
+    {}
+};
+
+template< typename MScalar 
+        , typename VScalar
+        , class Space >
+struct Multiply {
+
+  const Example::CrsMatrix< MScalar , Space >    m_A ;
+  const Kokkos::View< const VScalar * , Space > m_x ;
+  const Kokkos::View<       VScalar * , Space > m_y ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int iRow ) const
+    {
+      const int iEntryBegin = m_A.graph.row_map[iRow];
+      const int iEntryEnd   = m_A.graph.row_map[iRow+1];
+
+      double sum = 0 ;
+
+      for ( int iEntry = iEntryBegin ; iEntry < iEntryEnd ; ++iEntry ) {
+        sum += m_A.coeff(iEntry) * m_x( m_A.graph.entries(iEntry) );
+      }
+
+      m_y(iRow) = sum ;
+    }
+
+  Multiply( const View<       VScalar * , Space > & y 
+          , const CrsMatrix< MScalar , Space >    & A 
+          , const View< const VScalar * , Space > & x 
+          )
+  : m_A( A ), m_x( x ), m_y( y )
+  {}
+};
+
+template< typename MScalar
+        , typename VScalar
+        , class Space >
+inline
+void multiply( const int nrow
+             , const Kokkos::View< VScalar * , Space >    & y
+             , const Example::CrsMatrix< MScalar , Space > & A
+             , const Kokkos::View< VScalar * , Space >    & x
+             )
+{
+  Kokkos::parallel_for( Kokkos::RangePolicy<Space>(0,nrow), Multiply<MScalar,VScalar,Space>( y , A , x ) );
+}
+
+template< typename ValueType , class Space >
+struct WAXPBY {
+  const Kokkos::View< const ValueType * , Space >  m_x ;
+  const Kokkos::View< const ValueType * , Space >  m_y ;
+  const Kokkos::View<       ValueType * , Space >  m_w ;
+  const double m_alpha ;
+  const double m_beta ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int i ) const
+    { m_w(i) = m_alpha * m_x(i) + m_beta * m_y(i); }
+
+  WAXPBY( const View< ValueType * , Space >  & arg_w
+        , const double arg_alpha
+        , const View< ValueType * , Space >  & arg_x
+        , const double arg_beta
+        , const View< ValueType * , Space >  & arg_y
+        )
+    : m_x( arg_x )
+    , m_y( arg_y )
+    , m_w( arg_w )
+    , m_alpha( arg_alpha )
+    , m_beta( arg_beta )
+    {}
+};
+
+template< typename VScalar , class Space >
+void waxpby( const int n
+           , const Kokkos::View< VScalar * , Space > & arg_w
+           , const double                      arg_alpha
+           , const Kokkos::View< VScalar * , Space > & arg_x
+           , const double                      arg_beta
+           , const Kokkos::View< VScalar * , Space > & arg_y
+           )
+{
+  Kokkos::parallel_for( Kokkos::RangePolicy<Space>(0,n), WAXPBY<VScalar,Space>(arg_w,arg_alpha,arg_x,arg_beta,arg_y) );
+}
+
+template< typename VScalar , class Space >
+struct Dot {
+  typedef double value_type ;
+
+  const Kokkos::View< const VScalar * , Space >  m_x ;
+  const Kokkos::View< const VScalar * , Space >  m_y ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const int i , value_type & update ) const
+    { update += m_x(i) * m_y(i); }
+
+  Dot( const Kokkos::View< VScalar * , Space >  & arg_x
+     , const Kokkos::View< VScalar * , Space >  & arg_y
+     )
+    : m_x(arg_x), m_y(arg_y) {}
+};
+
+template< typename VScalar , class Space >
+double dot( const int n
+          , const Kokkos::View< VScalar * , Space > & arg_x
+          , const Kokkos::View< VScalar * , Space > & arg_y
+          )
+{
+  double result = 0 ;
+  Kokkos::parallel_reduce( Kokkos::RangePolicy<Space>(0,n) , Dot<VScalar,Space>( arg_x , arg_y ) , result );
+  return result ;
+}
+
+} // namespace Example
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+struct CGSolveResult {
+  size_t  iteration ;
+  double  iter_time ;
+  double  matvec_time ;
+  double  norm_res ;
+};
+
+template< class ImportType
+        , typename MScalar
+        , typename VScalar
+        , class Space
+        >
+inline
+void cgsolve( const ImportType & import
+            , const CrsMatrix< MScalar , Space >      & A
+            , const Kokkos::View< VScalar * , Space > & b
+            , const Kokkos::View< VScalar * , Space > & x
+            , const size_t  maximum_iteration = 200
+            , const double  tolerance = std::numeric_limits<double>::epsilon()
+            , CGSolveResult * result = 0
+            )
+{
+  typedef View< VScalar * , Space >  VectorType ;
+
+  const size_t count_owned = import.count_owned ;
+  const size_t count_total = import.count_owned + import.count_receive;
+
+  size_t  iteration = 0 ;
+  double  iter_time = 0 ;
+  double  matvec_time = 0 ;
+  double  norm_res = 0 ;
+
+  // Need input vector to matvec to be owned + received
+  VectorType pAll ( "cg::p" , count_total );
+
+  VectorType p = Kokkos::subview( pAll , std::pair<size_t,size_t>(0,count_owned) );
+  VectorType r ( "cg::r" , count_owned );
+  VectorType Ap( "cg::Ap", count_owned );
+
+  /* r = b - A * x ; */
+
+  /* p  = x       */  Kokkos::deep_copy( p , x );
+  /* import p     */  import( pAll );
+  /* Ap = A * p   */  multiply( count_owned , Ap , A , pAll );
+  /* r = b - Ap   */  waxpby( count_owned , r , 1.0 , b , -1.0 , Ap );
+  /* p  = r       */  Kokkos::deep_copy( p , r );
+
+  double old_rdot = Kokkos::Example::all_reduce( dot( count_owned , r , r ) , import.comm );
+
+  norm_res  = sqrt( old_rdot );
+  iteration = 0 ;
+
+  Kokkos::Timer wall_clock ;
+  Kokkos::Timer timer;
+
+  while ( tolerance < norm_res && iteration < maximum_iteration ) {
+
+    /* pAp_dot = dot( p , Ap = A * p ) */
+
+    timer.reset();
+    /* import p    */  import( pAll );
+    /* Ap = A * p  */  multiply( count_owned , Ap , A , pAll );
+    Space::fence();
+    matvec_time += timer.seconds();
+
+    const double pAp_dot = Kokkos::Example::all_reduce( dot( count_owned , p , Ap ) , import.comm );
+    const double alpha   = old_rdot / pAp_dot ;
+
+    /* x +=  alpha * p ;  */ waxpby( count_owned , x ,  alpha, p  , 1.0 , x );
+    /* r += -alpha * Ap ; */ waxpby( count_owned , r , -alpha, Ap , 1.0 , r );
+
+    const double r_dot = Kokkos::Example::all_reduce( dot( count_owned , r , r ) , import.comm );
+    const double beta  = r_dot / old_rdot ;
+
+    /* p = r + beta * p ; */ waxpby( count_owned , p , 1.0 , r , beta , p );
+
+    norm_res = sqrt( old_rdot = r_dot );
+
+    ++iteration ;
+  }
+
+  Space::fence();
+  iter_time = wall_clock.seconds();
+
+  if ( 0 != result ) {
+    result->iteration   = iteration ;
+    result->iter_time   = iter_time ;
+    result->matvec_time = matvec_time ;
+    result->norm_res    = norm_res ;
+  }
+}
+
+} // namespace Example
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_EXAMPLE_CG_SOLVE */
+
+
diff --git a/lib/kokkos/example/fenl/CMakeLists.txt b/lib/kokkos/example/fenl/CMakeLists.txt
new file mode 100644
index 0000000000..150656b16e
--- /dev/null
+++ b/lib/kokkos/example/fenl/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../common)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../fixture)
+
+SET(SOURCES "")
+
+FILE( GLOB SOURCES *.cpp )
+
+LIST( APPEND SOURCES ../fixture/BoxElemPart.cpp )
+
+TRIBITS_ADD_EXECUTABLE(
+  fenl
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/fenl/Makefile b/lib/kokkos/example/fenl/Makefile
new file mode 100644
index 0000000000..5d8e6fd303
--- /dev/null
+++ b/lib/kokkos/example/fenl/Makefile
@@ -0,0 +1,54 @@
+KOKKOS_PATH ?= ../..
+
+MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
+SRC_DIR := $(dir $(MAKEFILE_PATH))
+
+vpath %.cpp ${SRC_DIR}/../fixture ${SRC_DIR}
+
+EXAMPLE_HEADERS = $(wildcard $(SRC_DIR)/../common/*.hpp ${SRC_DIR}/../fixture/*.hpp ${SRC_DIR}/*.hpp)
+
+default: build_all
+	echo "End Build"
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+# KOKKOS_INTERNAL_USE_CUDA is not exported to installed Makefile.kokkos
+# use KOKKOS_DEVICE here
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?= -lpthread
+endif
+
+KOKKOS_CXXFLAGS +=	\
+	-I${SRC_DIR}/../common	\
+	-I${SRC_DIR}/../fixture	\
+	-I${SRC_DIR}
+
+EXE_EXAMPLE_FENL = KokkosExample_Fenl
+OBJ_EXAMPLE_FENL = BoxElemPart.o main.o fenl.o
+
+TARGETS = $(EXE_EXAMPLE_FENL)
+
+#TEST_TARGETS =
+
+$(EXE_EXAMPLE_FENL) : $(OBJ_EXAMPLE_FENL) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_EXAMPLE_FENL) $(KOKKOS_LIBS) $(LIB) -o $(EXE_EXAMPLE_FENL)
+
+build_all : $(TARGETS)
+
+test : build_all
+
+clean: kokkos-clean
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS) $(EXAMPLE_HEADERS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/fenl/fenl.cpp b/lib/kokkos/example/fenl/fenl.cpp
new file mode 100644
index 0000000000..a5cba608f4
--- /dev/null
+++ b/lib/kokkos/example/fenl/fenl.cpp
@@ -0,0 +1,117 @@
+/*
+// ************************************************************************
+//
+//   Kokkos: Manycore Performance-Portable Multidimensional Arrays
+//              Copyright (2012) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+*/
+
+#include <HexElement.hpp>
+#include <fenl_impl.hpp>
+
+namespace Kokkos {
+namespace Example {
+namespace FENL {
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+
+template
+Perf fenl< Kokkos::Threads , Kokkos::Example::BoxElemPart::ElemLinear >(
+  MPI_Comm comm ,
+  const int use_print ,
+  const int use_trials ,
+  const int use_atomic ,
+  const int global_elems[] );
+
+
+template
+Perf fenl< Kokkos::Threads , Kokkos::Example::BoxElemPart::ElemQuadratic >(
+  MPI_Comm comm ,
+  const int use_print ,
+  const int use_trials ,
+  const int use_atomic ,
+  const int global_elems[] );
+
+#endif
+
+
+#if defined (KOKKOS_HAVE_OPENMP)
+
+template
+Perf fenl< Kokkos::OpenMP , Kokkos::Example::BoxElemPart::ElemLinear >(
+  MPI_Comm comm ,
+  const int use_print ,
+  const int use_trials ,
+  const int use_atomic ,
+  const int global_elems[] );
+
+
+template
+Perf fenl< Kokkos::OpenMP , Kokkos::Example::BoxElemPart::ElemQuadratic >(
+  MPI_Comm comm ,
+  const int use_print ,
+  const int use_trials ,
+  const int use_atomic ,
+  const int global_elems[] );
+
+#endif
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+template
+Perf fenl< Kokkos::Cuda , Kokkos::Example::BoxElemPart::ElemLinear >(
+  MPI_Comm comm ,
+  const int use_print ,
+  const int use_trials ,
+  const int use_atomic ,
+  const int global_elems[] );
+
+
+template
+Perf fenl< Kokkos::Cuda , Kokkos::Example::BoxElemPart::ElemQuadratic >(
+  MPI_Comm comm ,
+  const int use_print ,
+  const int use_trials ,
+  const int use_atomic ,
+  const int global_elems[] );
+
+#endif
+
+
+} /* namespace FENL */
+} /* namespace Example */
+} /* namespace Kokkos */
+
diff --git a/lib/kokkos/example/fenl/fenl.hpp b/lib/kokkos/example/fenl/fenl.hpp
new file mode 100644
index 0000000000..e524a378c0
--- /dev/null
+++ b/lib/kokkos/example/fenl/fenl.hpp
@@ -0,0 +1,89 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_FENL_HPP
+#define KOKKOS_EXAMPLE_FENL_HPP
+
+#include <stdlib.h>
+#include <BoxElemPart.hpp>
+#include <WrapMPI.hpp>
+
+namespace Kokkos {
+namespace Example {
+namespace FENL {
+
+struct Perf {
+  size_t global_elem_count ;
+  size_t global_node_count ;
+  size_t newton_iter_count ;
+  size_t cg_iter_count ;
+  double map_ratio ;
+  double fill_node_set ;
+  double scan_node_count ;
+  double fill_graph_entries ;
+  double sort_graph_entries ;
+  double fill_element_graph ;
+  double create_sparse_matrix ;
+  double fill_time ;
+  double bc_time ;
+  double matvec_time ;
+  double cg_time ;
+  double newton_residual ;
+  double error_max ;
+
+};
+
+template < class Device , BoxElemPart::ElemOrder ElemOrder >
+Perf fenl(
+  MPI_Comm comm ,
+  const int use_print ,
+  const int use_trials ,
+  const int use_atomic ,
+  const int global_elems[] );
+
+} /* namespace FENL */
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_EXAMPLE_FENL_HPP */
+
diff --git a/lib/kokkos/example/fenl/fenl_functors.hpp b/lib/kokkos/example/fenl/fenl_functors.hpp
new file mode 100644
index 0000000000..3020c99a2f
--- /dev/null
+++ b/lib/kokkos/example/fenl/fenl_functors.hpp
@@ -0,0 +1,1173 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_FENLFUNCTORS_HPP
+#define KOKKOS_EXAMPLE_FENLFUNCTORS_HPP
+
+#include <stdio.h>
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+#include <limits>
+
+#include <Kokkos_Pair.hpp>
+#include <Kokkos_UnorderedMap.hpp>
+
+#include <impl/Kokkos_Timer.hpp>
+
+#include <BoxElemFixture.hpp>
+#include <HexElement.hpp>
+#include <CGSolve.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+namespace FENL {
+
+template< class ElemNodeIdView , class CrsGraphType , unsigned ElemNode >
+class NodeNodeGraph {
+public:
+
+  typedef typename ElemNodeIdView::execution_space  execution_space ;
+  typedef pair<unsigned,unsigned> key_type ;
+
+  typedef Kokkos::UnorderedMap< key_type, void , execution_space >  SetType ;
+  typedef typename CrsGraphType::row_map_type::non_const_type       RowMapType ;
+  typedef Kokkos::View< unsigned ,  execution_space >               UnsignedValue ;
+
+  // Static dimensions of 0 generate compiler warnings or errors.
+  typedef Kokkos::View< unsigned*[ElemNode][ElemNode] , execution_space >
+    ElemGraphType ;
+
+  struct TagFillNodeSet {};
+  struct TagScanNodeCount {};
+  struct TagFillGraphEntries {};
+  struct TagSortGraphEntries {};
+  struct TagFillElementGraph {};
+
+private:
+
+  enum PhaseType { FILL_NODE_SET ,
+                   SCAN_NODE_COUNT ,
+                   FILL_GRAPH_ENTRIES ,
+                   SORT_GRAPH_ENTRIES ,
+                   FILL_ELEMENT_GRAPH };
+
+  const unsigned        node_count ;
+  const ElemNodeIdView  elem_node_id ;
+  UnsignedValue         row_total ;
+  RowMapType            row_count ;
+  RowMapType            row_map ;
+  SetType               node_node_set ;
+  PhaseType             phase ;
+
+public:
+
+  CrsGraphType          graph ;
+  ElemGraphType         elem_graph ;
+
+  struct Times
+  {
+    double ratio;
+    double fill_node_set;
+    double scan_node_count;
+    double fill_graph_entries;
+    double sort_graph_entries;
+    double fill_element_graph;
+  };
+
+  NodeNodeGraph( const ElemNodeIdView & arg_elem_node_id ,
+                 const unsigned         arg_node_count,
+                 Times & results
+               )
+    : node_count(arg_node_count)
+    , elem_node_id( arg_elem_node_id )
+    , row_total( "row_total" )
+    , row_count(Kokkos::ViewAllocateWithoutInitializing("row_count") , node_count ) // will deep_copy to 0 inside loop
+    , row_map( "graph_row_map" , node_count + 1 )
+    , node_node_set()
+    , phase( FILL_NODE_SET )
+    , graph()
+    , elem_graph()
+   {
+      //--------------------------------
+      // Guess at capacity required for the map:
+
+      Kokkos::Timer wall_clock ;
+
+      wall_clock.reset();
+      phase = FILL_NODE_SET ;
+
+      // upper bound on the capacity
+      size_t set_capacity = (28ull * node_count) / 2;
+      unsigned failed_insert_count = 0 ;
+
+      do {
+        // Zero the row count to restart the fill
+        Kokkos::deep_copy( row_count , 0u );
+
+        node_node_set = SetType( ( set_capacity += failed_insert_count ) );
+
+        // May be larger that requested:
+        set_capacity = node_node_set.capacity();
+
+        Kokkos::parallel_reduce( Kokkos::RangePolicy<execution_space,TagFillNodeSet>(0,elem_node_id.dimension_0())
+                               , *this
+                               , failed_insert_count );
+
+      } while ( failed_insert_count );
+
+      execution_space::fence();
+      results.ratio = (double)node_node_set.size() / (double)node_node_set.capacity();
+      results.fill_node_set = wall_clock.seconds();
+      //--------------------------------
+
+      wall_clock.reset();
+      phase = SCAN_NODE_COUNT ;
+
+      // Exclusive scan of row_count into row_map
+      // including the final total in the 'node_count + 1' position.
+      // Zero the 'row_count' values.
+      Kokkos::parallel_scan( node_count , *this );
+
+      // Zero the row count for the fill:
+      Kokkos::deep_copy( row_count , 0u );
+
+      unsigned graph_entry_count = 0 ;
+
+      Kokkos::deep_copy( graph_entry_count , row_total );
+
+      // Assign graph's row_map and allocate graph's entries
+      graph.row_map = row_map ;
+      graph.entries = typename CrsGraphType::entries_type( "graph_entries" , graph_entry_count );
+
+      //--------------------------------
+      // Fill graph's entries from the (node,node) set.
+
+      execution_space::fence();
+      results.scan_node_count = wall_clock.seconds();
+
+      wall_clock.reset();
+      phase = FILL_GRAPH_ENTRIES ;
+      Kokkos::parallel_for( node_node_set.capacity() , *this );
+
+      execution_space::fence();
+      results.fill_graph_entries = wall_clock.seconds();
+
+      //--------------------------------
+      // Done with the temporary sets and arrays
+      wall_clock.reset();
+      phase = SORT_GRAPH_ENTRIES ;
+
+      row_total = UnsignedValue();
+      row_count = RowMapType();
+      row_map   = RowMapType();
+      node_node_set.clear();
+
+      //--------------------------------
+
+      Kokkos::parallel_for( node_count , *this );
+
+      execution_space::fence();
+      results.sort_graph_entries = wall_clock.seconds();
+
+      //--------------------------------
+      // Element-to-graph mapping:
+      wall_clock.reset();
+      phase = FILL_ELEMENT_GRAPH ;
+      elem_graph = ElemGraphType("elem_graph", elem_node_id.dimension_0() );
+      Kokkos::parallel_for( elem_node_id.dimension_0() , *this );
+
+      execution_space::fence();
+      results.fill_element_graph = wall_clock.seconds();
+    }
+
+  //------------------------------------
+  // parallel_for: create map and count row length
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const TagFillNodeSet & , unsigned ielem , unsigned & count ) const
+  {
+    // Loop over element's (row_local_node,col_local_node) pairs:
+    for ( unsigned row_local_node = 0 ; row_local_node < elem_node_id.dimension_1() ; ++row_local_node ) {
+
+      const unsigned row_node = elem_node_id( ielem , row_local_node );
+
+      for ( unsigned col_local_node = row_local_node ; col_local_node < elem_node_id.dimension_1() ; ++col_local_node ) {
+
+        const unsigned col_node = elem_node_id( ielem , col_local_node );
+
+        // If either node is locally owned then insert the pair into the unordered map:
+
+        if ( row_node < row_count.dimension_0() || col_node < row_count.dimension_0() ) {
+
+          const key_type key = (row_node < col_node) ? make_pair( row_node, col_node ) : make_pair( col_node, row_node ) ;
+
+          const typename SetType::insert_result result = node_node_set.insert( key );
+
+          // A successfull insert: the first time this pair was added
+          if ( result.success() ) {
+
+            // If row node is owned then increment count
+            if ( row_node < row_count.dimension_0() ) { atomic_fetch_add( & row_count( row_node ) , 1 ); }
+
+            // If column node is owned and not equal to row node then increment count
+            if ( col_node < row_count.dimension_0() && col_node != row_node ) { atomic_fetch_add( & row_count( col_node ) , 1 ); }
+          }
+          else if ( result.failed() ) {
+            ++count ;
+          }
+        }
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void fill_graph_entries( const unsigned iset ) const
+  {
+    if ( node_node_set.valid_at(iset) ) {
+      // Add each entry to the graph entries.
+
+      const key_type key = node_node_set.key_at(iset) ;
+      const unsigned row_node = key.first ;
+      const unsigned col_node = key.second ;
+
+      if ( row_node < row_count.dimension_0() ) {
+        const unsigned offset = graph.row_map( row_node ) + atomic_fetch_add( & row_count( row_node ) , 1 );
+        graph.entries( offset ) = col_node ;
+      }
+
+      if ( col_node < row_count.dimension_0() && col_node != row_node ) {
+        const unsigned offset = graph.row_map( col_node ) + atomic_fetch_add( & row_count( col_node ) , 1 );
+        graph.entries( offset ) = row_node ;
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void sort_graph_entries( const unsigned irow ) const
+  {
+    const unsigned row_beg = graph.row_map( irow );
+    const unsigned row_end = graph.row_map( irow + 1 );
+    for ( unsigned i = row_beg + 1 ; i < row_end ; ++i ) {
+      const unsigned col = graph.entries(i);
+      unsigned j = i ;
+      for ( ; row_beg < j && col < graph.entries(j-1) ; --j ) {
+        graph.entries(j) = graph.entries(j-1);
+      }
+      graph.entries(j) = col ;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void fill_elem_graph_map( const unsigned ielem ) const
+  {
+    for ( unsigned row_local_node = 0 ; row_local_node < elem_node_id.dimension_1() ; ++row_local_node ) {
+
+      const unsigned row_node = elem_node_id( ielem , row_local_node );
+
+      for ( unsigned col_local_node = 0 ; col_local_node < elem_node_id.dimension_1() ; ++col_local_node ) {
+
+        const unsigned col_node = elem_node_id( ielem , col_local_node );
+
+        unsigned entry = ~0u ;
+
+        if ( row_node + 1 < graph.row_map.dimension_0() ) {
+
+          const unsigned entry_end = graph.row_map( row_node + 1 );
+
+          entry = graph.row_map( row_node );
+
+          for ( ; entry < entry_end && graph.entries(entry) != col_node ; ++entry );
+
+          if ( entry == entry_end ) entry = ~0u ;
+        }
+
+        elem_graph( ielem , row_local_node , col_local_node ) = entry ;
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned iwork ) const
+  {
+/*
+    if ( phase == FILL_NODE_SET ) {
+      operator()( TagFillNodeSet() , iwork );
+    }
+    else */  
+    if ( phase == FILL_GRAPH_ENTRIES ) {
+      fill_graph_entries( iwork );
+    }
+    else if ( phase == SORT_GRAPH_ENTRIES ) {
+      sort_graph_entries( iwork );
+    }
+    else if ( phase == FILL_ELEMENT_GRAPH ) {
+      fill_elem_graph_map( iwork );
+    }
+  }
+
+  //------------------------------------
+  // parallel_scan: row offsets
+
+  typedef unsigned value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned irow , unsigned & update , const bool final ) const
+  {
+    // exclusive scan
+    if ( final ) { row_map( irow ) = update ; }
+
+    update += row_count( irow );
+
+    if ( final ) {
+      if ( irow + 1 == row_count.dimension_0() ) {
+        row_map( irow + 1 ) = update ;
+        row_total()         = update ;
+      }
+    }
+  }
+
+  // For the reduce phase:
+  KOKKOS_INLINE_FUNCTION
+  void init( const TagFillNodeSet & , unsigned & update ) const { update = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( const TagFillNodeSet & 
+           , volatile       unsigned & update
+           , volatile const unsigned & input ) const { update += input ; }
+
+  // For the scan phase::
+  KOKKOS_INLINE_FUNCTION
+  void init( unsigned & update ) const { update = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile       unsigned & update
+           , volatile const unsigned & input ) const { update += input ; }
+
+  //------------------------------------
+};
+
+} /* namespace FENL */
+} /* namespace Example */
+} /* namespace Kokkos  */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+namespace FENL {
+
+template< class ElemCompType >
+class NodeElemGatherFill {
+public:
+
+  typedef typename ElemCompType::execution_space         execution_space ;
+  typedef typename ElemCompType::vector_type         vector_type ;
+  typedef typename ElemCompType::sparse_matrix_type  sparse_matrix_type ;
+  typedef typename ElemCompType::elem_node_type      elem_node_type ;
+  typedef typename ElemCompType::elem_vectors_type   elem_vectors_type ;
+  typedef typename ElemCompType::elem_matrices_type  elem_matrices_type ;
+  typedef typename ElemCompType::elem_graph_type     elem_graph_type ;
+
+  static const unsigned ElemNodeCount = ElemCompType::ElemNodeCount ;
+
+  //------------------------------------
+
+private:
+
+  typedef Kokkos::StaticCrsGraph< unsigned[2] , execution_space >  CrsGraphType ;
+  typedef typename CrsGraphType::row_map_type::non_const_type  RowMapType ;
+  typedef Kokkos::View< unsigned ,  execution_space >              UnsignedValue ;
+
+  enum PhaseType { FILL_NODE_COUNT ,
+                   SCAN_NODE_COUNT ,
+                   FILL_GRAPH_ENTRIES ,
+                   SORT_GRAPH_ENTRIES ,
+                   GATHER_FILL };
+
+  const elem_node_type  elem_node_id ;
+  const elem_graph_type elem_graph ;
+  UnsignedValue         row_total ;
+  RowMapType            row_count ;
+  RowMapType            row_map ;
+  CrsGraphType          graph ;
+  vector_type           residual ;
+  sparse_matrix_type    jacobian ;
+  elem_vectors_type     elem_residual ;
+  elem_matrices_type    elem_jacobian ;
+  PhaseType             phase ;
+
+public:
+
+  NodeElemGatherFill()
+    : elem_node_id()
+    , elem_graph()
+    , row_total()
+    , row_count()
+    , row_map()
+    , graph()
+    , residual()
+    , jacobian()
+    , elem_residual()
+    , elem_jacobian()
+    , phase( FILL_NODE_COUNT )
+    {}
+
+  NodeElemGatherFill( const NodeElemGatherFill & rhs )
+    : elem_node_id(  rhs.elem_node_id )
+    , elem_graph(    rhs.elem_graph )
+    , row_total(     rhs.row_total )
+    , row_count(     rhs.row_count )
+    , row_map(       rhs.row_map )
+    , graph(         rhs.graph )
+    , residual(      rhs.residual )
+    , jacobian(      rhs.jacobian )
+    , elem_residual( rhs.elem_residual )
+    , elem_jacobian( rhs.elem_jacobian )
+    , phase(         rhs.phase )
+    {}
+
+  NodeElemGatherFill( const elem_node_type     & arg_elem_node_id ,
+                      const elem_graph_type    & arg_elem_graph ,
+                      const vector_type        & arg_residual ,
+                      const sparse_matrix_type & arg_jacobian ,
+                      const elem_vectors_type  & arg_elem_residual ,
+                      const elem_matrices_type & arg_elem_jacobian )
+    : elem_node_id( arg_elem_node_id )
+    , elem_graph( arg_elem_graph )
+    , row_total( "row_total" )
+    , row_count( "row_count" , arg_residual.dimension_0() )
+    , row_map( "graph_row_map" , arg_residual.dimension_0() + 1 )
+    , graph()
+    , residual( arg_residual )
+    , jacobian( arg_jacobian )
+    , elem_residual( arg_elem_residual )
+    , elem_jacobian( arg_elem_jacobian )
+    , phase( FILL_NODE_COUNT )
+    {
+      //--------------------------------
+      // Count node->element relations
+
+      phase = FILL_NODE_COUNT ;
+
+      Kokkos::parallel_for( elem_node_id.dimension_0() , *this );
+
+      //--------------------------------
+
+      phase = SCAN_NODE_COUNT ;
+
+      // Exclusive scan of row_count into row_map
+      // including the final total in the 'node_count + 1' position.
+      // Zero the 'row_count' values.
+      Kokkos::parallel_scan( residual.dimension_0() , *this );
+
+      // Zero the row count for the fill:
+      Kokkos::deep_copy( row_count , typename RowMapType::value_type(0) );
+
+      unsigned graph_entry_count = 0 ;
+
+      Kokkos::deep_copy( graph_entry_count , row_total );
+
+      // Assign graph's row_map and allocate graph's entries
+      graph.row_map = row_map ;
+
+      typedef typename CrsGraphType::entries_type graph_entries_type ;
+
+      graph.entries = graph_entries_type( "graph_entries" , graph_entry_count );
+
+      //--------------------------------
+      // Fill graph's entries from the (node,node) set.
+
+      phase = FILL_GRAPH_ENTRIES ;
+
+      Kokkos::deep_copy( row_count , 0u );
+      Kokkos::parallel_for( elem_node_id.dimension_0() , *this );
+
+      execution_space::fence();
+
+      //--------------------------------
+      // Done with the temporary sets and arrays
+
+      row_total = UnsignedValue();
+      row_count = RowMapType();
+      row_map   = RowMapType();
+
+      //--------------------------------
+
+      phase = SORT_GRAPH_ENTRIES ;
+      Kokkos::parallel_for( residual.dimension_0() , *this );
+
+      execution_space::fence();
+
+      phase = GATHER_FILL ;
+    }
+
+  void apply() const
+  {
+    Kokkos::parallel_for( residual.dimension_0() , *this );
+  }
+
+  //------------------------------------
+  //------------------------------------
+  // parallel_for: Count node->element pairs
+
+  KOKKOS_INLINE_FUNCTION
+  void fill_node_count( const unsigned ielem ) const
+  {
+    for ( unsigned row_local_node = 0 ; row_local_node < elem_node_id.dimension_1() ; ++row_local_node ) {
+
+      const unsigned row_node = elem_node_id( ielem , row_local_node );
+
+      if ( row_node < row_count.dimension_0() ) {
+        atomic_fetch_add( & row_count( row_node ) , 1 );
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void fill_graph_entries( const unsigned ielem ) const
+  {
+    for ( unsigned row_local_node = 0 ; row_local_node < elem_node_id.dimension_1() ; ++row_local_node ) {
+
+      const unsigned row_node = elem_node_id( ielem , row_local_node );
+
+      if ( row_node < row_count.dimension_0() ) {
+
+        const unsigned offset = graph.row_map( row_node ) + atomic_fetch_add( & row_count( row_node ) , 1 );
+
+        graph.entries( offset , 0 ) = ielem ;
+        graph.entries( offset , 1 ) = row_local_node ;
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void sort_graph_entries( const unsigned irow ) const
+  {
+    const unsigned row_beg = graph.row_map( irow );
+    const unsigned row_end = graph.row_map( irow + 1 );
+    for ( unsigned i = row_beg + 1 ; i < row_end ; ++i ) {
+      const unsigned elem  = graph.entries(i,0);
+      const unsigned local = graph.entries(i,1);
+      unsigned j = i ;
+      for ( ; row_beg < j && elem < graph.entries(j-1,0) ; --j ) {
+        graph.entries(j,0) = graph.entries(j-1,0);
+        graph.entries(j,1) = graph.entries(j-1,1);
+      }
+      graph.entries(j,0) = elem ;
+      graph.entries(j,1) = local ;
+    }
+  }
+
+  //------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void gather_fill( const unsigned irow ) const
+  {
+    const unsigned node_elem_begin = graph.row_map(irow);
+    const unsigned node_elem_end   = graph.row_map(irow+1);
+
+    //  for each element that a node belongs to
+
+    for ( unsigned i = node_elem_begin ; i < node_elem_end ; i++ ) {
+
+      const unsigned elem_id   = graph.entries( i, 0);
+      const unsigned row_index = graph.entries( i, 1);
+
+      residual(irow) += elem_residual(elem_id, row_index);
+
+      //  for each node in a particular related element
+      //  gather the contents of the element stiffness
+      //  matrix that belong in irow
+
+      for ( unsigned j = 0 ; j < ElemNodeCount ; ++j ) {
+        const unsigned A_index = elem_graph( elem_id , row_index , j );
+
+        jacobian.coeff( A_index ) += elem_jacobian( elem_id, row_index, j );
+      }
+    }
+  }
+
+  //------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned iwork ) const
+  {
+    if ( phase == FILL_NODE_COUNT ) {
+      fill_node_count( iwork );
+    }
+    else if ( phase == FILL_GRAPH_ENTRIES ) {
+      fill_graph_entries( iwork );
+    }
+    else if ( phase == SORT_GRAPH_ENTRIES ) {
+      sort_graph_entries( iwork );
+    }
+    else if ( phase == GATHER_FILL ) {
+      gather_fill( iwork );
+    }
+  }
+
+  //------------------------------------
+  // parallel_scan: row offsets
+
+  typedef unsigned value_type ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned irow , unsigned & update , const bool final ) const
+  {
+    // exclusive scan
+    if ( final ) { row_map( irow ) = update ; }
+
+    update += row_count( irow );
+
+    if ( final ) {
+      if ( irow + 1 == row_count.dimension_0() ) {
+        row_map( irow + 1 ) = update ;
+        row_total()         = update ;
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init( unsigned & update ) const { update = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile unsigned & update , const volatile unsigned & input ) const { update += input ; }
+};
+
+} /* namespace FENL */
+} /* namespace Example */
+} /* namespace Kokkos  */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+namespace FENL {
+
+template< class FiniteElementMeshType , class SparseMatrixType >
+class ElementComputation ;
+
+
+template< class ExecSpace , BoxElemPart::ElemOrder Order , class CoordinateMap , typename ScalarType >
+class ElementComputation<
+  Kokkos::Example::BoxElemFixture< ExecSpace , Order , CoordinateMap > ,
+  Kokkos::Example::CrsMatrix< ScalarType , ExecSpace > >
+{
+public:
+
+  typedef Kokkos::Example::BoxElemFixture< ExecSpace, Order, CoordinateMap >  mesh_type ;
+  typedef Kokkos::Example::HexElement_Data< mesh_type::ElemNode >             element_data_type ;
+
+  typedef Kokkos::Example::CrsMatrix< ScalarType , ExecSpace >  sparse_matrix_type ;
+  typedef typename sparse_matrix_type::StaticCrsGraphType       sparse_graph_type ;
+
+  typedef ExecSpace   execution_space ;
+  typedef ScalarType  scalar_type ;
+
+  static const unsigned SpatialDim       = element_data_type::spatial_dimension ;
+  static const unsigned TensorDim        = SpatialDim * SpatialDim ;
+  static const unsigned ElemNodeCount    = element_data_type::element_node_count ;
+  static const unsigned FunctionCount    = element_data_type::function_count ;
+  static const unsigned IntegrationCount = element_data_type::integration_count ;
+
+  //------------------------------------
+
+  typedef typename mesh_type::node_coord_type                                      node_coord_type ;
+  typedef typename mesh_type::elem_node_type                                       elem_node_type ;
+  typedef Kokkos::View< scalar_type*[FunctionCount][FunctionCount] , execution_space > elem_matrices_type ;
+  typedef Kokkos::View< scalar_type*[FunctionCount] ,                execution_space > elem_vectors_type ;
+  typedef Kokkos::View< scalar_type* ,                               execution_space > vector_type ;
+
+  typedef typename NodeNodeGraph< elem_node_type , sparse_graph_type , ElemNodeCount >::ElemGraphType elem_graph_type ;
+
+  //------------------------------------
+
+
+  //------------------------------------
+  // Computational data:
+
+  const element_data_type   elem_data ;
+  const elem_node_type      elem_node_ids ;
+  const node_coord_type     node_coords ;
+  const elem_graph_type     elem_graph ;
+  const elem_matrices_type  elem_jacobians ;
+  const elem_vectors_type   elem_residuals ;
+  const vector_type         solution ;
+  const vector_type         residual ;
+  const sparse_matrix_type  jacobian ;
+  const scalar_type         coeff_K ;
+
+  ElementComputation( const ElementComputation & rhs )
+    : elem_data()
+    , elem_node_ids( rhs.elem_node_ids )
+    , node_coords(   rhs.node_coords )
+    , elem_graph(    rhs.elem_graph )
+    , elem_jacobians( rhs.elem_jacobians )
+    , elem_residuals( rhs.elem_residuals )
+    , solution( rhs.solution )
+    , residual( rhs.residual )
+    , jacobian( rhs.jacobian )
+    , coeff_K( rhs.coeff_K )
+    {}
+
+  // If the element->sparse_matrix graph is provided then perform atomic updates
+  // Otherwise fill per-element contributions for subequent gather-add into a residual and jacobian.
+  ElementComputation( const mesh_type          & arg_mesh ,
+	              const scalar_type          arg_coeff_K ,
+                      const vector_type        & arg_solution ,
+                      const elem_graph_type    & arg_elem_graph ,
+                      const sparse_matrix_type & arg_jacobian ,
+                      const vector_type        & arg_residual )
+    : elem_data()
+    , elem_node_ids( arg_mesh.elem_node() )
+    , node_coords(   arg_mesh.node_coord() )
+    , elem_graph(    arg_elem_graph )
+    , elem_jacobians()
+    , elem_residuals()
+    , solution( arg_solution )
+    , residual( arg_residual )
+    , jacobian( arg_jacobian )
+    , coeff_K( arg_coeff_K )
+    {}
+
+  ElementComputation( const mesh_type    & arg_mesh ,
+	              const scalar_type    arg_coeff_K ,
+                      const vector_type  & arg_solution )
+    : elem_data()
+    , elem_node_ids( arg_mesh.elem_node() )
+    , node_coords(   arg_mesh.node_coord() )
+    , elem_graph()
+    , elem_jacobians( "elem_jacobians" , arg_mesh.elem_count() )
+    , elem_residuals( "elem_residuals" , arg_mesh.elem_count() )
+    , solution( arg_solution )
+    , residual()
+    , jacobian()
+    , coeff_K( arg_coeff_K )
+    {}
+
+  //------------------------------------
+
+  void apply() const
+  {
+    parallel_for( elem_node_ids.dimension_0() , *this );
+  }
+
+  //------------------------------------
+
+  static const unsigned FLOPS_transform_gradients =
+     /* Jacobian */           FunctionCount * TensorDim * 2 +
+     /* Inverse jacobian */   TensorDim * 6 + 6 +
+     /* Gradient transform */ FunctionCount * 15 ;
+
+  KOKKOS_INLINE_FUNCTION
+  float transform_gradients(
+    const float grad[][ FunctionCount ] , // Gradient of bases master element
+    const double x[] ,
+    const double y[] ,
+    const double z[] ,
+    float dpsidx[] ,
+    float dpsidy[] ,
+    float dpsidz[] ) const
+  {
+    enum { j11 = 0 , j12 = 1 , j13 = 2 ,
+           j21 = 3 , j22 = 4 , j23 = 5 ,
+           j31 = 6 , j32 = 7 , j33 = 8 };
+
+    // Jacobian accumulation:
+
+    double J[ TensorDim ] = { 0, 0, 0,  0, 0, 0,  0, 0, 0 };
+
+    for( unsigned i = 0; i < FunctionCount ; ++i ) {
+      const double x1 = x[i] ;
+      const double x2 = y[i] ;
+      const double x3 = z[i] ;
+
+      const float g1 = grad[0][i] ;
+      const float g2 = grad[1][i] ;
+      const float g3 = grad[2][i] ;
+
+      J[j11] += g1 * x1 ;
+      J[j12] += g1 * x2 ;
+      J[j13] += g1 * x3 ;
+
+      J[j21] += g2 * x1 ;
+      J[j22] += g2 * x2 ;
+      J[j23] += g2 * x3 ;
+
+      J[j31] += g3 * x1 ;
+      J[j32] += g3 * x2 ;
+      J[j33] += g3 * x3 ;
+    }
+
+    // Inverse jacobian:
+
+    float invJ[ TensorDim ] = {
+      static_cast<float>( J[j22] * J[j33] - J[j23] * J[j32] ) ,
+      static_cast<float>( J[j13] * J[j32] - J[j12] * J[j33] ) ,
+      static_cast<float>( J[j12] * J[j23] - J[j13] * J[j22] ) ,
+
+      static_cast<float>( J[j23] * J[j31] - J[j21] * J[j33] ) ,
+      static_cast<float>( J[j11] * J[j33] - J[j13] * J[j31] ) ,
+      static_cast<float>( J[j13] * J[j21] - J[j11] * J[j23] ) ,
+
+      static_cast<float>( J[j21] * J[j32] - J[j22] * J[j31] ) ,
+      static_cast<float>( J[j12] * J[j31] - J[j11] * J[j32] ) ,
+      static_cast<float>( J[j11] * J[j22] - J[j12] * J[j21] ) };
+
+    const float detJ = J[j11] * invJ[j11] +
+                       J[j21] * invJ[j12] +
+                       J[j31] * invJ[j13] ;
+
+    const float detJinv = 1.0 / detJ ;
+
+    for ( unsigned i = 0 ; i < TensorDim ; ++i ) { invJ[i] *= detJinv ; }
+
+    // Transform gradients:
+
+    for( unsigned i = 0; i < FunctionCount ; ++i ) {
+      const float g0 = grad[0][i];
+      const float g1 = grad[1][i];
+      const float g2 = grad[2][i];
+
+      dpsidx[i] = g0 * invJ[j11] + g1 * invJ[j12] + g2 * invJ[j13];
+      dpsidy[i] = g0 * invJ[j21] + g1 * invJ[j22] + g2 * invJ[j23];
+      dpsidz[i] = g0 * invJ[j31] + g1 * invJ[j32] + g2 * invJ[j33];
+    }
+
+    return detJ ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void contributeResidualJacobian(
+    const float coeff_k ,
+    const double dof_values[] ,
+    const float dpsidx[] ,
+    const float dpsidy[] ,
+    const float dpsidz[] ,
+    const float detJ ,
+    const float integ_weight ,
+    const float bases_vals[] ,
+    double elem_res[] ,
+    double elem_mat[][ FunctionCount ] ) const
+  {
+    double value_at_pt = 0 ;
+    double gradx_at_pt = 0 ;
+    double grady_at_pt = 0 ;
+    double gradz_at_pt = 0 ;
+
+    for ( unsigned m = 0 ; m < FunctionCount ; m++ ) {
+      value_at_pt += dof_values[m] * bases_vals[m] ;
+      gradx_at_pt += dof_values[m] * dpsidx[m] ;
+      grady_at_pt += dof_values[m] * dpsidy[m] ;
+      gradz_at_pt += dof_values[m] * dpsidz[m] ;
+    }
+
+    const scalar_type k_detJ_weight = coeff_k        * detJ * integ_weight ;
+    const double res_val = value_at_pt * value_at_pt * detJ * integ_weight ;
+    const double mat_val = 2.0 * value_at_pt         * detJ * integ_weight ;
+
+    // $$ R_i = \int_{\Omega} \nabla \phi_i \cdot (k \nabla T) + \phi_i T^2 d \Omega $$
+    // $$ J_{i,j} = \frac{\partial R_i}{\partial T_j} = \int_{\Omega} k \nabla \phi_i \cdot \nabla \phi_j + 2 \phi_i \phi_j T d \Omega $$
+
+    for ( unsigned m = 0; m < FunctionCount; ++m) {
+      double * const mat = elem_mat[m] ;
+      const float bases_val_m = bases_vals[m];
+      const float dpsidx_m    = dpsidx[m] ;
+      const float dpsidy_m    = dpsidy[m] ;
+      const float dpsidz_m    = dpsidz[m] ;
+
+      elem_res[m] += k_detJ_weight * ( dpsidx_m * gradx_at_pt +
+                                       dpsidy_m * grady_at_pt +
+                                       dpsidz_m * gradz_at_pt ) +
+                     res_val * bases_val_m ;
+
+      for( unsigned n = 0; n < FunctionCount; n++) {
+
+        mat[n] += k_detJ_weight * ( dpsidx_m * dpsidx[n] +
+                                    dpsidy_m * dpsidy[n] +
+                                    dpsidz_m * dpsidz[n] ) +
+                  mat_val * bases_val_m * bases_vals[n];
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned ielem ) const
+  {
+    // Gather nodal coordinates and solution vector:
+
+    double x[ FunctionCount ] ;
+    double y[ FunctionCount ] ;
+    double z[ FunctionCount ] ;
+    double val[ FunctionCount ] ;
+    unsigned node_index[ ElemNodeCount ];
+
+    for ( unsigned i = 0 ; i < ElemNodeCount ; ++i ) {
+      const unsigned ni = elem_node_ids( ielem , i );
+
+      node_index[i] = ni ;
+
+      x[i] = node_coords( ni , 0 );
+      y[i] = node_coords( ni , 1 );
+      z[i] = node_coords( ni , 2 );
+
+      val[i] = solution( ni );
+    }
+
+
+    double elem_vec[ FunctionCount ] ;
+    double elem_mat[ FunctionCount ][ FunctionCount ] ;
+
+    for( unsigned i = 0; i < FunctionCount ; i++ ) {
+      elem_vec[i] = 0 ;
+      for( unsigned j = 0; j < FunctionCount ; j++){
+        elem_mat[i][j] = 0 ;
+      }
+    }
+
+
+    for ( unsigned i = 0 ; i < IntegrationCount ; ++i ) {
+      float dpsidx[ FunctionCount ] ;
+      float dpsidy[ FunctionCount ] ;
+      float dpsidz[ FunctionCount ] ;
+
+      const float detJ =
+        transform_gradients( elem_data.gradients[i] , x , y , z ,
+                             dpsidx , dpsidy , dpsidz );
+
+      contributeResidualJacobian( coeff_K ,
+                                  val , dpsidx , dpsidy , dpsidz ,
+                                  detJ ,
+                                  elem_data.weights[i] ,
+                                  elem_data.values[i] ,
+                                  elem_vec , elem_mat );
+    }
+
+#if 0
+
+if ( 1 == ielem ) {
+  printf("ElemResidual { %f %f %f %f %f %f %f %f }\n",
+         elem_vec[0], elem_vec[1], elem_vec[2], elem_vec[3],
+         elem_vec[4], elem_vec[5], elem_vec[6], elem_vec[7]);
+
+  printf("ElemJacobian {\n");
+
+  for ( unsigned j = 0 ; j < FunctionCount ; ++j ) {
+  printf("  { %f %f %f %f %f %f %f %f }\n",
+         elem_mat[j][0], elem_mat[j][1], elem_mat[j][2], elem_mat[j][3],
+         elem_mat[j][4], elem_mat[j][5], elem_mat[j][6], elem_mat[j][7]);
+  }
+  printf("}\n");
+}
+
+#endif
+
+    if ( ! residual.dimension_0() ) {
+      for( unsigned i = 0; i < FunctionCount ; i++){
+        elem_residuals(ielem, i) = elem_vec[i] ;
+        for( unsigned j = 0; j < FunctionCount ; j++){
+          elem_jacobians(ielem, i, j) = elem_mat[i][j] ;
+        }
+      }
+    }
+    else {
+      for( unsigned i = 0 ; i < FunctionCount ; i++ ) {
+        const unsigned row = node_index[i] ;
+        if ( row < residual.dimension_0() ) {
+          atomic_fetch_add( & residual( row ) , elem_vec[i] );
+
+          for( unsigned j = 0 ; j < FunctionCount ; j++ ) {
+            const unsigned entry = elem_graph( ielem , i , j );
+            if ( entry != ~0u ) {
+              atomic_fetch_add( & jacobian.coeff( entry ) , elem_mat[i][j] );
+            }
+          }
+        }
+      }
+    }
+  }
+}; /* ElementComputation */
+
+//----------------------------------------------------------------------------
+
+template< class FixtureType , class SparseMatrixType >
+class DirichletComputation ;
+
+template< class ExecSpace , BoxElemPart::ElemOrder Order , class CoordinateMap , typename ScalarType >
+class DirichletComputation<
+  Kokkos::Example::BoxElemFixture< ExecSpace , Order , CoordinateMap > ,
+  Kokkos::Example::CrsMatrix< ScalarType , ExecSpace > >
+{
+public:
+
+  typedef Kokkos::Example::BoxElemFixture< ExecSpace, Order, CoordinateMap >  mesh_type ;
+  typedef typename mesh_type::node_coord_type                                 node_coord_type ;
+  typedef typename node_coord_type::value_type                                scalar_coord_type ;
+
+  typedef Kokkos::Example::CrsMatrix< ScalarType , ExecSpace >  sparse_matrix_type ;
+  typedef typename sparse_matrix_type::StaticCrsGraphType       sparse_graph_type ;
+
+  typedef ExecSpace   execution_space ;
+  typedef ScalarType  scalar_type ;
+
+  //------------------------------------
+
+  typedef Kokkos::View< scalar_type* , execution_space > vector_type ;
+
+  //------------------------------------
+  // Computational data:
+
+  const node_coord_type     node_coords ;
+  const vector_type         solution ;
+  const sparse_matrix_type  jacobian ;
+  const vector_type         residual ;
+  const scalar_type         bc_lower_value ;
+  const scalar_type         bc_upper_value ;
+  const scalar_coord_type   bc_lower_limit ;
+  const scalar_coord_type   bc_upper_limit ;
+  const unsigned            bc_plane ;
+  const unsigned            node_count ;
+        bool                init ;
+
+
+  DirichletComputation( const mesh_type          & arg_mesh ,
+                        const vector_type        & arg_solution ,
+                        const sparse_matrix_type & arg_jacobian ,
+                        const vector_type        & arg_residual ,
+                        const unsigned             arg_bc_plane ,
+                        const scalar_type          arg_bc_lower_value ,
+                        const scalar_type          arg_bc_upper_value )
+    : node_coords( arg_mesh.node_coord() )
+    , solution(    arg_solution )
+    , jacobian(    arg_jacobian )
+    , residual(    arg_residual )
+    , bc_lower_value( arg_bc_lower_value )
+    , bc_upper_value( arg_bc_upper_value )
+    , bc_lower_limit( std::numeric_limits<scalar_coord_type>::epsilon() )
+    , bc_upper_limit( scalar_coord_type(1) - std::numeric_limits<scalar_coord_type>::epsilon() )
+    , bc_plane(       arg_bc_plane )
+    , node_count( arg_mesh.node_count_owned() )
+    , init( false )
+    {
+      parallel_for( node_count , *this );
+      init = true ;
+    }
+
+  void apply() const
+  {
+    parallel_for( node_count , *this );
+  }
+
+  //------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned inode ) const
+  {
+    //  Apply dirichlet boundary condition on the Solution and Residual vectors.
+    //  To maintain the symmetry of the original global stiffness matrix,
+    //  zero out the columns that correspond to boundary conditions, and
+    //  update the residual vector accordingly
+
+    const unsigned iBeg = jacobian.graph.row_map[inode];
+    const unsigned iEnd = jacobian.graph.row_map[inode+1];
+
+    const scalar_coord_type c = node_coords(inode,bc_plane);
+    const bool bc_lower = c <= bc_lower_limit ;
+    const bool bc_upper = bc_upper_limit <= c ;
+
+    if ( ! init ) {
+      solution(inode) = bc_lower ? bc_lower_value : (
+                        bc_upper ? bc_upper_value : 0 );
+    }
+    else {
+      if ( bc_lower || bc_upper ) {
+
+        residual(inode) = 0 ;
+
+        //  zero each value on the row, and leave a one
+        //  on the diagonal
+
+        for( unsigned i = iBeg ; i < iEnd ; ++i ) {
+          jacobian.coeff(i) = int(inode) == int(jacobian.graph.entries(i)) ? 1 : 0 ;
+        }
+      }
+      else {
+
+        //  Find any columns that are boundary conditions.
+        //  Clear them and adjust the residual vector
+
+        for( unsigned i = iBeg ; i < iEnd ; ++i ) {
+          const unsigned       cnode = jacobian.graph.entries(i) ;
+          const scalar_coord_type cc = node_coords(cnode,bc_plane);
+
+          if ( ( cc <= bc_lower_limit ) || ( bc_upper_limit <= cc ) ) {
+            jacobian.coeff(i) = 0 ;
+          }
+        }
+      }
+    }
+  }
+};
+
+} /* namespace FENL */
+} /* namespace Example */
+} /* namespace Kokkos  */
+
+//----------------------------------------------------------------------------
+
+/* A Cuda-specific specialization for the element computation functor. */
+#if defined( __CUDACC__ )
+// #include <NonlinearElement_Cuda.hpp>
+#endif
+
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_EXAMPLE_FENLFUNCTORS_HPP */
+
diff --git a/lib/kokkos/example/fenl/fenl_impl.hpp b/lib/kokkos/example/fenl/fenl_impl.hpp
new file mode 100644
index 0000000000..64070ce55f
--- /dev/null
+++ b/lib/kokkos/example/fenl/fenl_impl.hpp
@@ -0,0 +1,598 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_FENL_IMPL_HPP
+#define KOKKOS_EXAMPLE_FENL_IMPL_HPP
+
+#include <math.h>
+
+// Kokkos libraries' headers:
+
+#include <Kokkos_UnorderedMap.hpp>
+#include <Kokkos_StaticCrsGraph.hpp>
+#include <impl/Kokkos_Timer.hpp>
+
+// Examples headers:
+
+#include <BoxElemFixture.hpp>
+#include <VectorImport.hpp>
+#include <CGSolve.hpp>
+
+#include <fenl.hpp>
+#include <fenl_functors.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+namespace FENL {
+
+inline
+double maximum( MPI_Comm comm , double local )
+{
+  double global = local ;
+#if defined( KOKKOS_HAVE_MPI )
+  MPI_Allreduce( & local , & global , 1 , MPI_DOUBLE , MPI_MAX , comm );
+#endif
+  return global ;
+}
+
+} /* namespace FENL */
+} /* namespace Example */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+namespace FENL {
+
+class ManufacturedSolution {
+public:
+
+  // Manufactured solution for one dimensional nonlinear PDE
+  //
+  //  -K T_zz + T^2 = 0 ; T(zmin) = T_zmin ; T(zmax) = T_zmax
+  //
+  //  Has an analytic solution of the form:
+  //
+  //    T(z) = ( a ( z - zmin ) + b )^(-2) where K = 1 / ( 6 a^2 )
+  //
+  //  Given T_0 and T_L compute K for this analytic solution.
+  //
+  //  Two analytic solutions:
+  //
+  //    Solution with singularity:
+  //    , a( ( 1.0 / sqrt(T_zmax) + 1.0 / sqrt(T_zmin) ) / ( zmax - zmin ) )
+  //    , b( -1.0 / sqrt(T_zmin) )
+  //
+  //    Solution without singularity:
+  //    , a( ( 1.0 / sqrt(T_zmax) - 1.0 / sqrt(T_zmin) ) / ( zmax - zmin ) )
+  //    , b( 1.0 / sqrt(T_zmin) )
+
+  const double zmin ;
+  const double zmax ;
+  const double T_zmin ;
+  const double T_zmax ;
+  const double a ;
+  const double b ;
+  const double K ;
+
+  ManufacturedSolution( const double arg_zmin ,
+                        const double arg_zmax ,
+                        const double arg_T_zmin ,
+                        const double arg_T_zmax )
+    : zmin( arg_zmin )
+    , zmax( arg_zmax )
+    , T_zmin( arg_T_zmin )
+    , T_zmax( arg_T_zmax )
+    , a( ( 1.0 / sqrt(T_zmax) - 1.0 / sqrt(T_zmin) ) / ( zmax - zmin ) )
+    , b( 1.0 / sqrt(T_zmin) )
+    , K( 1.0 / ( 6.0 * a * a ) )
+    {}
+
+  double operator()( const double z ) const
+  {
+    const double tmp = a * ( z - zmin ) + b ;
+    return 1.0 / ( tmp * tmp );
+  }
+};
+
+} /* namespace FENL */
+} /* namespace Example */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+namespace FENL {
+
+template < class Space , BoxElemPart::ElemOrder ElemOrder >
+Perf fenl(
+  MPI_Comm comm ,
+  const int use_print ,
+  const int use_trials ,
+  const int use_atomic ,
+  const int use_elems[] )
+{
+  typedef Kokkos::Example::BoxElemFixture< Space , ElemOrder > FixtureType ;
+
+  typedef Kokkos::Example::CrsMatrix< double , Space >
+    SparseMatrixType ;
+
+  typedef typename SparseMatrixType::StaticCrsGraphType
+    SparseGraphType ;
+
+  typedef Kokkos::Example::FENL::NodeNodeGraph< typename FixtureType::elem_node_type , SparseGraphType , FixtureType::ElemNode >
+     NodeNodeGraphType ;
+
+  typedef Kokkos::Example::FENL::ElementComputation< FixtureType , SparseMatrixType >
+    ElementComputationType ;
+
+  typedef Kokkos::Example::FENL::DirichletComputation< FixtureType , SparseMatrixType >
+    DirichletComputationType ;
+
+  typedef NodeElemGatherFill< ElementComputationType >
+    NodeElemGatherFillType ;
+
+  typedef typename ElementComputationType::vector_type VectorType ;
+
+  typedef Kokkos::Example::VectorImport<
+     typename FixtureType::comm_list_type ,
+     typename FixtureType::send_nodeid_type ,
+     VectorType > ImportType ;
+
+  //------------------------------------
+
+  const unsigned newton_iteration_limit     = 10 ;
+  const double   newton_iteration_tolerance = 1e-7 ;
+  const unsigned cg_iteration_limit         = 200 ;
+  const double   cg_iteration_tolerance     = 1e-7 ;
+
+  //------------------------------------
+
+  const int print_flag = use_print && Kokkos::Impl::is_same< Kokkos::HostSpace , typename Space::memory_space >::value ;
+
+  int comm_rank ;
+  int comm_size ;
+
+  MPI_Comm_rank( comm , & comm_rank );
+  MPI_Comm_size( comm , & comm_size );
+
+  // Decompose by node to avoid mpi-communication for assembly
+
+  const float bubble_x = 1.0 ;
+  const float bubble_y = 1.0 ;
+  const float bubble_z = 1.0 ;
+
+  const FixtureType fixture( BoxElemPart::DecomposeNode , comm_size , comm_rank ,
+                             use_elems[0] , use_elems[1] , use_elems[2] ,
+                             bubble_x , bubble_y , bubble_z );
+
+
+  {
+    int global_error = ! fixture.ok();
+
+#if defined( KOKKOS_HAVE_MPI )
+    int local_error = global_error ;
+    global_error = 0 ;
+    MPI_Allreduce( & local_error , & global_error , 1 , MPI_INT , MPI_SUM , comm );
+#endif
+
+    if ( global_error ) {
+      throw std::runtime_error(std::string("Error generating finite element fixture"));
+    }
+  }
+
+  //------------------------------------
+
+  const ImportType comm_nodal_import(
+    comm ,
+    fixture.recv_node() ,
+    fixture.send_node() ,
+    fixture.send_nodeid() ,
+    fixture.node_count_owned() ,
+    fixture.node_count() - fixture.node_count_owned() );
+
+  //------------------------------------
+
+  const double bc_lower_value = 1 ;
+  const double bc_upper_value = 2 ;
+
+  const Kokkos::Example::FENL::ManufacturedSolution
+    manufactured_solution( 0 , 1 , bc_lower_value , bc_upper_value  );
+
+  //------------------------------------
+
+  for ( int k = 0 ; k < comm_size && use_print ; ++k ) {
+    if ( k == comm_rank ) {
+      typename FixtureType::node_grid_type::HostMirror
+        h_node_grid = Kokkos::create_mirror_view( fixture.node_grid() );
+
+      typename FixtureType::node_coord_type::HostMirror
+        h_node_coord = Kokkos::create_mirror_view( fixture.node_coord() );
+
+      typename FixtureType::elem_node_type::HostMirror
+        h_elem_node = Kokkos::create_mirror_view( fixture.elem_node() );
+
+      Kokkos::deep_copy( h_node_grid , fixture.node_grid() );
+      Kokkos::deep_copy( h_node_coord , fixture.node_coord() );
+      Kokkos::deep_copy( h_elem_node , fixture.elem_node() );
+
+      std::cout << "MPI[" << comm_rank << "]" << std::endl ;
+      std::cout << "Node grid {" ;
+      for ( unsigned inode = 0 ; inode < fixture.node_count() ; ++inode ) {
+        std::cout << " (" << h_node_grid(inode,0)
+                  << "," << h_node_grid(inode,1)
+                  << "," << h_node_grid(inode,2)
+                  << ")" ;
+      }
+      std::cout << " }" << std::endl ;
+  
+      std::cout << "Node coord {" ;
+      for ( unsigned inode = 0 ; inode < fixture.node_count() ; ++inode ) {
+        std::cout << " (" << h_node_coord(inode,0)
+                  << "," << h_node_coord(inode,1)
+                  << "," << h_node_coord(inode,2)
+                  << ")" ;
+      }
+      std::cout << " }" << std::endl ;
+
+      std::cout << "Manufactured solution"
+                << " a[" << manufactured_solution.a << "]"
+                << " b[" << manufactured_solution.b << "]"
+                << " K[" << manufactured_solution.K << "]"
+                << " {" ;
+      for ( unsigned inode = 0 ; inode < fixture.node_count() ; ++inode ) {
+        std::cout << " " << manufactured_solution( h_node_coord( inode , 2 ) );
+      }
+      std::cout << " }" << std::endl ;
+
+      std::cout << "ElemNode {" << std::endl ;
+      for ( unsigned ielem = 0 ; ielem < fixture.elem_count() ; ++ielem ) {
+        std::cout << "  elem[" << ielem << "]{" ;
+        for ( unsigned inode = 0 ; inode < FixtureType::ElemNode ; ++inode ) {
+          std::cout << " " << h_elem_node(ielem,inode);
+        }
+        std::cout << " }{" ;
+        for ( unsigned inode = 0 ; inode < FixtureType::ElemNode ; ++inode ) {
+          std::cout << " (" << h_node_grid(h_elem_node(ielem,inode),0)
+                    << "," << h_node_grid(h_elem_node(ielem,inode),1)
+                    << "," << h_node_grid(h_elem_node(ielem,inode),2)
+                    << ")" ;
+        }
+        std::cout << " }" << std::endl ;
+      }
+      std::cout << "}" << std::endl ;
+    }
+    std::cout.flush();
+    MPI_Barrier( comm );
+  }
+
+  //------------------------------------
+
+  Kokkos::Timer wall_clock ;
+
+  Perf perf_stats = Perf() ;
+
+  for ( int itrial = 0 ; itrial < use_trials ; ++itrial ) {
+
+    Perf perf = Perf() ;
+
+    perf.global_elem_count = fixture.elem_count_global();
+    perf.global_node_count = fixture.node_count_global();
+
+    //----------------------------------
+    // Create the sparse matrix graph and element-to-graph map
+    // from the element->to->node identifier array.
+    // The graph only has rows for the owned nodes.
+
+    typename NodeNodeGraphType::Times graph_times;
+
+    const NodeNodeGraphType
+      mesh_to_graph( fixture.elem_node() , fixture.node_count_owned(), graph_times );
+
+    perf.map_ratio          = maximum(comm, graph_times.ratio);
+    perf.fill_node_set      = maximum(comm, graph_times.fill_node_set);
+    perf.scan_node_count    = maximum(comm, graph_times.scan_node_count);
+    perf.fill_graph_entries = maximum(comm, graph_times.fill_graph_entries);
+    perf.sort_graph_entries = maximum(comm, graph_times.sort_graph_entries);
+    perf.fill_element_graph = maximum(comm, graph_times.fill_element_graph);
+
+    wall_clock.reset();
+    // Create the sparse matrix from the graph:
+
+    SparseMatrixType jacobian( mesh_to_graph.graph );
+
+    Space::fence();
+
+    perf.create_sparse_matrix = maximum( comm , wall_clock.seconds() );
+
+    //----------------------------------
+
+    for ( int k = 0 ; k < comm_size && print_flag ; ++k ) {
+      if ( k == comm_rank ) {
+        const unsigned nrow = jacobian.graph.numRows();
+        std::cout << "MPI[" << comm_rank << "]" << std::endl ;
+        std::cout << "JacobianGraph {" << std::endl ;
+        for ( unsigned irow = 0 ; irow < nrow ; ++irow ) {
+          std::cout << "  row[" << irow << "]{" ;
+          const unsigned entry_end = jacobian.graph.row_map(irow+1);
+          for ( unsigned entry = jacobian.graph.row_map(irow) ; entry < entry_end ; ++entry ) {
+            std::cout << " " << jacobian.graph.entries(entry);
+          }
+          std::cout << " }" << std::endl ;
+        }
+        std::cout << "}" << std::endl ;
+
+        std::cout << "ElemGraph {" << std::endl ;
+        for ( unsigned ielem = 0 ; ielem < mesh_to_graph.elem_graph.dimension_0() ; ++ielem ) {
+          std::cout << "  elem[" << ielem << "]{" ;
+          for ( unsigned irow = 0 ; irow < mesh_to_graph.elem_graph.dimension_1() ; ++irow ) {
+            std::cout << " {" ;
+            for ( unsigned icol = 0 ; icol < mesh_to_graph.elem_graph.dimension_2() ; ++icol ) {
+              std::cout << " " << mesh_to_graph.elem_graph(ielem,irow,icol);
+            }
+            std::cout << " }" ;
+          }
+          std::cout << " }" << std::endl ;
+        }
+        std::cout << "}" << std::endl ;
+      }
+      std::cout.flush();
+      MPI_Barrier( comm );
+    }
+
+    //----------------------------------
+
+    // Allocate solution vector for each node in the mesh and residual vector for each owned node
+    const VectorType nodal_solution( "nodal_solution" , fixture.node_count() );
+    const VectorType nodal_residual( "nodal_residual" , fixture.node_count_owned() );
+    const VectorType nodal_delta(    "nodal_delta" ,    fixture.node_count_owned() );
+
+    // Create element computation functor
+    const ElementComputationType elemcomp(
+      use_atomic ? ElementComputationType( fixture , manufactured_solution.K , nodal_solution ,
+                                           mesh_to_graph.elem_graph , jacobian , nodal_residual )
+                 : ElementComputationType( fixture , manufactured_solution.K , nodal_solution ) );
+
+    const NodeElemGatherFillType gatherfill(
+      use_atomic ? NodeElemGatherFillType()
+                 : NodeElemGatherFillType( fixture.elem_node() ,
+                                           mesh_to_graph.elem_graph ,
+                                           nodal_residual ,
+                                           jacobian ,
+                                           elemcomp.elem_residuals ,
+                                           elemcomp.elem_jacobians ) );
+
+    // Create boundary condition functor
+    const DirichletComputationType dirichlet(
+      fixture , nodal_solution , jacobian , nodal_residual ,
+      2 /* apply at 'z' ends */ ,
+      manufactured_solution.T_zmin ,
+      manufactured_solution.T_zmax );
+
+    //----------------------------------
+    // Nonlinear Newton iteration:
+
+    double residual_norm_init = 0 ;
+
+    for ( perf.newton_iter_count = 0 ;
+          perf.newton_iter_count < newton_iteration_limit ;
+          ++perf.newton_iter_count ) {
+
+      //--------------------------------
+
+      comm_nodal_import( nodal_solution );
+
+      //--------------------------------
+      // Element contributions to residual and jacobian
+
+      wall_clock.reset();
+
+      Kokkos::deep_copy( nodal_residual , double(0) );
+      Kokkos::deep_copy( jacobian.coeff , double(0) );
+
+      elemcomp.apply();
+
+      if ( ! use_atomic ) {
+        gatherfill.apply();
+      }
+
+      Space::fence();
+      perf.fill_time = maximum( comm , wall_clock.seconds() );
+
+      //--------------------------------
+      // Apply boundary conditions
+
+      wall_clock.reset();
+
+      dirichlet.apply();
+
+      Space::fence();
+      perf.bc_time = maximum( comm , wall_clock.seconds() );
+
+      //--------------------------------
+      // Evaluate convergence
+
+      const double residual_norm =
+        std::sqrt(
+          Kokkos::Example::all_reduce(
+            Kokkos::Example::dot( fixture.node_count_owned() , nodal_residual, nodal_residual ) , comm ) );
+
+      perf.newton_residual = residual_norm ;
+
+      if ( 0 == perf.newton_iter_count ) { residual_norm_init = residual_norm ; }
+
+      if ( residual_norm < residual_norm_init * newton_iteration_tolerance ) { break ; }
+
+      //--------------------------------
+      // Solve for nonlinear update
+
+      CGSolveResult cg_result ;
+
+      Kokkos::Example::cgsolve( comm_nodal_import
+                              , jacobian
+                              , nodal_residual
+                              , nodal_delta
+                              , cg_iteration_limit
+                              , cg_iteration_tolerance
+                              , & cg_result
+                              );
+
+      // Update solution vector
+
+      Kokkos::Example::waxpby( fixture.node_count_owned() , nodal_solution , -1.0 , nodal_delta , 1.0 , nodal_solution );
+
+      perf.cg_iter_count += cg_result.iteration ;
+      perf.matvec_time   += cg_result.matvec_time ;
+      perf.cg_time       += cg_result.iter_time ;
+
+      //--------------------------------
+
+      if ( print_flag ) {
+        const double delta_norm =
+          std::sqrt(
+            Kokkos::Example::all_reduce(
+              Kokkos::Example::dot( fixture.node_count_owned() , nodal_delta, nodal_delta ) , comm ) );
+
+        if ( 0 == comm_rank ) {
+          std::cout << "Newton iteration[" << perf.newton_iter_count << "]"
+                    << " residual[" << perf.newton_residual << "]"
+                    << " update[" << delta_norm << "]"
+                    << " cg_iteration[" << cg_result.iteration << "]"
+                    << " cg_residual[" << cg_result.norm_res << "]"
+                    << std::endl ;
+        }
+
+        for ( int k = 0 ; k < comm_size ; ++k ) {
+          if ( k == comm_rank ) {
+            const unsigned nrow = jacobian.graph.numRows();
+
+            std::cout << "MPI[" << comm_rank << "]" << std::endl ;
+            std::cout << "Residual {" ;
+            for ( unsigned irow = 0 ; irow < nrow ; ++irow ) {
+              std::cout << " " << nodal_residual(irow);
+            }
+            std::cout << " }" << std::endl ;
+
+            std::cout << "Delta {" ;
+            for ( unsigned irow = 0 ; irow < nrow ; ++irow ) {
+              std::cout << " " << nodal_delta(irow);
+            }
+            std::cout << " }" << std::endl ;
+
+            std::cout << "Solution {" ;
+            for ( unsigned irow = 0 ; irow < nrow ; ++irow ) {
+              std::cout << " " << nodal_solution(irow);
+            }
+            std::cout << " }" << std::endl ;
+
+            std::cout << "Jacobian[ "
+                      << jacobian.graph.numRows() << " x " << Kokkos::maximum_entry( jacobian.graph )
+                      << " ] {" << std::endl ;
+            for ( unsigned irow = 0 ; irow < nrow ; ++irow ) {
+              std::cout << "  {" ;
+              const unsigned entry_end = jacobian.graph.row_map(irow+1);
+              for ( unsigned entry = jacobian.graph.row_map(irow) ; entry < entry_end ; ++entry ) {
+                std::cout << " (" << jacobian.graph.entries(entry)
+                          << "," << jacobian.coeff(entry)
+                          << ")" ;
+              }
+              std::cout << " }" << std::endl ;
+            }
+            std::cout << "}" << std::endl ;
+          }
+          std::cout.flush();
+          MPI_Barrier( comm );
+        }
+      }
+      //--------------------------------
+    }
+
+    // Evaluate solution error
+
+    if ( 0 == itrial ) {
+      const typename FixtureType::node_coord_type::HostMirror
+        h_node_coord = Kokkos::create_mirror_view( fixture.node_coord() );
+
+      const typename VectorType::HostMirror
+        h_nodal_solution = Kokkos::create_mirror_view( nodal_solution );
+
+      Kokkos::deep_copy( h_node_coord , fixture.node_coord() );
+      Kokkos::deep_copy( h_nodal_solution , nodal_solution );
+
+      double error_max = 0 ;
+      for ( unsigned inode = 0 ; inode < fixture.node_count_owned() ; ++inode ) {
+        const double answer = manufactured_solution( h_node_coord( inode , 2 ) );
+        const double error = ( h_nodal_solution(inode) - answer ) / answer ;
+        if ( error_max < fabs( error ) ) { error_max = fabs( error ); }
+      }
+
+      perf.error_max = std::sqrt( Kokkos::Example::all_reduce_max( error_max , comm ) );
+
+      perf_stats = perf ;
+    }
+    else {
+      perf_stats.fill_node_set = std::min( perf_stats.fill_node_set , perf.fill_node_set );
+      perf_stats.scan_node_count = std::min( perf_stats.scan_node_count , perf.scan_node_count );
+      perf_stats.fill_graph_entries = std::min( perf_stats.fill_graph_entries , perf.fill_graph_entries );
+      perf_stats.sort_graph_entries = std::min( perf_stats.sort_graph_entries , perf.sort_graph_entries );
+      perf_stats.fill_element_graph = std::min( perf_stats.fill_element_graph , perf.fill_element_graph );
+      perf_stats.create_sparse_matrix = std::min( perf_stats.create_sparse_matrix , perf.create_sparse_matrix );
+      perf_stats.fill_time = std::min( perf_stats.fill_time , perf.fill_time );
+      perf_stats.bc_time = std::min( perf_stats.bc_time , perf.bc_time );
+      perf_stats.cg_time = std::min( perf_stats.cg_time , perf.cg_time );
+    }
+  }
+
+  return perf_stats ;
+}
+
+} /* namespace FENL */
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_EXAMPLE_FENL_IMPL_HPP */
+
diff --git a/lib/kokkos/example/fenl/main.cpp b/lib/kokkos/example/fenl/main.cpp
new file mode 100644
index 0000000000..06005d97cb
--- /dev/null
+++ b/lib/kokkos/example/fenl/main.cpp
@@ -0,0 +1,422 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+
+#include <utility>
+#include <string>
+#include <vector>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include <Kokkos_Core.hpp>
+
+#include <WrapMPI.hpp>
+#include <fenl.hpp>
+
+// For vtune
+#include <sys/types.h>
+#include <unistd.h>
+
+//----------------------------------------------------------------------------
+
+enum { CMD_USE_THREADS = 0
+     , CMD_USE_NUMA
+     , CMD_USE_CORE_PER_NUMA
+     , CMD_USE_CUDA
+     , CMD_USE_OPENMP
+     , CMD_USE_CUDA_DEV
+     , CMD_USE_FIXTURE_X
+     , CMD_USE_FIXTURE_Y
+     , CMD_USE_FIXTURE_Z
+     , CMD_USE_FIXTURE_BEGIN
+     , CMD_USE_FIXTURE_END
+     , CMD_USE_FIXTURE_QUADRATIC
+     , CMD_USE_ATOMIC
+     , CMD_USE_TRIALS
+     , CMD_VTUNE
+     , CMD_PRINT
+     , CMD_ECHO
+     , CMD_ERROR
+     , CMD_COUNT };
+
+void print_cmdline( std::ostream & s , const int cmd[] )
+{
+  if ( cmd[ CMD_USE_THREADS ] ) {
+    s << " Threads(" << cmd[ CMD_USE_THREADS ]
+      << ") NUMA(" << cmd[ CMD_USE_NUMA ]
+      << ") CORE_PER_NUMA(" << cmd[ CMD_USE_CORE_PER_NUMA ]
+      << ")" ;
+  }
+  if ( cmd[ CMD_USE_OPENMP ] ) {
+    s << " OpenMP(" << cmd[ CMD_USE_OPENMP ]
+      << ") NUMA(" << cmd[ CMD_USE_NUMA ]
+      << ") CORE_PER_NUMA(" << cmd[ CMD_USE_CORE_PER_NUMA ]
+      << ")" ;
+  }
+  if ( cmd[ CMD_USE_FIXTURE_X ] ) {
+    s << " Fixture(" << cmd[ CMD_USE_FIXTURE_X ]
+      << "x" << cmd[ CMD_USE_FIXTURE_Y ]
+      << "x" << cmd[ CMD_USE_FIXTURE_Z ]
+      << ")" ;
+  }
+  if ( cmd[ CMD_USE_FIXTURE_BEGIN ] ) {
+    s << " Fixture( " << cmd[ CMD_USE_FIXTURE_BEGIN ]
+      << " .. " << cmd[ CMD_USE_FIXTURE_END ]
+      << " )" ;
+  }
+  if ( cmd[ CMD_USE_FIXTURE_QUADRATIC ] ) {
+    s << " Quadratic-Element" ;
+  }
+  if ( cmd[ CMD_USE_CUDA ] ) {
+    s << " CUDA(" << cmd[ CMD_USE_CUDA_DEV ] << ")" ;
+  }
+  if ( cmd[ CMD_USE_ATOMIC ] ) {
+    s << " ATOMIC" ;
+  }
+  if ( cmd[ CMD_USE_TRIALS ] ) {
+    s << " TRIALS(" << cmd[ CMD_USE_TRIALS ] << ")" ;
+  }
+  if ( cmd[ CMD_VTUNE ] ) {
+    s << " VTUNE" ;
+  }
+  if ( cmd[ CMD_PRINT ] ) {
+    s << " PRINT" ;
+  }
+  s << std::endl ;
+}
+
+void print_perf_value( std::ostream & s , const std::vector<size_t> & widths,  const Kokkos::Example::FENL::Perf & perf )
+{
+  int i=0;
+  s << std::setw(widths[i++]) << perf.global_elem_count << " ,";
+  s << std::setw(widths[i++]) << perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << perf.newton_iter_count << " ,";
+  s << std::setw(widths[i++]) << perf.cg_iter_count << " ,";
+  s << std::setw(widths[i++]) << perf.map_ratio << " ,";
+  s << std::setw(widths[i++]) << ( perf.fill_node_set * 1000.0 ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( perf.scan_node_count * 1000.0 ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( perf.fill_graph_entries * 1000.0 ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( perf.sort_graph_entries * 1000.0 ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( perf.fill_element_graph * 1000.0 ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( perf.create_sparse_matrix * 1000.0 ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( perf.fill_time * 1000.0 ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( perf.bc_time * 1000.0 ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( ( perf.matvec_time * 1000.0 ) / perf.cg_iter_count ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i++]) << ( ( perf.cg_time * 1000.0 ) / perf.cg_iter_count ) / perf.global_node_count << " ,";
+  s << std::setw(widths[i])   << perf.error_max;
+  s << std::endl ;
+}
+
+template< class Device , Kokkos::Example::BoxElemPart::ElemOrder ElemOrder >
+void run( MPI_Comm comm , const int cmd[] )
+{
+  int comm_rank = 0 ;
+
+#if defined( KOKKOS_HAVE_MPI )
+  MPI_Comm_rank( comm , & comm_rank );
+#else
+  comm = 0 ;
+#endif
+
+
+  if ( 0 == comm_rank ) {
+    if ( cmd[ CMD_USE_THREADS ] ) { std::cout << "THREADS , " << cmd[ CMD_USE_THREADS ] ; }
+    else if ( cmd[ CMD_USE_OPENMP ] ) { std::cout << "OPENMP , " << cmd[ CMD_USE_OPENMP ] ; }
+    else if ( cmd[ CMD_USE_CUDA ] ) { std::cout << "CUDA" ; }
+
+    if ( cmd[ CMD_USE_FIXTURE_QUADRATIC ] ) { std::cout << " , QUADRATIC-ELEMENT" ; }
+    else { std::cout << " , LINEAR-ELEMENT" ; }
+
+    if ( cmd[ CMD_USE_ATOMIC ] ) { std::cout << " , USING ATOMICS" ; }
+  }
+
+  std::vector< std::pair<std::string,std::string> > headers;
+
+
+  headers.push_back(std::make_pair("ELEMS","count"));
+  headers.push_back(std::make_pair("NODES","count"));
+  headers.push_back(std::make_pair("NEWTON","iter"));
+  headers.push_back(std::make_pair("CG","iter"));
+  headers.push_back(std::make_pair("MAP_RATIO","ratio"));
+  headers.push_back(std::make_pair("SET_FILL/NODE","millisec"));
+  headers.push_back(std::make_pair("SCAN/NODE","millisec"));
+  headers.push_back(std::make_pair("GRAPH_FILL/NODE","millisec"));
+  headers.push_back(std::make_pair("SORT/NODE","millisec"));
+  headers.push_back(std::make_pair("ELEM_GRAPH_FILL/NODE","millisec"));
+  headers.push_back(std::make_pair("MATRIX_CREATE/NODE","millisec"));
+  headers.push_back(std::make_pair("MATRIX_FILL/NODE","millisec"));
+  headers.push_back(std::make_pair("BOUNDARY/NODE","millisec"));
+  headers.push_back(std::make_pair("MAT_VEC/ITER/ROW","millisec"));
+  headers.push_back(std::make_pair("CG/ITER/ROW","millisec"));
+  headers.push_back(std::make_pair("ERROR","ratio"));
+
+  // find print widths
+  size_t min_width = 10;
+  std::vector< size_t > widths(headers.size());
+  for (size_t i=0, ie=headers.size(); i<ie; ++i)
+    widths[i] = std::max(min_width, headers[i].first.size()+1);
+
+  // print column headers
+  if ( 0 == comm_rank ) {
+    std::cout << std::endl ;
+    for (size_t i=0; i<headers.size(); ++i)
+      std::cout << std::setw(widths[i]) << headers[i].first << " ,";
+    std::cout << "\b\b  " << std::endl;
+    for (size_t i=0; i<headers.size(); ++i)
+      std::cout << std::setw(widths[i]) << headers[i].second << " ,";
+    std::cout << "\b\b  " << std::endl;
+
+    std::cout << std::scientific;
+    std::cout.precision(3);
+  }
+
+  if ( cmd[ CMD_USE_FIXTURE_BEGIN ] ) {
+    for ( int i = cmd[CMD_USE_FIXTURE_BEGIN] ; i < cmd[CMD_USE_FIXTURE_END] * 2 ; i *= 2 ) {
+      int nelem[3] ;
+      nelem[0] = std::max( 1 , (int) cbrt( ((double) i) / 2.0 ) );
+      nelem[1] = 1 + nelem[0] ;
+      nelem[2] = 2 * nelem[0] ;
+
+      const Kokkos::Example::FENL::Perf perf =
+        cmd[ CMD_USE_FIXTURE_QUADRATIC ]
+        ? Kokkos::Example::FENL::fenl< Device , Kokkos::Example::BoxElemPart::ElemQuadratic >
+            ( comm , cmd[CMD_PRINT], cmd[CMD_USE_TRIALS], cmd[CMD_USE_ATOMIC], nelem )
+        : Kokkos::Example::FENL::fenl< Device , Kokkos::Example::BoxElemPart::ElemLinear >
+            ( comm , cmd[CMD_PRINT], cmd[CMD_USE_TRIALS], cmd[CMD_USE_ATOMIC], nelem )
+        ;
+
+      if ( 0 == comm_rank ) print_perf_value( std::cout , widths, perf );
+    }
+  }
+  else {
+    int nelem[3] = { cmd[ CMD_USE_FIXTURE_X ] ,
+                     cmd[ CMD_USE_FIXTURE_Y ] ,
+                     cmd[ CMD_USE_FIXTURE_Z ] };
+
+    const Kokkos::Example::FENL::Perf perf =
+      cmd[ CMD_USE_FIXTURE_QUADRATIC ]
+      ? Kokkos::Example::FENL::fenl< Device , Kokkos::Example::BoxElemPart::ElemQuadratic >
+          ( comm , cmd[CMD_PRINT], cmd[CMD_USE_TRIALS], cmd[CMD_USE_ATOMIC], nelem )
+      : Kokkos::Example::FENL::fenl< Device , Kokkos::Example::BoxElemPart::ElemLinear >
+          ( comm , cmd[CMD_PRINT], cmd[CMD_USE_TRIALS], cmd[CMD_USE_ATOMIC], nelem )
+      ;
+
+    if ( 0 == comm_rank ) print_perf_value( std::cout , widths, perf );
+  }
+}
+
+//----------------------------------------------------------------------------
+
+int main( int argc , char ** argv )
+{
+  int comm_rank = 0 ;
+
+#if defined( KOKKOS_HAVE_MPI )
+  MPI_Init( & argc , & argv );
+  MPI_Comm comm = MPI_COMM_WORLD ;
+  MPI_Comm_rank( comm , & comm_rank );
+#else
+  MPI_Comm comm = 0 ;
+  (void) comm ; // suppress warning
+#endif
+
+  int cmdline[ CMD_COUNT ] ;
+
+  for ( int i = 0 ; i < CMD_COUNT ; ++i ) cmdline[i] = 0 ;
+
+  if ( 0 == comm_rank ) {
+    for ( int i = 1 ; i < argc ; ++i ) {
+      if ( 0 == strcasecmp( argv[i] , "threads" ) ) {
+        cmdline[ CMD_USE_THREADS ] = atoi( argv[++i] );
+      }
+      else if ( 0 == strcasecmp( argv[i] , "openmp" ) ) {
+        cmdline[ CMD_USE_OPENMP ] = atoi( argv[++i] );
+      }
+      else if ( 0 == strcasecmp( argv[i] , "cores" ) ) {
+        sscanf( argv[++i] , "%dx%d" ,
+                cmdline + CMD_USE_NUMA ,
+                cmdline + CMD_USE_CORE_PER_NUMA );
+      }
+      else if ( 0 == strcasecmp( argv[i] , "cuda" ) ) {
+        cmdline[ CMD_USE_CUDA ] = 1 ;
+      }
+      else if ( 0 == strcasecmp( argv[i] , "cuda-dev" ) ) {
+        cmdline[ CMD_USE_CUDA ] = 1 ;
+        cmdline[ CMD_USE_CUDA_DEV ] = atoi( argv[++i] ) ;
+      }
+      else if ( 0 == strcasecmp( argv[i] , "fixture" ) ) {
+        sscanf( argv[++i] , "%dx%dx%d" ,
+                cmdline + CMD_USE_FIXTURE_X ,
+                cmdline + CMD_USE_FIXTURE_Y ,
+                cmdline + CMD_USE_FIXTURE_Z );
+      }
+      else if ( 0 == strcasecmp( argv[i] , "fixture-range" ) ) {
+        sscanf( argv[++i] , "%d..%d" ,
+                cmdline + CMD_USE_FIXTURE_BEGIN ,
+                cmdline + CMD_USE_FIXTURE_END );
+      }
+      else if ( 0 == strcasecmp( argv[i] , "fixture-quadratic" ) ) {
+        cmdline[ CMD_USE_FIXTURE_QUADRATIC ] = 1 ;
+      }
+      else if ( 0 == strcasecmp( argv[i] , "atomic" ) ) {
+        cmdline[ CMD_USE_ATOMIC ] = 1 ;
+      }
+      else if ( 0 == strcasecmp( argv[i] , "trials" ) ) {
+        cmdline[ CMD_USE_TRIALS ] = atoi( argv[++i] ) ;
+      }
+      else if ( 0 == strcasecmp( argv[i] , "vtune" ) ) {
+        cmdline[ CMD_VTUNE ] = 1 ;
+      }
+      else if ( 0 == strcasecmp( argv[i] , "print" ) ) {
+        cmdline[ CMD_PRINT ] = 1 ;
+      }
+      else if ( 0 == strcasecmp( argv[i] , "echo" ) ) {
+        cmdline[ CMD_ECHO ] = 1 ;
+      }
+      else {
+        cmdline[ CMD_ERROR ] = 1 ;
+
+        std::cerr << "Unrecognized command line argument #" << i << ": " << argv[i] << std::endl ;
+      }
+    }
+
+    if ( cmdline[ CMD_ECHO ] && 0 == comm_rank ) { print_cmdline( std::cout , cmdline ); }
+  }
+
+#if defined( KOKKOS_HAVE_MPI )
+  MPI_Bcast( cmdline , CMD_COUNT , MPI_INT , 0 , comm );
+#endif
+
+  if ( cmdline[ CMD_VTUNE ] ) {
+    std::stringstream cmd;
+    pid_t my_os_pid=getpid();
+    const std::string vtune_loc =
+      "/usr/local/intel/vtune_amplifier_xe_2013/bin64/amplxe-cl";
+    const std::string output_dir = "./vtune/vtune.";
+    const int p_rank = comm_rank;
+    cmd << vtune_loc
+        << " -collect hotspots -result-dir " << output_dir << p_rank
+        << " -target-pid " << my_os_pid << " &";
+    if (p_rank == 0)
+      std::cout << cmd.str() << std::endl;
+    system(cmd.str().c_str());
+    system("sleep 10");
+  }
+
+  if ( ! cmdline[ CMD_ERROR ] && ! cmdline[ CMD_ECHO ] ) {
+
+    if ( ! cmdline[ CMD_USE_TRIALS ] ) { cmdline[ CMD_USE_TRIALS ] = 1 ; }
+
+    if ( ! cmdline[ CMD_USE_FIXTURE_X ] && ! cmdline[ CMD_USE_FIXTURE_BEGIN ] ) {
+      cmdline[ CMD_USE_FIXTURE_X ] = 2 ;
+      cmdline[ CMD_USE_FIXTURE_Y ] = 2 ;
+      cmdline[ CMD_USE_FIXTURE_Z ] = 2 ;
+    }
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+
+    if ( cmdline[ CMD_USE_THREADS ] ) {
+
+      if ( cmdline[ CMD_USE_NUMA ] && cmdline[ CMD_USE_CORE_PER_NUMA ] ) {
+        Kokkos::Threads::initialize( cmdline[ CMD_USE_THREADS ] ,
+                                     cmdline[ CMD_USE_NUMA ] ,
+                                     cmdline[ CMD_USE_CORE_PER_NUMA ] );
+      }
+      else {
+        Kokkos::Threads::initialize( cmdline[ CMD_USE_THREADS ] );
+      }
+
+      run< Kokkos::Threads , Kokkos::Example::BoxElemPart::ElemLinear >( comm , cmdline );
+
+      Kokkos::Threads::finalize();
+    }
+
+#endif
+
+#if defined( KOKKOS_HAVE_OPENMP )
+
+    if ( cmdline[ CMD_USE_OPENMP ] ) {
+
+      if ( cmdline[ CMD_USE_NUMA ] && cmdline[ CMD_USE_CORE_PER_NUMA ] ) {
+        Kokkos::OpenMP::initialize( cmdline[ CMD_USE_OPENMP ] ,
+                                     cmdline[ CMD_USE_NUMA ] ,
+                                     cmdline[ CMD_USE_CORE_PER_NUMA ] );
+      }
+      else {
+        Kokkos::OpenMP::initialize( cmdline[ CMD_USE_OPENMP ] );
+      }
+
+      run< Kokkos::OpenMP , Kokkos::Example::BoxElemPart::ElemLinear >( comm , cmdline );
+
+      Kokkos::OpenMP::finalize();
+    }
+
+#endif
+
+#if defined( KOKKOS_HAVE_CUDA )
+    if ( cmdline[ CMD_USE_CUDA ] ) {
+      // Use the last device:
+
+      Kokkos::HostSpace::execution_space::initialize();
+      Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice( cmdline[ CMD_USE_CUDA_DEV ] ) );
+
+      run< Kokkos::Cuda , Kokkos::Example::BoxElemPart::ElemLinear >( comm , cmdline );
+
+      Kokkos::Cuda::finalize();
+      Kokkos::HostSpace::execution_space::finalize();
+    }
+
+#endif
+
+  }
+
+#if defined( KOKKOS_HAVE_MPI )
+  MPI_Finalize();
+#endif
+
+  return cmdline[ CMD_ERROR ] ? -1 : 0 ;
+}
+
diff --git a/lib/kokkos/example/fixture/BoxElemFixture.hpp b/lib/kokkos/example/fixture/BoxElemFixture.hpp
new file mode 100644
index 0000000000..66d6e741af
--- /dev/null
+++ b/lib/kokkos/example/fixture/BoxElemFixture.hpp
@@ -0,0 +1,355 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_BOXELEMFIXTURE_HPP
+#define KOKKOS_EXAMPLE_BOXELEMFIXTURE_HPP
+
+#include <stdio.h>
+#include <utility>
+
+#include <Kokkos_Core.hpp>
+
+#include <HexElement.hpp>
+#include <BoxElemPart.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+/** \brief  Map a grid onto a unit cube with smooth nonlinear grading
+ *          of the map.
+ */
+struct MapGridUnitCube {
+
+  const float m_a ;
+  const float m_b ;
+  const float m_c ;
+  const size_t m_max_x ;
+  const size_t m_max_y ;
+  const size_t m_max_z ;
+
+  MapGridUnitCube( const size_t grid_max_x ,
+                   const size_t grid_max_y ,
+                   const size_t grid_max_z ,
+                   const float bubble_x ,
+                   const float bubble_y ,
+                   const float bubble_z )
+    : m_a( bubble_x )
+    , m_b( bubble_y )
+    , m_c( bubble_z )
+    , m_max_x( grid_max_x )
+    , m_max_y( grid_max_y )
+    , m_max_z( grid_max_z )
+    {}
+
+  template< typename Scalar >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int grid_x ,
+                   int grid_y ,
+                   int grid_z ,
+                   Scalar & coord_x ,
+                   Scalar & coord_y ,
+                   Scalar & coord_z ) const
+    {
+      // Map to a unit cube [0,1]^3
+
+      const double x = double(grid_x) / double(m_max_x);
+      const double y = double(grid_y) / double(m_max_y);
+      const double z = double(grid_z) / double(m_max_z);
+    
+      coord_x = x + x * x * ( x - 1 ) * ( x - 1 ) * m_a ;
+      coord_y = y + y * y * ( y - 1 ) * ( y - 1 ) * m_b ;
+      coord_z = z + z * z * ( z - 1 ) * ( z - 1 ) * m_c ;
+    }
+};
+
+} // namespace Example
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+/** \brief  Generate a distributed unstructured finite element mesh
+ *          from a partitioned NX*NY*NZ box of elements.
+ *
+ *  Order owned nodes first followed by off-process nodes
+ *  grouped by owning process.
+ */
+template< class Device ,
+          BoxElemPart::ElemOrder Order ,
+          class CoordinateMap = MapGridUnitCube >
+class BoxElemFixture {
+public:
+
+  typedef Device execution_space ;
+
+  enum { SpaceDim = 3 };
+  enum { ElemNode = Order == BoxElemPart::ElemLinear ? 8 :
+                    Order == BoxElemPart::ElemQuadratic ? 27 : 0 };
+
+private:
+
+  typedef Kokkos::Example::HexElement_TensorData< ElemNode > hex_data ;
+
+  Kokkos::Example::BoxElemPart m_box_part ;
+  CoordinateMap                m_coord_map ;
+
+  Kokkos::View< double *[SpaceDim] , Device > m_node_coord ;
+  Kokkos::View< size_t *[SpaceDim] , Device > m_node_grid ;
+  Kokkos::View< size_t *[ElemNode] , Device > m_elem_node ;
+  Kokkos::View< size_t *[2] ,        Device > m_recv_node ;
+  Kokkos::View< size_t *[2] ,        Device > m_send_node ;
+  Kokkos::View< size_t * ,           Device > m_send_node_id ;
+
+  unsigned char m_elem_node_local[ ElemNode ][4] ;
+
+public:
+
+  typedef Kokkos::View< const size_t  * [ElemNode], Device > elem_node_type ;
+  typedef Kokkos::View< const double  * [SpaceDim], Device > node_coord_type ;
+  typedef Kokkos::View< const size_t  * [SpaceDim], Device > node_grid_type ;
+  typedef Kokkos::View< const size_t  * [2] , Device > comm_list_type ;
+  typedef Kokkos::View< const size_t  *     , Device > send_nodeid_type ;
+
+  inline bool ok() const { return m_box_part.ok(); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t node_count() const { return m_node_grid.dimension_0(); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t node_count_owned() const { return m_box_part.owns_node_count(); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t node_count_global() const { return m_box_part.global_node_count(); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t elem_count() const { return m_elem_node.dimension_0(); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t elem_count_global() const { return m_box_part.global_elem_count(); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t elem_node_local( size_t inode , int k ) const
+    { return m_elem_node_local[inode][k] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t node_grid( size_t inode , int iaxis ) const
+    { return m_node_grid(inode,iaxis); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t node_global_index( size_t local ) const
+    {
+      const size_t tmp_node_grid[SpaceDim] =
+        { m_node_grid(local,0) , m_node_grid(local,1) , m_node_grid(local,2) };
+      return m_box_part.global_node_id( tmp_node_grid );
+    }
+
+  KOKKOS_INLINE_FUNCTION
+  double node_coord( size_t inode , int iaxis ) const
+    { return m_node_coord(inode,iaxis); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t node_grid_max( int iaxis ) const
+    { return m_box_part.global_coord_max(iaxis); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t elem_node( size_t ielem , size_t inode ) const
+    { return m_elem_node(ielem,inode); }
+
+  elem_node_type   elem_node()   const { return m_elem_node ; }
+  node_coord_type  node_coord()  const { return m_node_coord ; }
+  node_grid_type   node_grid()   const { return m_node_grid ; }
+  comm_list_type   recv_node()   const { return m_recv_node ; }
+  comm_list_type   send_node()   const { return m_send_node ; }
+  send_nodeid_type send_nodeid() const { return m_send_node_id ; }
+
+  KOKKOS_INLINE_FUNCTION
+  BoxElemFixture( const BoxElemFixture & rhs )
+    : m_box_part(   rhs.m_box_part )
+    , m_coord_map(  rhs.m_coord_map )
+    , m_node_coord( rhs.m_node_coord )
+    , m_node_grid(  rhs.m_node_grid )
+    , m_elem_node(  rhs.m_elem_node )
+    , m_recv_node(  rhs.m_recv_node )
+    , m_send_node(  rhs.m_send_node )
+    , m_send_node_id( rhs.m_send_node_id )
+    {
+      for ( int i = 0 ; i < ElemNode ; ++i ) {
+        m_elem_node_local[i][0] = rhs.m_elem_node_local[i][0] ;
+        m_elem_node_local[i][1] = rhs.m_elem_node_local[i][1] ;
+        m_elem_node_local[i][2] = rhs.m_elem_node_local[i][2] ;
+        m_elem_node_local[i][3] = 0 ;
+      }
+    }
+
+  BoxElemFixture & operator = ( const BoxElemFixture & rhs )
+    {
+      m_box_part      = rhs.m_box_part ;
+      m_coord_map     = rhs.m_coord_map ;
+      m_node_coord    = rhs.m_node_coord ;
+      m_node_grid     = rhs.m_node_grid ;
+      m_elem_node     = rhs.m_elem_node ;
+      m_recv_node     = rhs.m_recv_node ;
+      m_send_node     = rhs.m_send_node ;
+      m_send_node_id  = rhs.m_send_node_id ;
+     
+      for ( int i = 0 ; i < ElemNode ; ++i ) {
+        m_elem_node_local[i][0] = rhs.m_elem_node_local[i][0] ;
+        m_elem_node_local[i][1] = rhs.m_elem_node_local[i][1] ;
+        m_elem_node_local[i][2] = rhs.m_elem_node_local[i][2] ;
+        m_elem_node_local[i][3] = 0 ;
+      }
+      return *this ;
+    }
+
+  BoxElemFixture( const BoxElemPart::Decompose decompose ,
+                  const size_t global_size ,
+                  const size_t global_rank ,
+                  const size_t elem_nx ,
+                  const size_t elem_ny ,
+                  const size_t elem_nz ,
+                  const float bubble_x = 1.1f ,
+                  const float bubble_y = 1.2f ,
+                  const float bubble_z = 1.3f )
+  : m_box_part( Order , decompose , global_size , global_rank , elem_nx , elem_ny , elem_nz )
+  , m_coord_map( m_box_part.global_coord_max(0) ,
+                 m_box_part.global_coord_max(1) ,
+                 m_box_part.global_coord_max(2) ,
+                 bubble_x ,
+                 bubble_y ,
+                 bubble_z )
+  , m_node_coord( "fixture_node_coord" , m_box_part.uses_node_count() )
+  , m_node_grid(  "fixture_node_grid" , m_box_part.uses_node_count() )
+  , m_elem_node(  "fixture_elem_node" , m_box_part.uses_elem_count() )
+  , m_recv_node(  "fixture_recv_node" , m_box_part.recv_node_msg_count() )
+  , m_send_node(  "fixture_send_node" , m_box_part.send_node_msg_count() )
+  , m_send_node_id( "fixture_send_node_id" , m_box_part.send_node_id_count() )
+  {
+    {
+      const hex_data elem_data ;
+
+      for ( int i = 0 ; i < ElemNode ; ++i ) {
+        m_elem_node_local[i][0] = elem_data.eval_map[i][0] ;
+        m_elem_node_local[i][1] = elem_data.eval_map[i][1] ;
+        m_elem_node_local[i][2] = elem_data.eval_map[i][2] ;
+        m_elem_node_local[i][3] = 0 ;
+      }
+    }
+
+    const size_t nwork = 
+      std::max( m_recv_node.dimension_0() ,
+      std::max( m_send_node.dimension_0() ,
+      std::max( m_send_node_id.dimension_0() ,
+      std::max( m_node_grid.dimension_0() ,
+                m_elem_node.dimension_0() * m_elem_node.dimension_1() ))));
+
+    Kokkos::parallel_for( nwork , *this );
+  }
+
+
+  // Initialization:
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_t i ) const
+  {
+    if ( i < m_elem_node.dimension_0() * m_elem_node.dimension_1() ) {
+
+      const size_t ielem = i / ElemNode ;
+      const size_t inode = i % ElemNode ;
+
+      size_t elem_grid[SpaceDim] ;
+      size_t tmp_node_grid[SpaceDim] ;
+
+      m_box_part.uses_elem_coord( ielem , elem_grid );
+
+      enum { elem_node_scale = Order == BoxElemPart::ElemLinear ? 1 :
+                               Order == BoxElemPart::ElemQuadratic ? 2 : 0 };
+
+      tmp_node_grid[0] = elem_node_scale * elem_grid[0] + m_elem_node_local[inode][0] ;
+      tmp_node_grid[1] = elem_node_scale * elem_grid[1] + m_elem_node_local[inode][1] ;
+      tmp_node_grid[2] = elem_node_scale * elem_grid[2] + m_elem_node_local[inode][2] ;
+
+      m_elem_node(ielem,inode) = m_box_part.local_node_id( tmp_node_grid );
+    }
+
+    if ( i < m_node_grid.dimension_0() ) {
+      size_t tmp_node_grid[SpaceDim] ;
+      m_box_part.local_node_coord( i , tmp_node_grid );
+      m_node_grid(i,0) = tmp_node_grid[0] ;
+      m_node_grid(i,1) = tmp_node_grid[1] ;
+      m_node_grid(i,2) = tmp_node_grid[2] ;
+
+      m_coord_map( tmp_node_grid[0] ,
+                   tmp_node_grid[1] ,
+                   tmp_node_grid[2] ,
+                   m_node_coord(i,0) ,
+                   m_node_coord(i,1) ,
+                   m_node_coord(i,2) );
+    }
+
+    if ( i < m_recv_node.dimension_0() ) {
+      m_recv_node(i,0) = m_box_part.recv_node_rank(i);
+      m_recv_node(i,1) = m_box_part.recv_node_count(i);
+    }
+
+    if ( i < m_send_node.dimension_0() ) {
+      m_send_node(i,0) = m_box_part.send_node_rank(i);
+      m_send_node(i,1) = m_box_part.send_node_count(i);
+    }
+
+    if ( i < m_send_node_id.dimension_0() ) {
+      m_send_node_id(i) = m_box_part.send_node_id(i);
+    }
+  }
+};
+
+} // namespace Example
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_EXAMPLE_BOXELEMFIXTURE_HPP */
+
diff --git a/lib/kokkos/example/fixture/BoxElemPart.cpp b/lib/kokkos/example/fixture/BoxElemPart.cpp
new file mode 100644
index 0000000000..fe89246689
--- /dev/null
+++ b/lib/kokkos/example/fixture/BoxElemPart.cpp
@@ -0,0 +1,413 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <utility>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <limits>
+#include <BoxElemPart.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+void box_partition( const size_t global_size ,
+                    const size_t global_rank ,
+                    const size_t global_box[][2] ,
+                          size_t box[][2] )
+{
+  box[0][0] = global_box[0][0] ; box[0][1] = global_box[0][1] ;
+  box[1][0] = global_box[1][0] ; box[1][1] = global_box[1][1] ;
+  box[2][0] = global_box[2][0] ; box[2][1] = global_box[2][1] ;
+
+  size_t ip = 0 ;
+  size_t np = global_size ;
+
+  while ( 1 < np ) {
+
+    // P = [ ip + j * portion , ip + ( j + 1 ) * portion )
+
+    size_t jip , jup ;
+
+    {
+      const size_t part = ( 0 == ( np % 5 ) ) ? 5 : (
+                          ( 0 == ( np % 3 ) ) ? 3 : 2 );
+
+      const size_t portion = np / part ;
+
+      if ( 2 < part || global_rank < ip + portion ) {
+        jip = portion * size_t( double( global_rank - ip ) / double(portion) );
+        jup = jip + portion ;
+      }
+      else {
+        jip = portion ;
+        jup = np ;
+      }
+    }
+
+    // Choose axis with largest count:
+
+    const size_t nb[3] = {
+      box[0][1] - box[0][0] ,
+      box[1][1] - box[1][0] ,
+      box[2][1] - box[2][0] };
+
+    const int axis = nb[2] > nb[1] ? ( nb[2] > nb[0] ? 2 : 0 )
+                                        : ( nb[1] > nb[0] ? 1 : 0 );
+
+    box[ axis ][1] = box[ axis ][0] + size_t( double(nb[axis]) * ( double(jup) / double(np) ));
+    box[ axis ][0] = box[ axis ][0] + size_t( double(nb[axis]) * ( double(jip) / double(np) ));
+
+    np = jup - jip ;
+    ip = ip + jip ;
+  }
+}
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+void BoxElemPart::local( const size_t  rank ,
+                               size_t  uses_elem[][2] ,
+                               size_t  owns_node[][2] ,
+                               size_t  uses_node[][2] ) const
+{
+  if ( BoxElemPart::DecomposeElem == m_decompose ) {
+
+    Kokkos::Example::box_partition( m_global_size , rank , m_global_elem_box , uses_elem );
+
+    for ( int i = 0 ; i < 3 ; ++i ) {
+      owns_node[i][0] = uses_elem[i][0] ;
+      owns_node[i][1] = uses_elem[i][1] + ( m_global_elem_box[i][1] == uses_elem[i][1] ? 1 : 0 );
+    }
+  }
+  else {
+
+    const size_t global_vert[3][2] =
+      { { 0 , m_global_elem_box[0][1] + 1 },
+        { 0 , m_global_elem_box[1][1] + 1 },
+        { 0 , m_global_elem_box[2][1] + 1 } };
+
+    Kokkos::Example::box_partition( m_global_size , rank , global_vert , owns_node );
+
+    for ( int i = 0 ; i < 3 ; ++i ) {
+      uses_elem[i][0] = global_vert[i][0] == owns_node[i][0] ? owns_node[i][0] : owns_node[i][0] - 1 ;
+      uses_elem[i][1] = global_vert[i][1] == owns_node[i][1] ? owns_node[i][1] - 1 : owns_node[i][1] ;
+    }
+  }
+
+  for ( int i = 0 ; i < 3 ; ++i ) {
+    uses_node[i][0] = uses_elem[i][0] ;
+    uses_node[i][1] = uses_elem[i][1] + 1 ;
+  }
+
+  if ( BoxElemPart::ElemQuadratic == m_elem_order ) {
+    for ( int i = 0 ; i < 3 ; ++i ) {
+      owns_node[i][0] = 2 * owns_node[i][0] ;
+      uses_node[i][0] = 2 * uses_node[i][0] ;
+      owns_node[i][1] = 2 * owns_node[i][1] - 1 ;
+      uses_node[i][1] = 2 * uses_node[i][1] - 1 ;
+    }
+  }
+}
+
+BoxElemPart::BoxElemPart(
+  const BoxElemPart::ElemOrder elem_order ,
+  const BoxElemPart::Decompose decompose ,
+  const size_t global_size ,
+  const size_t global_rank ,
+  const size_t elem_nx ,
+  const size_t elem_ny ,
+  const size_t elem_nz )
+{
+  m_global_size = global_size ;
+  m_global_rank = global_rank ;
+  m_decompose   = decompose ;
+  m_elem_order  = elem_order ;
+
+  m_global_elem_box[0][0] = 0 ; m_global_elem_box[0][1] = elem_nx ;
+  m_global_elem_box[1][0] = 0 ; m_global_elem_box[1][1] = elem_ny ;
+  m_global_elem_box[2][0] = 0 ; m_global_elem_box[2][1] = elem_nz ;
+
+  m_global_node_box[0][0] = 0 ; m_global_node_box[0][1] = 0 ;
+  m_global_node_box[1][0] = 0 ; m_global_node_box[1][1] = 0 ;
+  m_global_node_box[2][0] = 0 ; m_global_node_box[2][1] = 0 ;
+
+  m_owns_node_count = 0 ;
+  m_send_node_count = 0 ;
+
+  m_ok = true ;
+
+  //----------------------------------------
+
+  if ( ElemLinear == elem_order ) {
+    m_global_node_box[0][1] = elem_nx + 1 ;
+    m_global_node_box[1][1] = elem_ny + 1 ;
+    m_global_node_box[2][1] = elem_nz + 1 ;
+  }
+  else if ( ElemQuadratic == elem_order ) {
+    m_global_node_box[0][1] = 2 * elem_nx + 1 ;
+    m_global_node_box[1][1] = 2 * elem_ny + 1 ;
+    m_global_node_box[2][1] = 2 * elem_nz + 1 ;
+  }
+
+  //----------------------------------------
+
+  local( m_global_rank , m_uses_elem_box , m_owns_node_box[0] , m_uses_node_box );
+
+  const size_t global_node_count_ = Kokkos::Example::box_count( m_global_node_box );
+  const size_t global_elem_count_ = Kokkos::Example::box_count( m_global_elem_box );
+
+  //----------------------------------------
+
+  size_t elem_count = Kokkos::Example::box_count( m_uses_elem_box );
+  size_t node_count = Kokkos::Example::box_count( m_owns_node_box[0] );
+
+  m_owns_node[0][0] = global_rank ;
+  m_owns_node[0][1] = node_count ;
+  m_owns_node_count = 1 ;
+  m_send_node_count = 0 ;
+
+  for ( size_t rr = 1 ; rr < m_global_size && m_ok ; ++rr ) {
+
+    const size_t rank = ( m_global_rank + rr ) % m_global_size ;
+
+    size_t elem_box[3][2] , o_node_box[3][2] , u_node_box[3][2] ;
+
+    // Boxes for process 'rank'
+    local( rank , elem_box , o_node_box , u_node_box );
+
+    // Box that this process uses but is owned by process 'rank'
+    Kokkos::Example::box_intersect( m_owns_node_box[ m_owns_node_count ] , m_uses_node_box , o_node_box );
+
+    m_owns_node[ m_owns_node_count ][1] = Kokkos::Example::box_count( m_owns_node_box[ m_owns_node_count ] );
+
+    if ( m_owns_node[ m_owns_node_count ][1] ) {
+
+      if ( ( PROC_NEIGH_MAX - 1 ) <= m_owns_node_count ) {
+        std::cout << "BoxElemPart exceeded maximum neighbor count" << std::endl ;
+        m_ok = false ;
+        break ;
+      }
+
+      m_owns_node[ m_owns_node_count ][0] = rank ;
+
+      ++m_owns_node_count ;
+    }
+
+    // Box that this process owns and is used by process 'rank'
+    Kokkos::Example::box_intersect( m_send_node_box[ m_send_node_count ] , m_owns_node_box[0] , u_node_box );
+
+    m_send_node[ m_send_node_count ][1] = Kokkos::Example::box_count( m_send_node_box[ m_send_node_count ] );
+
+    if ( m_send_node[ m_send_node_count ][1] ) {
+
+      if ( ( PROC_NEIGH_MAX - 1 ) <= m_send_node_count ) {
+        std::cout << "BoxElemPart exceeded maximum neighbor count" << std::endl ;
+        m_ok = false ;
+        break ;
+      }
+
+      m_send_node[ m_send_node_count ][0] = rank ;
+      ++m_send_node_count ;
+    }
+
+    // Error checking:
+
+    size_t test_box[3][2] ;
+
+    elem_count += Kokkos::Example::box_count( elem_box );
+    node_count += Kokkos::Example::box_count( o_node_box );
+
+    {
+      Kokkos::Example::box_intersect( test_box , m_owns_node_box[0] , o_node_box );
+
+      if ( Kokkos::Example::box_count( test_box ) ) {
+        std::cout << "Box partitioning error" << std::endl ;
+        std::cout << "owns_node[" << m_global_rank << "]{"
+                  << " [" << m_owns_node_box[0][0][0] << "," << m_owns_node_box[0][0][1] << ")"
+                  << " [" << m_owns_node_box[0][1][0] << "," << m_owns_node_box[0][1][1] << ")"
+                  << " [" << m_owns_node_box[0][2][0] << "," << m_owns_node_box[0][2][1] << ")"
+                  << "} intersects"
+                  << " owns_node[" << rank << "]{"
+                  << " [" << o_node_box[0][0] << "," << o_node_box[0][1] << ")"
+                  << " [" << o_node_box[1][0] << "," << o_node_box[1][1] << ")"
+                  << " [" << o_node_box[2][0] << "," << o_node_box[2][1] << ")"
+                  << "}" << std::endl ;
+        m_ok = false ;
+        break ;
+      }
+    }
+
+    if ( DecomposeElem == decompose ) {
+
+      Kokkos::Example::box_intersect( test_box , m_uses_elem_box , elem_box );
+
+      if ( Kokkos::Example::box_count( test_box ) ) {
+        std::cout << "Box partitioning error" << std::endl ;
+        std::cout << "ElemBox[" << m_global_rank << "]{"
+                  << " [" << m_uses_elem_box[0][0] << "," << m_uses_elem_box[0][1] << ")"
+                  << " [" << m_uses_elem_box[1][0] << "," << m_uses_elem_box[1][1] << ")"
+                  << " [" << m_uses_elem_box[2][0] << "," << m_uses_elem_box[2][1] << ")"
+                  << "} intersects"
+                  << " ElemBox[" << rank << "]{"
+                  << " [" << elem_box[0][0] << "," << elem_box[0][1] << ")"
+                  << " [" << elem_box[1][0] << "," << elem_box[1][1] << ")"
+                  << " [" << elem_box[2][0] << "," << elem_box[2][1] << ")"
+                  << "}" << std::endl ;
+        m_ok = false ;
+        break ;
+      }
+    }
+  }
+
+  // Sentinal values at the end of the owns and send lists:
+
+  m_owns_node[ m_owns_node_count ][0] = ~0u ;
+  m_owns_node[ m_owns_node_count ][1] = ~0u ;
+  m_owns_node_box[ m_owns_node_count ][0][0] = 0u ; m_owns_node_box[ m_owns_node_count ][0][0] = ~0u ;
+  m_owns_node_box[ m_owns_node_count ][1][0] = 0u ; m_owns_node_box[ m_owns_node_count ][1][0] = ~0u ;
+  m_owns_node_box[ m_owns_node_count ][2][0] = 0u ; m_owns_node_box[ m_owns_node_count ][2][0] = ~0u ;
+
+  m_send_node[ m_send_node_count ][0] = ~0u ;
+  m_send_node[ m_send_node_count ][1] = ~0u ;
+  m_send_node_box[ m_send_node_count ][0][0] = 0u ; m_send_node_box[ m_send_node_count ][0][0] = ~0u ;
+  m_send_node_box[ m_send_node_count ][1][0] = 0u ; m_send_node_box[ m_send_node_count ][1][0] = ~0u ;
+  m_send_node_box[ m_send_node_count ][2][0] = 0u ; m_send_node_box[ m_send_node_count ][2][0] = ~0u ;
+
+  {
+    size_t count = 0 ;
+    for ( size_t i = 0 ; i < m_owns_node_count ; ++i ) {
+      count += m_owns_node[i][1] ;
+    }
+    if ( count != Kokkos::Example::box_count( m_uses_node_box ) ) {
+      std::cout << "Node uses count = " << Kokkos::Example::box_count( m_uses_node_box )
+                << " error count = " << count << std::endl ;
+      m_ok = false ;
+    }
+  }
+
+  if ( global_node_count_ != node_count ) {
+    std::cout << "Node count = " << global_node_count_ << " overlap error count = " << node_count << std::endl ;
+    m_ok = false ;
+  }
+
+  if ( DecomposeElem == decompose && global_elem_count_ != elem_count ) {
+    std::cout << "Elem count = " << global_elem_count_ << " overlap error count = " << elem_count << std::endl ;
+    m_ok = false ;
+  }
+
+  if ( ! m_ok ) {
+    for ( int i = 0 ; i < 3 ; ++i ) { for ( int j = 0 ; j < 2 ; ++j ) {
+      m_global_elem_box[i][j] = 0 ;
+      m_global_node_box[i][j] = 0 ;
+      m_uses_elem_box[i][j] = 0 ;
+      m_uses_node_box[i][j] = 0 ;
+    }}
+    m_owns_node_count = 0 ;
+    m_send_node_count = 0 ;
+  }
+}
+
+void BoxElemPart::print( std::ostream & s ) const
+{
+  s << "BoxElemPart P[" << m_global_rank << ":" << m_global_size << "]"
+    << std::endl
+    << "  elem_box {"
+    << " [" << m_uses_elem_box[0][0] << "," << m_uses_elem_box[0][1] << ")"
+    << " [" << m_uses_elem_box[1][0] << "," << m_uses_elem_box[1][1] << ")"
+    << " [" << m_uses_elem_box[2][0] << "," << m_uses_elem_box[2][1] << ")"
+    << " } / {"
+    << " [" << m_global_elem_box[0][0] << "," << m_global_elem_box[0][1] << ")"
+    << " [" << m_global_elem_box[1][0] << "," << m_global_elem_box[1][1] << ")"
+    << " [" << m_global_elem_box[2][0] << "," << m_global_elem_box[2][1] << ")"
+    << " }"
+    << std::endl
+    << "  node_box {"
+    << " [" << m_owns_node_box[0][0][0] << "," << m_owns_node_box[0][0][1] << ")"
+    << " [" << m_owns_node_box[0][1][0] << "," << m_owns_node_box[0][1][1] << ")"
+    << " [" << m_owns_node_box[0][2][0] << "," << m_owns_node_box[0][2][1] << ")"
+    << " } / {"
+    << " [" << m_uses_node_box[0][0] << "," << m_uses_node_box[0][1] << ")"
+    << " [" << m_uses_node_box[1][0] << "," << m_uses_node_box[1][1] << ")"
+    << " [" << m_uses_node_box[2][0] << "," << m_uses_node_box[2][1] << ")"
+    << " } / {"
+    << " [" << m_global_node_box[0][0] << "," << m_global_node_box[0][1] << ")"
+    << " [" << m_global_node_box[1][0] << "," << m_global_node_box[1][1] << ")"
+    << " [" << m_global_node_box[2][0] << "," << m_global_node_box[2][1] << ")"
+    << " }"
+    << std::endl ;
+
+  for ( size_t i = 1 ; i < m_owns_node_count ; ++i ) {
+    s << "  P[" << m_owns_node[i][0] << "]"
+      << " recv node_box {"
+      << " [" << m_owns_node_box[i][0][0] << "," << m_owns_node_box[i][0][1] << ")"
+      << " [" << m_owns_node_box[i][1][0] << "," << m_owns_node_box[i][1][1] << ")"
+      << " [" << m_owns_node_box[i][2][0] << "," << m_owns_node_box[i][2][1] << ")"
+      << " }"
+      << std::endl ;
+  }
+
+  for ( size_t i = 0 ; i < m_send_node_count ; ++i ) {
+    s << "  P[" << m_send_node[i][0] << "]"
+      << " send node_box {"
+      << " [" << m_send_node_box[i][0][0] << "," << m_send_node_box[i][0][1] << ")"
+      << " [" << m_send_node_box[i][1][0] << "," << m_send_node_box[i][1][1] << ")"
+      << " [" << m_send_node_box[i][2][0] << "," << m_send_node_box[i][2][1] << ")"
+      << " }"
+      << std::endl ;
+  }
+}
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+//----------------------------------------------------------------------------
+
+
diff --git a/lib/kokkos/example/fixture/BoxElemPart.hpp b/lib/kokkos/example/fixture/BoxElemPart.hpp
new file mode 100644
index 0000000000..98f44e7d9d
--- /dev/null
+++ b/lib/kokkos/example/fixture/BoxElemPart.hpp
@@ -0,0 +1,320 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_BOXELEMPART_HPP
+#define KOKKOS_BOXELEMPART_HPP
+
+#include <utility>
+#include <ostream>
+#include <Kokkos_Macros.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+KOKKOS_INLINE_FUNCTION
+void box_intersect( size_t box[][2] ,
+                    const size_t boxA[][2] ,
+                    const size_t boxB[][2] )
+{
+  for ( int i = 0 ; i < 3 ; ++i ) {
+    box[i][0] = boxA[i][0] > boxB[i][0] ? boxA[i][0] : boxB[i][0] ;
+    box[i][1] = boxA[i][1] < boxB[i][1] ? boxA[i][1] : boxB[i][1] ;
+    if ( box[i][0] > box[i][1] ) box[i][1] = box[i][0] ;
+  }
+}
+
+KOKKOS_INLINE_FUNCTION
+size_t box_count( const size_t box[][2] )
+{
+  return size_t( box[0][1] - box[0][0] ) *
+         size_t( box[1][1] - box[1][0] ) *
+         size_t( box[2][1] - box[2][0] );
+}
+
+KOKKOS_INLINE_FUNCTION
+void box_ghost_layer( const size_t global_box[][2] ,
+                      const size_t local_box[][2] ,
+                      const size_t ghost_layer ,
+                            size_t ghost_box[][2] )
+{
+  for ( int i = 0 ; i < 3 ; ++i ) {
+    ghost_box[i][0] = global_box[i][0] + ghost_layer > local_box[i][0] ? global_box[i][0] : local_box[i][0] - ghost_layer ;
+    ghost_box[i][1] = global_box[i][1] < local_box[i][1] + ghost_layer ? global_box[i][1] : local_box[i][1] + ghost_layer ;
+  }
+}
+
+void box_partition( const size_t global_size ,
+                    const size_t global_rank ,
+                    const size_t global_box[][2] ,
+                          size_t box[][2] );
+
+} // namespace Example
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Example {
+
+/** \brief Partition a box of hexahedral elements among subdomains.
+ *
+ *  Nodes are ordered locally as follows:
+ *    { owned_by[ this_process ] ,
+ *      owned_by[ neighbor_process[0] ] ,
+ *      owned_by[ neighbor_process[1] ] ,
+ *      owned_by[ neighbor_process[2] ] ,
+ *      ... };
+ */
+class BoxElemPart {
+public:
+
+  enum Decompose { DecomposeNode , DecomposeElem };
+  enum ElemOrder { ElemLinear , ElemQuadratic };
+
+  bool ok() const { return m_ok ; }
+
+  BoxElemPart( const ElemOrder elem_order ,
+               const Decompose decompose ,
+               const size_t global_size ,
+               const size_t global_rank ,
+               const size_t elem_nx ,
+               const size_t elem_ny ,
+               const size_t elem_nz );
+
+  KOKKOS_INLINE_FUNCTION
+  size_t global_elem_count() const
+    { return Kokkos::Example::box_count( m_global_elem_box ); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t global_node_count() const
+    { return Kokkos::Example::box_count( m_global_node_box ); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t uses_elem_count() const
+    { return Kokkos::Example::box_count( m_uses_elem_box ); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t owns_node_count() const
+    { return Kokkos::Example::box_count( m_owns_node_box[0] ); }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t uses_node_count() const
+    { return Kokkos::Example::box_count( m_uses_node_box ); }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  size_t uses_elem_offset( const size_t ix ,
+                           const size_t iy ,
+                           const size_t iz ) const
+  {
+    return size_t( ix - m_uses_elem_box[0][0] ) + size_t( m_uses_elem_box[0][1] - m_uses_elem_box[0][0] ) * (
+           size_t( iy - m_uses_elem_box[1][0] ) + size_t( m_uses_elem_box[1][1] - m_uses_elem_box[1][0] ) * (
+           size_t( iz - m_uses_elem_box[2][0] ) ) );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void uses_elem_coord( size_t lid , size_t c[] ) const
+  {
+    const size_t nx = m_uses_elem_box[0][1] - m_uses_elem_box[0][0] ;
+    const size_t ny = m_uses_elem_box[1][1] - m_uses_elem_box[1][0] ;
+
+    c[0] = m_uses_elem_box[0][0] + lid % nx ; lid /= nx ;
+    c[1] = m_uses_elem_box[1][0] + lid % ny ; lid /= ny ;
+    c[2] = m_uses_elem_box[2][0] + lid ;
+  }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  size_t global_coord_max( size_t axis ) const
+  { return m_global_node_box[axis][1] - 1 ; }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void local_node_coord( size_t lid , size_t coord[] ) const
+  {
+    // Local id within an 'owns' block (has sentinal)
+    size_t j = 0 ;
+    while ( m_owns_node[j][1] <= lid ) { lid -= m_owns_node[j][1] ; ++j ; }
+
+    // Map to global coordinates:
+    const size_t nx = m_owns_node_box[j][0][1] - m_owns_node_box[j][0][0] ;
+    const size_t ny = m_owns_node_box[j][1][1] - m_owns_node_box[j][1][0] ;
+
+    coord[0] = m_owns_node_box[j][0][0] + lid % nx ; lid /= nx ;
+    coord[1] = m_owns_node_box[j][1][0] + lid % ny ; lid /= ny ;
+    coord[2] = m_owns_node_box[j][2][0] + lid ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t local_node_id( const size_t c[] ) const
+  {
+    // Find which 'owns' block and accumulate the offset of this block:
+    size_t lid = 0 ;
+    size_t j = 0 ;
+    while ( ! ( m_owns_node_box[j][0][0] <= c[0] && c[0] < m_owns_node_box[j][0][1] &&
+                m_owns_node_box[j][1][0] <= c[1] && c[1] < m_owns_node_box[j][1][1] &&
+                m_owns_node_box[j][2][0] <= c[2] && c[2] < m_owns_node_box[j][2][1] ) ) {
+      
+      lid += m_owns_node[j][1] ;
+      ++j ;
+    }
+
+    // Map offset to the block plus offset within the block:
+    return lid +
+           size_t( c[0] - m_owns_node_box[j][0][0] ) + size_t( m_owns_node_box[j][0][1] - m_owns_node_box[j][0][0] ) * (
+           size_t( c[1] - m_owns_node_box[j][1][0] ) + size_t( m_owns_node_box[j][1][1] - m_owns_node_box[j][1][0] ) * (
+           size_t( c[2] - m_owns_node_box[j][2][0] ) ) );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t global_node_id( const size_t c[] ) const
+  {
+    return size_t( c[0] - m_global_node_box[0][0] ) + size_t( m_global_node_box[0][1] - m_global_node_box[0][0] ) * (
+           size_t( c[1] - m_global_node_box[1][0] ) + size_t( m_global_node_box[1][1] - m_global_node_box[1][0] ) * (
+           size_t( c[2] - m_global_node_box[2][0] ) ) );
+  }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  size_t recv_node_msg_count() const { return m_owns_node_count - 1 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t recv_node_rank(  size_t msg ) const { return m_owns_node[msg+1][0] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t recv_node_count( size_t msg ) const { return m_owns_node[msg+1][1] ; }
+
+  //----------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  size_t send_node_msg_count() const { return m_send_node_count ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t send_node_rank(  size_t msg ) const { return m_send_node[msg][0] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t send_node_count( size_t msg ) const { return m_send_node[msg][1] ; }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t send_node_id_count() const
+  {
+    size_t count = 0 ;
+    for ( size_t i = 0 ; i < m_send_node_count ; ++i ) {
+      count += m_send_node[i][1] ;
+    }
+    return count ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  size_t send_node_id( size_t item ) const
+  {
+    // Find which send list this send item is in:
+    size_t j = 0 ;
+    while ( m_send_node[j][1] <= item ) { item -= m_send_node[j][1] ; ++j ; }
+
+    // Map to global coordinate:
+    const size_t nx = m_send_node_box[j][0][1] - m_send_node_box[j][0][0] ;
+    const size_t ny = m_send_node_box[j][1][1] - m_send_node_box[j][1][0] ;
+
+    size_t c[3] ;
+
+    c[0] = m_send_node_box[j][0][0] + item % nx ; item /= nx ;
+    c[1] = m_send_node_box[j][1][0] + item % ny ; item /= ny ;
+    c[2] = m_send_node_box[j][2][0] + item ;
+
+    // Map to local id:
+    return size_t( c[0] - m_owns_node_box[0][0][0] ) + size_t( m_owns_node_box[0][0][1] - m_owns_node_box[0][0][0] ) * (
+           size_t( c[1] - m_owns_node_box[0][1][0] ) + size_t( m_owns_node_box[0][1][1] - m_owns_node_box[0][1][0] ) * (
+           size_t( c[2] - m_owns_node_box[0][2][0] ) ) );
+  }
+
+  //----------------------------------------
+
+  void print( std::ostream & s ) const ;
+
+private:
+
+  // Maximum number of processes in a neighborhood, including this process
+  enum { PROC_NEIGH_MAX = 64 };
+
+  void local( const size_t  rank ,
+                    size_t  uses_elem[][2] ,
+                    size_t  owns_node[][2] ,
+                    size_t  uses_node[][2] ) const ;
+
+  size_t  m_global_size ;
+  size_t  m_global_rank ;
+
+  Decompose m_decompose ;
+  ElemOrder m_elem_order ;
+
+  size_t m_global_elem_box[3][2] ;
+  size_t m_global_node_box[3][2] ;
+  size_t m_uses_elem_box[3][2] ;
+  size_t m_uses_node_box[3][2] ;
+
+  // [ processor rank , count ]
+  size_t m_owns_node_box[ PROC_NEIGH_MAX ][3][2] ;
+  size_t m_owns_node[     PROC_NEIGH_MAX ][2] ;
+  size_t m_owns_node_count ;
+
+  size_t m_send_node_box[ PROC_NEIGH_MAX ][3][2] ;
+  size_t m_send_node[     PROC_NEIGH_MAX ][2] ;
+  size_t m_send_node_count ;
+
+  bool   m_ok ;
+};
+
+} // namespace Example
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_BOXELEMPART_HPP */
+
diff --git a/lib/kokkos/example/fixture/CMakeLists.txt b/lib/kokkos/example/fixture/CMakeLists.txt
new file mode 100644
index 0000000000..298c54c5bb
--- /dev/null
+++ b/lib/kokkos/example/fixture/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../common)
+
+SET(SOURCES_TEST Main.cpp TestFixture.cpp BoxElemPart.cpp )
+
+# Automatically picks up 'kokkosexample_fixture'
+TRIBITS_ADD_EXECUTABLE_AND_TEST(
+  TestFixture
+  SOURCES ${SOURCES_TEST}
+  )
+
diff --git a/lib/kokkos/example/fixture/HexElement.hpp b/lib/kokkos/example/fixture/HexElement.hpp
new file mode 100644
index 0000000000..cb39358f9d
--- /dev/null
+++ b/lib/kokkos/example/fixture/HexElement.hpp
@@ -0,0 +1,270 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_HEXELEMENT_HPP
+#define KOKKOS_HEXELEMENT_HPP
+
+namespace Kokkos {
+namespace Example {
+
+template< unsigned NodeCount >
+class HexElement_TensorData ;
+
+template< unsigned NodeCount , class Device >
+class HexElement_TensorEval ;
+
+//----------------------------------------------------------------------------
+/** \brief  Evaluate Hex element on interval [-1,1]^3 */
+template<>
+class HexElement_TensorData< 8 > {
+public:
+
+  static const unsigned element_node_count    = 8 ;
+  static const unsigned spatial_dimension     = 3 ;
+  static const unsigned integration_count_1d  = 2 ;
+  static const unsigned function_count_1d     = 2 ;
+
+  float values_1d [ function_count_1d ][ integration_count_1d ];
+  float derivs_1d [ function_count_1d ][ integration_count_1d ];
+  float weights_1d[ integration_count_1d ];
+
+  unsigned char eval_map[ element_node_count ][4] ;
+
+  static float eval_value_1d( const unsigned jf , const float x )
+  {
+    return 0 == jf ? 0.5 * ( 1.0 - x ) : (
+           1 == jf ? 0.5 * ( 1.0 + x ) : 0 );
+  }
+
+  static float eval_deriv_1d( const unsigned jf , const float )
+  {
+    return 0 == jf ? -0.5 : (
+           1 == jf ?  0.5 : 0 );
+  }
+
+  HexElement_TensorData()
+  {
+    const unsigned char tmp_map[ element_node_count ][ spatial_dimension ] =
+      { { 0 , 0 , 0 },
+        { 1 , 0 , 0 },
+        { 1 , 1 , 0 },
+        { 0 , 1 , 0 },
+        { 0 , 0 , 1 },
+        { 1 , 0 , 1 },
+        { 1 , 1 , 1 },
+        { 0 , 1 , 1 } };
+
+    weights_1d[0] = 1 ;
+    weights_1d[1] = 1 ;
+
+    const float points_1d[ integration_count_1d ] =
+      { -0.577350269 , 0.577350269 };
+
+    for ( unsigned i = 0 ; i < element_node_count ; ++i ) {
+      eval_map[i][0] = tmp_map[i][0];
+      eval_map[i][1] = tmp_map[i][1];
+      eval_map[i][2] = tmp_map[i][2];
+    }
+
+    for ( unsigned xp = 0 ; xp < integration_count_1d ; ++xp ) {
+    for ( unsigned xf = 0 ; xf < function_count_1d ; ++xf ) {
+      values_1d[xp][xf] = eval_value_1d( xf , points_1d[xp] );
+      derivs_1d[xp][xf] = eval_deriv_1d( xf , points_1d[xp] );
+    }}
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template<>
+class HexElement_TensorData< 27 > {
+public:
+
+  static const unsigned element_node_count    = 27 ;
+  static const unsigned spatial_dimension     = 3 ;
+  static const unsigned integration_count_1d  = 3 ;
+  static const unsigned function_count_1d     = 3 ;
+
+  float values_1d [ function_count_1d ][ integration_count_1d ];
+  float derivs_1d [ function_count_1d ][ integration_count_1d ];
+  float weights_1d[ integration_count_1d ];
+
+  unsigned char eval_map[ element_node_count ][4] ;
+
+  // sizeof(EvaluateElementHex) = 111 bytes =
+  //   sizeof(float) * 9 +
+  //   sizeof(float) * 9 +
+  //   sizeof(float) * 3 +
+  //   sizeof(char) * 27 
+
+  static float eval_value_1d( const unsigned jf , const float p )
+  {
+    return 0 == jf ? 0.5 * p * ( p - 1 ) : (
+           1 == jf ? 1.0 - p * p : (
+           2 == jf ? 0.5 * p * ( p + 1 ) : 0 ));
+  }
+
+  static float eval_deriv_1d( const unsigned jf , const float p )
+  {
+    return 0 == jf ? p - 0.5 : (
+           1 == jf ? -2.0 * p : (
+           2 == jf ? p + 0.5 : 0 ));
+  }
+
+  HexElement_TensorData()
+  {
+    const unsigned char tmp_map[ element_node_count ][ spatial_dimension ] =
+      { { 0 , 0 , 0 },
+        { 2 , 0 , 0 },
+        { 2 , 2 , 0 },
+        { 0 , 2 , 0 },
+        { 0 , 0 , 2 },
+        { 2 , 0 , 2 },
+        { 2 , 2 , 2 },
+        { 0 , 2 , 2 },
+        { 1 , 0 , 0 },
+        { 2 , 1 , 0 },
+        { 1 , 2 , 0 },
+        { 0 , 1 , 0 },
+        { 0 , 0 , 1 },
+        { 2 , 0 , 1 },
+        { 2 , 2 , 1 },
+        { 0 , 2 , 1 },
+        { 1 , 0 , 2 },
+        { 2 , 1 , 2 },
+        { 1 , 2 , 2 },
+        { 0 , 1 , 2 },
+        { 1 , 1 , 1 },
+        { 1 , 1 , 0 },
+        { 1 , 1 , 2 },
+        { 0 , 1 , 1 },
+        { 2 , 1 , 1 },
+        { 1 , 0 , 1 },
+        { 1 , 2 , 1 } };
+
+    // Interval [-1,1]
+
+    weights_1d[0] = 0.555555556 ;
+    weights_1d[1] = 0.888888889 ;
+    weights_1d[2] = 0.555555556 ;
+
+    const float points_1d[3] = { -0.774596669 ,
+                                  0.000000000 ,
+                                  0.774596669 };
+
+    for ( unsigned i = 0 ; i < element_node_count ; ++i ) {
+      eval_map[i][0] = tmp_map[i][0];
+      eval_map[i][1] = tmp_map[i][1];
+      eval_map[i][2] = tmp_map[i][2];
+    }
+
+    for ( unsigned xp = 0 ; xp < integration_count_1d ; ++xp ) {
+    for ( unsigned xf = 0 ; xf < function_count_1d ; ++xf ) {
+      values_1d[xp][xf] = eval_value_1d( xf , points_1d[xp] );
+      derivs_1d[xp][xf] = eval_deriv_1d( xf , points_1d[xp] );
+    }}
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< unsigned NodeCount >
+class HexElement_Data {
+public:
+  static const unsigned spatial_dimension   = 3 ;
+  static const unsigned element_node_count  = NodeCount ;
+  static const unsigned integration_count   = NodeCount ;
+  static const unsigned function_count      = NodeCount ;
+
+  float weights[   integration_count ] ;
+  float values[    integration_count ][ function_count ];
+  float gradients[ integration_count ][ spatial_dimension ][ function_count ];
+
+  HexElement_Data()
+  {
+    HexElement_TensorData< NodeCount > tensor_data ;
+
+    for ( unsigned ip = 0 ; ip < integration_count ; ++ip ) {
+
+      const unsigned ipx = tensor_data.eval_map[ip][0] ;
+      const unsigned ipy = tensor_data.eval_map[ip][1] ;
+      const unsigned ipz = tensor_data.eval_map[ip][2] ;
+
+      weights[ip] = tensor_data.weights_1d[ ipx ] *
+                    tensor_data.weights_1d[ ipy ] *
+                    tensor_data.weights_1d[ ipz ] ;
+
+      for ( unsigned jf = 0 ; jf < function_count ; ++jf ) {
+
+        const unsigned jfx = tensor_data.eval_map[jf][0] ;
+        const unsigned jfy = tensor_data.eval_map[jf][1] ;
+        const unsigned jfz = tensor_data.eval_map[jf][2] ;
+
+        values[ip][jf] = tensor_data.values_1d[ ipx ][ jfx ] *
+                         tensor_data.values_1d[ ipy ][ jfy ] *
+                         tensor_data.values_1d[ ipz ][ jfz ] ;
+
+        gradients[ip][0][jf] = tensor_data.derivs_1d[ ipx ][ jfx ] *
+                               tensor_data.values_1d[ ipy ][ jfy ] *
+                               tensor_data.values_1d[ ipz ][ jfz ] ;
+
+        gradients[ip][1][jf] = tensor_data.values_1d[ ipx ][ jfx ] *
+                               tensor_data.derivs_1d[ ipy ][ jfy ] *
+                               tensor_data.values_1d[ ipz ][ jfz ] ;
+
+        gradients[ip][2][jf] = tensor_data.values_1d[ ipx ][ jfx ] *
+                               tensor_data.values_1d[ ipy ][ jfy ] *
+                               tensor_data.derivs_1d[ ipz ][ jfz ] ;
+      }
+    }
+  }
+};
+
+//----------------------------------------------------------------------------
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_HEXELEMENT_HPP */
+
+
diff --git a/lib/kokkos/example/fixture/Main.cpp b/lib/kokkos/example/fixture/Main.cpp
new file mode 100644
index 0000000000..d80828ca52
--- /dev/null
+++ b/lib/kokkos/example/fixture/Main.cpp
@@ -0,0 +1,304 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#include <utility>
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+#include <BoxElemPart.hpp>
+
+namespace Kokkos {
+namespace Example {
+template< class > void test_fixture();
+}
+}
+
+int test_box( const size_t global_size
+            , const size_t global_box[][2]
+            , const bool print_verbose )
+{
+  size_t global_count = 0 ;
+  size_t global_max = 0 ;
+  size_t global_min = Kokkos::Example::box_count( global_box );
+  size_t global_box_max[3][2] = { { 0 , 0 } , { 0 , 0 } , { 0 , 0 } };
+  size_t global_box_min[3][2] = { { 0 , global_box[0][1] } , { 0 , global_box[1][1] } , { 0 , global_box[2][1] } };
+  size_t intersect_error = 0 ;
+  size_t neighbor_max = 0 ;
+
+  for ( size_t global_rank = 0 ; global_rank < global_size ; ++global_rank ) {
+    size_t box[3][2] = { { 0 , global_box[0][1] } , { 0 , global_box[1][1] } , { 0 , global_box[2][1] } };
+    size_t ghost_box[3][2] ;
+    size_t neighbor_count = 0 ;
+
+    Kokkos::Example::box_partition( global_size , global_rank , global_box , box );
+
+    Kokkos::Example::box_ghost_layer( global_box , box , 1 , ghost_box );
+
+    {
+      const size_t n = Kokkos::Example::box_count( box );
+
+      for ( int i = 0 ; i < 3 ; ++i ) {
+        if ( ( box[i][1] - box[i][0] ) < ( global_box_min[i][1] - global_box_min[i][0] ) ) {
+          global_box_min[i][0] = box[i][0] ;
+          global_box_min[i][1] = box[i][1] ;
+        }
+        if ( ( box[i][1] - box[i][0] ) > ( global_box_max[i][1] - global_box_max[i][0] ) ) {
+          global_box_max[i][0] = box[i][0] ;
+          global_box_max[i][1] = box[i][1] ;
+        }
+      }
+
+      global_max = std::max( global_max , n );
+      global_min = std::min( global_min , n );
+      global_count += n ;
+    }
+
+    for ( size_t other_rank = 0 ; other_rank  < global_size ; ++other_rank ) {
+
+      if ( other_rank == global_rank ) continue ;
+
+      size_t other_box[3][2] = { { 0 , global_box[0][1] } , { 0 , global_box[1][1] } , { 0 , global_box[2][1] } };
+      size_t intersect_box[3][2] ;
+
+      Kokkos::Example::box_partition( global_size , other_rank , global_box , other_box );
+
+      Kokkos::Example::box_intersect( intersect_box , box , other_box );
+
+      const size_t n = Kokkos::Example::box_count( intersect_box );
+
+      intersect_error += n ;
+
+      Kokkos::Example::box_intersect( intersect_box , ghost_box , other_box );
+
+      neighbor_count += Kokkos::Example::box_count( intersect_box ) ? 1 : 0 ;
+
+      if ( n ) {
+        std::cout << "box partition intersection error" << std::endl ;
+        std::cout << "box = {"
+                  << " [ " << box[0][0] << " , " << box[0][1] << " )"
+                  << " [ " << box[1][0] << " , " << box[1][1] << " )"
+                  << " [ " << box[2][0] << " , " << box[2][1] << " )"
+                  << " }" << std::endl ;
+        std::cout << "other_box = {"
+                  << " [ " << other_box[0][0] << " , " << other_box[0][1] << " )"
+                  << " [ " << other_box[1][0] << " , " << other_box[1][1] << " )"
+                  << " [ " << other_box[2][0] << " , " << other_box[2][1] << " )"
+                  << " }" << std::endl ;
+        return 0 ;
+      }
+    }
+
+    neighbor_max = std::max( neighbor_max , neighbor_count );
+  }
+
+  if ( print_verbose ) {
+
+    std::cout << "global_part = " << global_size << std::endl ;
+    std::cout << "global_box  = { "
+              << " [ " << global_box[0][0] << " .. " << global_box[0][1] << " ) X"
+              << " [ " << global_box[1][0] << " .. " << global_box[1][1] << " ) X"
+              << " [ " << global_box[2][0] << " .. " << global_box[2][1] << " )"
+              << " }" << std::endl ;
+    std::cout << "count( global_box ) = " << Kokkos::Example::box_count( global_box ) << std::endl ;
+    std::cout << "sum partition( global_box ) = " << global_count << std::endl ;
+    std::cout << "avg partition( global_box ) = " << size_t( double(global_count) / double(global_size)) << std::endl ;
+    std::cout << "min partition( global_box ) = " << global_min << std::endl ;
+    std::cout << "min part X   ( global_box ) = [ " << global_box_min[0][0] << " .. " << global_box_min[0][1] << " )" << std::endl ;
+    std::cout << "min part Y   ( global_box ) = [ " << global_box_min[1][0] << " .. " << global_box_min[1][1] << " )" << std::endl ;
+    std::cout << "min part Z   ( global_box ) = [ " << global_box_min[2][0] << " .. " << global_box_min[2][1] << " )" << std::endl ;
+    std::cout << "max partition( global_box ) = " << global_max << std::endl ;
+    std::cout << "max part X   ( global_box ) = [ " << global_box_max[0][0] << " .. " << global_box_max[0][1] << " )" << std::endl ;
+    std::cout << "max part Y   ( global_box ) = [ " << global_box_max[1][0] << " .. " << global_box_max[1][1] << " )" << std::endl ;
+    std::cout << "max part Z   ( global_box ) = [ " << global_box_max[2][0] << " .. " << global_box_max[2][1] << " )" << std::endl ;
+    std::cout << "sum intersect( global_box ) = " << intersect_error << std::endl ;
+    std::cout << "max neighbor = " << neighbor_max << std::endl ;
+  }
+
+  return neighbor_max ;
+}
+
+void test_elem()
+{
+  const Kokkos::Example::BoxElemPart::Decompose
+    decompose = Kokkos::Example::BoxElemPart:: DecomposeElem ; // DecomposeElem | DecomposeNode ;
+  const size_t global_size = 256 ;
+  const size_t global_nx = 100 ;
+  const size_t global_ny = 120 ;
+  const size_t global_nz = 140 ;
+
+  double node_count_avg = 0 ;
+  size_t node_count_max = 0 ;
+  size_t node_count_min = ( global_nx + 1 ) * ( global_ny + 1 ) * ( global_nz + 1 );
+  double elem_count_avg = 0 ;
+  size_t elem_count_max = 0 ;
+  size_t elem_count_min = global_nx * global_ny * global_nz ;
+  double recv_count_avg = 0 ;
+  size_t recv_count_max = 0 ;
+  size_t recv_count_min = global_size ;
+  double send_count_avg = 0 ;
+  size_t send_count_max = 0 ;
+  size_t send_count_min = global_size ;
+
+  for ( size_t r = 0 ; r < global_size ; ++r ) {
+    const Kokkos::Example::BoxElemPart
+       fixture( Kokkos::Example::BoxElemPart::ElemLinear ,
+                decompose , global_size , r , global_nx , global_ny , global_nz );
+
+    // Print a sample:
+
+    // if ( r == global_size * 2 / 3 ) fixture.print( std::cout );
+
+    // Verify recv/send alignment:
+
+    {
+      size_t recv_lid = fixture.owns_node_count();
+
+      for ( size_t i = 0 ; i < fixture.recv_node_msg_count() ; ++i ) {
+        const size_t recv_rank  = fixture.recv_node_rank( i );
+        const size_t recv_count = fixture.recv_node_count( i );
+
+        const Kokkos::Example::BoxElemPart other_fixture(
+           Kokkos::Example::BoxElemPart::ElemLinear ,
+           decompose , global_size , recv_rank , global_nx , global_ny , global_nz );
+
+        size_t send_item = 0 ;
+
+        size_t j = 0 ;
+        while ( j < other_fixture.send_node_msg_count() && other_fixture.send_node_rank(j) != r ) {
+          send_item += other_fixture.send_node_count( j );
+           ++j ;
+        }
+
+        if ( recv_count != other_fixture.send_node_count(j) ) {
+          std::cout << "Error P[" << r << "].recv(" << recv_count << ") != "
+                    << "P[" << recv_rank << "].send(" << other_fixture.send_node_count(j) << ")"
+                    << std::endl ;
+        }
+        else {
+
+          for ( size_t k = 0 ; k < recv_count ; ++k , ++send_item , ++recv_lid ) {
+
+            const size_t send_lid = other_fixture.send_node_id( send_item );
+
+            size_t recv_coord[3] , send_coord[3] ;
+
+            fixture.local_node_coord( recv_lid , recv_coord );
+
+            other_fixture.local_node_coord( send_lid , send_coord );
+
+            if ( recv_coord[0] != send_coord[0] ||
+                 recv_coord[1] != send_coord[1] ||
+                 recv_coord[2] != send_coord[2] ) {
+              std::cout << "Error P[" << r << "].recv[" << recv_lid << "]{ "
+                        << recv_coord[0] << " , "
+                        << recv_coord[1] << " , "
+                        << recv_coord[2] << " } != "
+                        << "P[" << recv_rank << "].send[" << send_lid << "]{ "
+                        << send_coord[0] << " , "
+                        << send_coord[1] << " , "
+                        << send_coord[2] << " }"
+                        << std::endl ;
+            }
+          }
+        }
+      }
+    }
+
+    node_count_avg += fixture.owns_node_count();
+    elem_count_avg += fixture.uses_elem_count();
+    recv_count_avg += fixture.recv_node_msg_count();
+    send_count_avg += fixture.send_node_msg_count();
+
+    elem_count_min = std::min( (size_t) fixture.uses_elem_count() , elem_count_min );
+    elem_count_max = std::max( (size_t) fixture.uses_elem_count() , elem_count_max );
+    node_count_min = std::min( (size_t) fixture.owns_node_count() , node_count_min );
+    node_count_max = std::max( (size_t) fixture.owns_node_count() , node_count_max );
+
+    recv_count_max = std::max( (size_t) fixture.recv_node_msg_count() , recv_count_max );
+    recv_count_min = std::min( (size_t) fixture.recv_node_msg_count() , recv_count_min );
+    send_count_max = std::max( (size_t) fixture.send_node_msg_count() , send_count_max );
+    send_count_min = std::min( (size_t) fixture.send_node_msg_count() , send_count_min );
+  }
+
+  node_count_avg /= double(global_size);
+  elem_count_avg /= double(global_size);
+  recv_count_avg /= double(global_size);
+  send_count_avg /= double(global_size);
+
+  std::cout << "Elem min(" << elem_count_min << ") avg(" << elem_count_avg << ") max(" << elem_count_max << ") " << std::endl
+            << "Node min(" << node_count_min << ") avg(" << node_count_avg << ") max(" << node_count_max << ") " << std::endl
+            << "Recv min(" << recv_count_min << ") avg(" << recv_count_avg << ") max(" << recv_count_max << ") " << std::endl
+            << "Send min(" << send_count_min << ") avg(" << send_count_avg << ") max(" << send_count_max << ") " << std::endl
+            ;
+}
+
+int main()
+{
+  for ( int i = 1 ; i <= 32 ; ++i ) {
+    const size_t global_size = 16 * i ;
+    const size_t global_box[3][2] = { { 0 , 65 } , { 0 , 65 } , { 0 , 65 } };
+    if ( 30 < test_box( global_size , global_box , false ) ) {
+      test_box( global_size , global_box , true );
+    }
+  }
+
+//  test_elem();
+
+  {
+    std::cout << "test_fixture< Host >" << std::endl ;
+    Kokkos::HostSpace::execution_space::initialize( 1 );
+    Kokkos::Example::test_fixture< Kokkos::HostSpace::execution_space >();
+    Kokkos::HostSpace::execution_space::finalize();
+  }
+
+#if defined( KOKKOS_HAVE_CUDA )
+  {
+    std::cout << "test_fixture< Cuda >" << std::endl ;
+    Kokkos::HostSpace::execution_space::initialize();
+    Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice(0) );
+    Kokkos::Example::test_fixture< Kokkos::Cuda >();
+    Kokkos::Cuda::finalize();
+    Kokkos::HostSpace::execution_space::finalize();
+  }
+#endif
+}
+
diff --git a/lib/kokkos/example/fixture/Makefile b/lib/kokkos/example/fixture/Makefile
new file mode 100644
index 0000000000..990f4f18e7
--- /dev/null
+++ b/lib/kokkos/example/fixture/Makefile
@@ -0,0 +1,48 @@
+KOKKOS_PATH = ../..
+
+vpath %.cpp ${KOKKOS_PATH}/example/fixture
+
+EXAMPLE_HEADERS = $(wildcard $(KOKKOS_PATH)/example/common/*.hpp ${KOKKOS_PATH}/example/fixture/*.hpp )
+
+default: build_all
+	echo "End Build"
+        
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?= -lpthread
+endif
+
+KOKKOS_CXXFLAGS +=	\
+	-I${KOKKOS_PATH}/example/common	\
+	-I${KOKKOS_PATH}/example/fixture
+
+EXE_EXAMPLE_FIXTURE = KokkosExample_Fixture
+OBJ_EXAMPLE_FIXTURE = Main.o TestFixture.o BoxElemPart.o
+
+TARGETS = $(EXE_EXAMPLE_FIXTURE)
+
+#TEST_TARGETS =
+
+$(EXE_EXAMPLE_FIXTURE) : $(OBJ_EXAMPLE_FIXTURE) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) $(OBJ_EXAMPLE_FIXTURE) $(KOKKOS_LIBS) $(LIB) -o $(EXE_EXAMPLE_FIXTURE)
+
+build_all : $(TARGETS)
+
+test : build_all
+
+clean: kokkos-clean
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS) $(EXAMPLE_HEADERS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/fixture/TestFixture.cpp b/lib/kokkos/example/fixture/TestFixture.cpp
new file mode 100644
index 0000000000..9cf2f07322
--- /dev/null
+++ b/lib/kokkos/example/fixture/TestFixture.cpp
@@ -0,0 +1,58 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <TestFixture.hpp>
+
+namespace Kokkos {
+namespace Example {
+
+template void test_fixture< Kokkos::HostSpace::execution_space >();
+
+#if defined( KOKKOS_HAVE_CUDA )
+template void test_fixture<Kokkos::Cuda>();
+#endif
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
diff --git a/lib/kokkos/example/fixture/TestFixture.hpp b/lib/kokkos/example/fixture/TestFixture.hpp
new file mode 100644
index 0000000000..dbf5ca56f5
--- /dev/null
+++ b/lib/kokkos/example/fixture/TestFixture.hpp
@@ -0,0 +1,156 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXAMPLE_TESTFIXTURE_HPP
+#define KOKKOS_EXAMPLE_TESTFIXTURE_HPP
+
+#include <utility>
+#include <iostream>
+
+#include <Kokkos_Core.hpp>
+
+#include <BoxElemPart.hpp>
+#include <BoxElemFixture.hpp>
+
+namespace Kokkos {
+namespace Example {
+
+template< class Device >
+struct FixtureVerifyElemNodeCoord
+{
+  typedef Device execution_space ;
+
+  typedef struct { size_t success , error ; } value_type ;
+
+  typedef Kokkos::Example::BoxElemFixture< Device , Kokkos::Example::BoxElemPart::ElemLinear > FixtureType ;
+
+  FixtureType m_fixture ;
+
+  KOKKOS_INLINE_FUNCTION
+  void init( value_type & update ) const { update.success = update.error = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join( volatile       value_type & update ,
+             volatile const value_type & input ) const
+    {
+      update.success += input.success ;
+      update.error += input.error ;
+    }
+  
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_t ielem , value_type & update ) const
+  {
+    unsigned node_coord[ FixtureType::ElemNode ][3] ;
+
+    for ( unsigned i = 0 ; i < FixtureType::ElemNode ; ++i ) {
+      const unsigned node_id = m_fixture.elem_node(ielem,i);
+      node_coord[i][0] = m_fixture.node_grid(node_id,0);
+      node_coord[i][1] = m_fixture.node_grid(node_id,1);
+      node_coord[i][2] = m_fixture.node_grid(node_id,2);
+    }
+
+    int error = 0 ;
+    for ( unsigned i = 1 ; i < FixtureType::ElemNode ; ++i ) {
+      if ( node_coord[0][0] + m_fixture.elem_node_local(i,0) != node_coord[i][0] ||
+           node_coord[0][1] + m_fixture.elem_node_local(i,1) != node_coord[i][1] ||
+           node_coord[0][2] + m_fixture.elem_node_local(i,2) != node_coord[i][2] ) {
+        error = 1 ;
+      }
+    }
+
+    if ( error ) {
+      ++update.error ;
+    }
+    else {
+      ++update.success ;
+    }
+  }
+
+  FixtureVerifyElemNodeCoord( const FixtureType & f ) : m_fixture(f) {}
+};
+
+
+template< class Device >
+void test_fixture()
+{
+  typedef Kokkos::Example::BoxElemFixture< Device , Kokkos::Example::BoxElemPart::ElemLinear > FixtureType ;
+
+  const Kokkos::Example::BoxElemPart::Decompose
+    decompose = Kokkos::Example::BoxElemPart:: DecomposeElem ; // DecomposeElem | DecomposeNode ;
+
+  const unsigned global_size = 256 ;
+  const unsigned global_nx = 400 ;
+  const unsigned global_ny = 400 ;
+  const unsigned global_nz = 400 ;
+
+  for ( unsigned my_rank = 0 ; my_rank < global_size ; ++my_rank ) {
+
+    const FixtureType fixture( decompose , global_size , my_rank , global_nx , global_ny , global_nz );
+
+    // Verify grid coordinates of element's nodes
+    
+    typename FixtureVerifyElemNodeCoord<Device>::value_type result = { 0 , 0 };
+
+    Kokkos::parallel_reduce( fixture.elem_node().dimension_0() , FixtureVerifyElemNodeCoord<Device>( fixture ) , result );
+
+    if ( result.error ) {
+      std::cout << "P[" << my_rank << ":" << global_size
+                << "] Fixture elem_node_coord"
+                << " success(" << result.success << ")"
+                << " error(" << result.error << ")"
+                << std::endl ;
+    }
+
+    // Check send/recv alignment
+
+
+  }
+}
+
+
+} /* namespace Example */
+} /* namespace Kokkos */
+
+#endif /* #ifndef KOKKOS_EXAMPLE_TESTFIXTURE_HPP */
+
diff --git a/lib/kokkos/example/global_2_local_ids/CMakeLists.txt b/lib/kokkos/example/global_2_local_ids/CMakeLists.txt
new file mode 100644
index 0000000000..9f32fe5802
--- /dev/null
+++ b/lib/kokkos/example/global_2_local_ids/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(SOURCES "")
+
+SET(SOURCES
+  G2L_Main.cpp 
+  )
+
+TRIBITS_ADD_EXECUTABLE(
+  global_2_local_ids
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  )
+
+
diff --git a/lib/kokkos/example/global_2_local_ids/G2L.hpp b/lib/kokkos/example/global_2_local_ids/G2L.hpp
new file mode 100644
index 0000000000..9023ae0426
--- /dev/null
+++ b/lib/kokkos/example/global_2_local_ids/G2L.hpp
@@ -0,0 +1,266 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#ifndef KOKKOS_GLOBAL_TO_LOCAL_IDS_HPP
+#define KOKKOS_GLOBAL_TO_LOCAL_IDS_HPP
+
+#include <Kokkos_Core.hpp>
+
+#include <Kokkos_UnorderedMap.hpp>
+
+#include <vector>
+#include <algorithm>
+#include <iomanip>
+
+#include <impl/Kokkos_Timer.hpp>
+
+// This test will simulate global ids
+
+namespace G2L {
+
+static const unsigned begin_id_size = 256u;
+static const unsigned end_id_size = 1u << 25;
+static const unsigned id_step = 2u;
+
+//use to help generate global ids
+union helper
+{
+  uint32_t word;
+  uint8_t byte[4];
+};
+
+
+//generate a unique global id from the local id
+template <typename Device>
+struct generate_ids
+{
+  typedef Device execution_space;
+  typedef typename execution_space::size_type size_type;
+  typedef Kokkos::View<uint32_t*,execution_space> local_id_view;
+
+  local_id_view local_2_global;
+
+  generate_ids( local_id_view & ids)
+    : local_2_global(ids)
+  {
+    Kokkos::parallel_for(local_2_global.size(), *this);
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(size_type i) const
+  {
+
+    helper x = {static_cast<uint32_t>(i)};
+
+    // shuffle the bytes of i to create a unique, semi-random global_id
+    x.word = ~x.word;
+
+    uint8_t tmp = x.byte[3];
+    x.byte[3] = x.byte[1];
+    x.byte[1] = tmp;
+
+    tmp = x.byte[2];
+    x.byte[2] = x.byte[0];
+    x.byte[0] = tmp;
+
+    local_2_global[i] = x.word;
+  }
+
+};
+
+// fill a map of global_id -> local_id
+template <typename Device>
+struct fill_map
+{
+  typedef Device execution_space;
+  typedef typename execution_space::size_type size_type;
+  typedef Kokkos::View<const uint32_t*,execution_space, Kokkos::MemoryRandomAccess> local_id_view;
+  typedef Kokkos::UnorderedMap<uint32_t,size_type,execution_space> global_id_view;
+
+  global_id_view global_2_local;
+  local_id_view local_2_global;
+
+  fill_map( global_id_view gIds, local_id_view lIds)
+    : global_2_local(gIds) , local_2_global(lIds)
+  {
+    Kokkos::parallel_for(local_2_global.size(), *this);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(size_type i) const
+  {
+    global_2_local.insert( local_2_global[i], i);
+  }
+
+};
+
+// check that the global id is found and that it maps to the local id
+template <typename Device>
+struct find_test
+{
+  typedef Device execution_space;
+  typedef typename execution_space::size_type size_type;
+  typedef Kokkos::View<const uint32_t*,execution_space, Kokkos::MemoryRandomAccess> local_id_view;
+  typedef Kokkos::UnorderedMap<const uint32_t, const size_type,execution_space> global_id_view;
+
+  global_id_view global_2_local;
+  local_id_view local_2_global;
+
+  typedef size_t value_type;
+
+  find_test( global_id_view gIds, local_id_view lIds, value_type & num_errors)
+    : global_2_local(gIds) , local_2_global(lIds)
+  {
+    Kokkos::parallel_reduce(local_2_global.size(), *this, num_errors);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void init(value_type & v) const
+  { v = 0; }
+
+  KOKKOS_INLINE_FUNCTION
+  void join(volatile value_type & dst, volatile value_type const & src) const
+  { dst += src; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(size_type i, value_type & num_errors) const
+  {
+    uint32_t index = global_2_local.find( local_2_global[i] );
+
+    if (  !global_2_local.valid_at(index)
+        || global_2_local.key_at(index) != local_2_global[i]
+        || global_2_local.value_at(index) != i)
+      ++num_errors;
+  }
+
+};
+
+// run test
+template <typename Device>
+size_t test_global_to_local_ids(unsigned num_ids, unsigned capacity, unsigned num_find_iterations)
+{
+
+  typedef Device execution_space;
+  typedef typename execution_space::size_type size_type;
+
+  typedef Kokkos::View<uint32_t*,execution_space> local_id_view;
+  typedef Kokkos::UnorderedMap<uint32_t,size_type,execution_space> global_id_view;
+
+  double elasped_time = 0;
+  Kokkos::Timer timer;
+
+  local_id_view local_2_global("local_ids", num_ids);
+  global_id_view global_2_local(capacity);
+
+  int shiftw = 15;
+
+  //create
+  elasped_time = timer.seconds();
+  std::cout << std::setw(shiftw) <<  "allocate: " <<  elasped_time << std::endl;
+  timer.reset();
+
+  // generate unique ids
+  {
+    generate_ids<Device> gen(local_2_global);
+  }
+
+  // generate
+  elasped_time = timer.seconds();
+  std::cout << std::setw(shiftw) << "generate: " <<  elasped_time << std::endl;
+  timer.reset();
+
+  {
+    fill_map<Device> fill(global_2_local, local_2_global);
+  }
+
+  // fill
+  elasped_time = timer.seconds();
+  std::cout << std::setw(shiftw) << "fill: " <<  elasped_time << std::endl;
+  timer.reset();
+
+
+  size_t num_errors = global_2_local.failed_insert();
+
+  if (num_errors == 0u) {
+    for (unsigned i=0; i<num_find_iterations; ++i)
+    {
+      find_test<Device> find(global_2_local, local_2_global,num_errors);
+    }
+
+    // find
+    elasped_time = timer.seconds();
+    std::cout << std::setw(shiftw) << "lookup: " <<  elasped_time << std::endl;
+  }
+  else {
+    std::cout << "    !!! Fill Failed !!!" << std::endl;
+  }
+
+  return num_errors;
+}
+
+template <typename Device>
+size_t run_test(unsigned num_ids, unsigned num_find_iterations)
+{
+  // expect to fail
+  unsigned capacity = (num_ids*2u)/3u;
+  std::cout << " 66% of needed capacity (should fail)" << std::endl;
+  test_global_to_local_ids<Device>(num_ids, capacity, num_find_iterations);
+
+  //should not fail
+  std::cout << " 100% of needed capacity" << std::endl;
+  capacity = num_ids;
+  size_t num_errors = test_global_to_local_ids<Device>(num_ids, capacity, num_find_iterations);
+
+  //should not fail
+  std::cout << " 150% of needed capacity" << std::endl;
+  capacity = (num_ids*3u)/2u;
+  num_errors += test_global_to_local_ids<Device>(num_ids, capacity, num_find_iterations);
+
+  return num_errors;
+}
+
+
+} // namespace G2L
+
+
+#endif //KOKKOS_GLOBAL_TO_LOCAL_IDS_HPP
+
diff --git a/lib/kokkos/example/global_2_local_ids/G2L_Main.cpp b/lib/kokkos/example/global_2_local_ids/G2L_Main.cpp
new file mode 100644
index 0000000000..171ed4b5f6
--- /dev/null
+++ b/lib/kokkos/example/global_2_local_ids/G2L_Main.cpp
@@ -0,0 +1,149 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#include <G2L.hpp>
+
+namespace G2L {
+
+size_t run_serial(unsigned num_ids, unsigned num_find_iterations)
+{
+#ifdef KOKKOS_HAVE_SERIAL
+  std::cout << "Serial" << std::endl;
+  return run_test<Kokkos::Serial>(num_ids,num_find_iterations);
+#else
+  return 0;
+#endif // KOKKOS_HAVE_SERIAL
+}
+
+size_t run_threads(unsigned num_ids, unsigned num_find_iterations)
+{
+#ifdef KOKKOS_HAVE_PTHREAD
+  std::cout << "Threads" << std::endl;
+  return run_test<Kokkos::Threads>(num_ids,num_find_iterations);
+#else
+  return 0;
+#endif
+}
+
+size_t run_openmp(unsigned num_ids, unsigned num_find_iterations)
+{
+#ifdef KOKKOS_HAVE_OPENMP
+  std::cout << "OpenMP" << std::endl;
+  return run_test<Kokkos::OpenMP>(num_ids,num_find_iterations);
+#else
+  return 0;
+#endif
+}
+
+size_t run_cuda(unsigned num_ids, unsigned num_find_iterations)
+{
+#ifdef KOKKOS_HAVE_CUDA
+  std::cout << "Cuda" << std::endl;
+  return run_test<Kokkos::Cuda>(num_ids,num_find_iterations);
+#else
+  return 0;
+#endif
+}
+
+} // namespace G2L
+
+
+int main(int argc, char *argv[])
+{
+  unsigned num_ids = 100000;
+  unsigned num_find_iterations = 1000;
+
+  if (argc == 3) {
+    num_ids = atoi(argv[1]);
+    num_find_iterations = atoi(argv[2]);
+  }
+  else if (argc != 1) {
+    std::cout << argv[0] << " num_ids num_find_iterations" << std::endl;
+    return 0;
+  }
+
+
+  // query the topology of the host
+  unsigned threads_count = 4 ;
+
+  if (Kokkos::hwloc::available()) {
+    threads_count = Kokkos::hwloc::get_available_numa_count() *
+                    Kokkos::hwloc::get_available_cores_per_numa() *
+                    Kokkos::hwloc::get_available_threads_per_core();
+
+  }
+
+  std::cout << "Threads: " << threads_count << std::endl;
+  std::cout << "Number of ids: " << num_ids << std::endl;
+  std::cout << "Number of find iterations: " << num_find_iterations << std::endl;
+
+  size_t num_errors = 0;
+
+  num_errors += G2L::run_serial(num_ids,num_find_iterations);
+
+#ifdef KOKKOS_HAVE_CUDA
+  Kokkos::HostSpace::execution_space::initialize(threads_count);
+  Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice(0) );
+  num_errors += G2L::run_cuda(num_ids,num_find_iterations);
+  Kokkos::Cuda::finalize();
+  Kokkos::HostSpace::execution_space::finalize();
+#endif
+
+#ifdef KOKKOS_HAVE_PTHREAD
+  Kokkos::Threads::initialize( threads_count );
+  num_errors += G2L::run_threads(num_ids,num_find_iterations);
+  Kokkos::Threads::finalize();
+#endif
+
+#ifdef KOKKOS_HAVE_OPENMP
+  Kokkos::OpenMP::initialize( threads_count );
+  num_errors += G2L::run_openmp(num_ids,num_find_iterations);
+  Kokkos::OpenMP::finalize();
+#endif
+
+
+  return num_errors;
+}
+
diff --git a/lib/kokkos/example/global_2_local_ids/Makefile b/lib/kokkos/example/global_2_local_ids/Makefile
new file mode 100644
index 0000000000..bf8fbea3e0
--- /dev/null
+++ b/lib/kokkos/example/global_2_local_ids/Makefile
@@ -0,0 +1,53 @@
+KOKKOS_PATH ?= ../..
+
+MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
+SRC_DIR := $(dir $(MAKEFILE_PATH))
+
+SRC = $(wildcard $(SRC_DIR)/*.cpp)
+OBJ = $(SRC:$(SRC_DIR)/%.cpp=%.o)
+
+#SRC = $(wildcard *.cpp)
+#OBJ = $(SRC:%.cpp=%.o)
+
+default: build
+	echo "Start Build"
+
+# use installed Makefile.kokkos
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = $(NVCC_WRAPPER)
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS = 
+EXE = $(addsuffix .cuda, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "Cuda,OpenMP"
+#KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS =  
+EXE = $(addsuffix .host, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "OpenMP"
+#KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+LIB =
+
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: 
+	rm -f *.a *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:$(SRC_DIR)/%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
diff --git a/lib/kokkos/example/grow_array/CMakeLists.txt b/lib/kokkos/example/grow_array/CMakeLists.txt
new file mode 100644
index 0000000000..d9ff170492
--- /dev/null
+++ b/lib/kokkos/example/grow_array/CMakeLists.txt
@@ -0,0 +1,14 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(SOURCES "")
+
+FILE(GLOB SOURCES *.cpp)
+
+TRIBITS_ADD_EXECUTABLE(
+  grow_array
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  )
+
diff --git a/lib/kokkos/example/grow_array/Makefile b/lib/kokkos/example/grow_array/Makefile
new file mode 100644
index 0000000000..bf8fbea3e0
--- /dev/null
+++ b/lib/kokkos/example/grow_array/Makefile
@@ -0,0 +1,53 @@
+KOKKOS_PATH ?= ../..
+
+MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
+SRC_DIR := $(dir $(MAKEFILE_PATH))
+
+SRC = $(wildcard $(SRC_DIR)/*.cpp)
+OBJ = $(SRC:$(SRC_DIR)/%.cpp=%.o)
+
+#SRC = $(wildcard *.cpp)
+#OBJ = $(SRC:%.cpp=%.o)
+
+default: build
+	echo "Start Build"
+
+# use installed Makefile.kokkos
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = $(NVCC_WRAPPER)
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS = 
+EXE = $(addsuffix .cuda, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "Cuda,OpenMP"
+#KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS =  
+EXE = $(addsuffix .host, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "OpenMP"
+#KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+LIB =
+
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: 
+	rm -f *.a *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:$(SRC_DIR)/%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
diff --git a/lib/kokkos/example/grow_array/grow_array.hpp b/lib/kokkos/example/grow_array/grow_array.hpp
new file mode 100644
index 0000000000..9daef1a4b0
--- /dev/null
+++ b/lib/kokkos/example/grow_array/grow_array.hpp
@@ -0,0 +1,257 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef EXAMPLE_GROW_ARRAY
+#define EXAMPLE_GROW_ARRAY
+
+#include <stdlib.h>
+
+#include <Kokkos_Core.hpp>
+
+#include <algorithm>
+
+#if defined(KOKKOS_HAVE_CUDA)
+#include <thrust/device_ptr.h>
+#include <thrust/sort.h>
+#endif
+
+namespace Example {
+
+//----------------------------------------------------------------------------
+
+template< class ExecSpace >
+struct SortView {
+
+  template< typename ValueType >
+  SortView( const Kokkos::View<ValueType*,ExecSpace> v , int begin , int end )
+    {
+      std::sort( v.ptr_on_device() + begin , v.ptr_on_device() + end );
+    }
+};
+
+#if defined(KOKKOS_HAVE_CUDA)
+template<>
+struct SortView< Kokkos::Cuda > {
+  template< typename ValueType >
+  SortView( const Kokkos::View<ValueType*,Kokkos::Cuda> v , int begin , int end )
+    {
+      thrust::sort( thrust::device_ptr<ValueType>( v.ptr_on_device() + begin )
+                  , thrust::device_ptr<ValueType>( v.ptr_on_device() + end ) );
+    }
+};
+#endif
+
+
+
+//----------------------------------------------------------------------------
+
+template< class ExecSpace >
+struct GrowArrayFunctor {
+
+  typedef ExecSpace  execution_space ;
+
+  enum { SHIFT = sizeof(int) == 8 ? 6 : 5 }; // 8 or 4 byte int
+  enum { MASK  = ( 1 << SHIFT ) - 1 };
+
+  const Kokkos::View<int*,ExecSpace>  m_search_flags ; // bit flags for values to append
+  const Kokkos::View<int*,ExecSpace>  m_search_array ; // array to append values
+  const Kokkos::View<int,ExecSpace>   m_search_count ; // offset
+  const int m_search_total ;
+  const int m_search_team_chunk ;
+
+  GrowArrayFunctor( int array_length , int search_length , int print = 1 )
+    : m_search_flags( "flags" , ( search_length + MASK ) >> SHIFT ) // One bit per search entry
+    , m_search_array( "array" , array_length )
+    , m_search_count( "count" )
+    , m_search_total( search_length )
+    , m_search_team_chunk( 2048 )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  bool flag_is_set( const int index ) const
+    {
+      // 64 or 32 bit integer:
+
+      const int j = index >> SHIFT ; // which integer flag
+      const int k = 1 << ( index & MASK ); // which bit in that integer
+      const int s = ( j < int(m_search_flags.dimension_0()) ) && ( 0 != ( m_search_flags(j) & k ) );
+
+      return s ;
+    }
+
+  typedef typename Kokkos::TeamPolicy<ExecSpace>::member_type team_member ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const team_member & member ) const
+    {
+      enum { LOCAL_BUFFER_LENGTH = 16 };
+
+      int local_buffer[ LOCAL_BUFFER_LENGTH ] ;
+      int local_count = 0 ;
+
+      // Each team searches 'm_search_team_chunk' indices.
+      // The threads of a team must iterate together because all
+      // threads in the team must call 'team_scan' to prevent deadlock in the team.
+
+            int search_team_begin = member.league_rank() * m_search_team_chunk ;
+      const int search_team_end   = search_team_begin + m_search_team_chunk ;
+
+      int k = 0 ;
+
+      while ( search_team_begin < search_team_end ) {
+
+        // This iteration searches [ search_team_begin .. search_team_begin + member.team_size() ]
+        const int thread_search_index = search_team_begin + member.team_rank();
+
+        // If this thread's search index is in the range
+        // and the flag is set, push into this thread's local buffer.
+        if ( thread_search_index < m_search_total && flag_is_set(thread_search_index) ) {
+          local_buffer[ local_count ] = thread_search_index ;
+          ++local_count ;
+        }
+
+        // Move the team's search range forward
+        search_team_begin += member.team_size(); // Striding team by team size
+
+        // Count number of times a thread's buffer might have grown:
+        ++k ;
+
+        // Write buffer if end of search or a thread might have filled its buffer.
+        if ( k == LOCAL_BUFFER_LENGTH /* A thread in my team might have filled its buffer */ ||
+             ! ( search_team_begin < search_team_end ) /* Team is at the end of its search */ ) {
+
+          // Team's exclusive scan of threads' contributions, with global offset.
+          // This thread writes its buffer into [ team_offset .. team_offset + local_count )
+          const int team_offset = member.team_scan( local_count , & *m_search_count );
+
+          // Copy locally buffered entries into global array:
+          for ( int i = 0 ; i < local_count ; ++i ) {
+            m_search_array( team_offset + i ) = local_buffer[i] ;
+          }
+
+          k = 0 ;
+          local_count = 0 ;
+        }
+      }
+    }
+};
+
+
+template< class ExecSpace >
+void grow_array( int array_length , int search_length , int print = 1 )
+{
+  typedef GrowArrayFunctor< ExecSpace > FunctorType ;
+
+  FunctorType functor( array_length , search_length , print );
+
+  typename Kokkos::View<int,ExecSpace>::HostMirror  count = Kokkos::create_mirror_view( functor.m_search_count );
+  typename Kokkos::View<int*,ExecSpace>::HostMirror flags = Kokkos::create_mirror_view( functor.m_search_flags );
+
+  // Set at most 'array_length' random bits over the search length.
+  for ( int i = 0 ; i < array_length ; ++i ) {
+    // 'lrand48()' generates random number between [0..2^31]
+    // index = ( lrand48() * search_length ) / ( 2^31 )
+    const long int index = ( lrand48() * search_length ) >> 31 ;
+    // set the bit within the flags:
+    flags( index >> FunctorType::SHIFT ) |= ( 1 << ( index & FunctorType::MASK ) );
+  }
+
+  Kokkos::deep_copy( functor.m_search_flags , flags );
+
+  // Each team works on 'functor.m_search_team_chunk' span of the search_length
+  Kokkos::TeamPolicy< ExecSpace >
+    work( /* #teams */ ( search_length + functor.m_search_team_chunk - 1 ) / functor.m_search_team_chunk
+        , /* threads/team */ Kokkos::TeamPolicy< ExecSpace >::team_size_max( functor ) );
+
+  // Fill array:
+  Kokkos::parallel_for( work , functor );
+
+  // How much was filled:
+  Kokkos::deep_copy( count , functor.m_search_count );
+
+  // Sort array:
+  SortView< ExecSpace >( functor.m_search_array , 0 , *count );
+
+  // Mirror the results:
+  typename Kokkos::View<int*,ExecSpace>::HostMirror results = Kokkos::create_mirror_view( functor.m_search_array );
+  Kokkos::deep_copy( results , functor.m_search_array );
+
+  // Verify results:
+  int result_error_count = 0 ;
+  int flags_error_count = 0 ;
+  for ( int i = 0 ; i < *count ; ++i ) {
+    const int index = results(i);
+    const int entry = index >> FunctorType::SHIFT ;
+    const int bit   = 1 << ( index & FunctorType::MASK );
+    const bool flag = 0 != ( flags( entry ) & bit );
+    if ( ! flag ) {
+      if ( print ) std::cerr << "result( " << i << " : " << index << " )";
+      ++result_error_count ;
+    }
+    flags( entry ) &= ~bit ; // Clear that verified bit
+  }
+
+  for ( int i = 0 ; i < int(flags.dimension_0()) ; ++i ) {
+    // If any uncleared bits then an error
+    if ( flags(i) ) {
+      if ( print ) std::cerr << "flags( " << i << " : " << flags(i) << " )" ;
+      ++flags_error_count ;
+    }
+  }
+
+  if ( result_error_count || flags_error_count ) {
+    std::cerr << std::endl << "Example::GrowArrayFunctor( " << array_length
+              << " , " << search_length
+              << " ) result_error_count( " << result_error_count << " )"
+              << " ) flags_error_count( " << flags_error_count << " )"
+              << std::endl ;
+  }
+}
+
+
+} // namespace Example
+
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef EXAMPLE_GROW_ARRAY */
+
diff --git a/lib/kokkos/example/grow_array/main.cpp b/lib/kokkos/example/grow_array/main.cpp
new file mode 100644
index 0000000000..4693aa3af4
--- /dev/null
+++ b/lib/kokkos/example/grow_array/main.cpp
@@ -0,0 +1,110 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <iostream>
+#include <sstream>
+
+#include <Kokkos_Core.hpp>
+
+#include <grow_array.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+int main( int argc , char ** argv )
+{
+  int num_threads = 4 ;
+  int use_numa = 1 ;
+  int use_core = 1 ;
+  int length_array  = 1000000 ;
+  int span_values = 100000000 ;
+
+
+  if ( Kokkos::hwloc::available() ) {
+    use_numa = Kokkos::hwloc::get_available_numa_count();
+    use_core = Kokkos::hwloc::get_available_cores_per_numa() - 1 ;
+    num_threads = use_numa * use_core * Kokkos::hwloc::get_available_threads_per_core();
+  }
+
+#if defined( KOKKOS_HAVE_SERIAL )
+  {
+    std::cout << "Kokkos::Serial" << std::endl ;
+    // The Serial device accepts these arguments, though it may ignore them.
+    Kokkos::Serial::initialize( num_threads , use_numa , use_core );
+    Example::grow_array< Kokkos::Serial >( length_array , span_values );
+    Kokkos::Serial::finalize ();
+  }
+#endif // defined( KOKKOS_HAVE_SERIAL )
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+  {
+    std::cout << "Kokkos::Threads" << std::endl ;
+    Kokkos::Threads::initialize( num_threads , use_numa , use_core );
+    Example::grow_array< Kokkos::Threads >( length_array , span_values );
+    Kokkos::Threads::finalize();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_OPENMP )
+  {
+    std::cout << "Kokkos::OpenMP" << std::endl ;
+    Kokkos::OpenMP::initialize( num_threads , use_numa , use_core );
+    Example::grow_array< Kokkos::OpenMP >( length_array , span_values );
+    Kokkos::OpenMP::finalize();
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_CUDA )
+  {
+    std::cout << "Kokkos::Cuda" << std::endl ;
+    Kokkos::HostSpace::execution_space::initialize(1);
+    Kokkos::Cuda::initialize();
+    Example::grow_array< Kokkos::Cuda >( length_array , span_values );
+    Kokkos::Cuda::finalize();
+    Kokkos::HostSpace::execution_space::finalize();
+  }
+#endif
+
+  return 0 ;
+}
+
diff --git a/lib/kokkos/example/ichol/Makefile b/lib/kokkos/example/ichol/Makefile
new file mode 100644
index 0000000000..57e972f042
--- /dev/null
+++ b/lib/kokkos/example/ichol/Makefile
@@ -0,0 +1,63 @@
+SCOTCH_PATH = /home/hcedwar/scotch/6.0.0
+KOKKOS_PATH = ../..
+
+vpath %.cpp ${KOKKOS_PATH}/example/ichol/src ${KOKKOS_PATH}/example/ichol/example 
+
+EXAMPLE_HEADERS = $(wildcard $(KOKKOS_PATH)/example/ichol/src/*.hpp ${KOKKOS_PATH}/example/ichol/example/*.hpp )
+
+default: build_all
+	echo "End Build"
+        
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifeq ($(KOKKOS_INTERNAL_USE_CUDA), 1)
+	CXX = $(NVCC_WRAPPER)
+	CXXFLAGS ?= -O3
+	LINK = $(CXX)
+	LDFLAGS ?= -lpthread
+else
+	CXX ?= g++
+	CXXFLAGS ?= -O3
+	LINK ?= $(CXX)
+	LDFLAGS ?= -lpthread
+endif
+
+KOKKOS_CXXFLAGS +=	\
+	-I${KOKKOS_PATH}/example/ichol/src	\
+	-I${KOKKOS_PATH}/example/ichol/example	\
+	-I${SCOTCH_PATH}/include
+
+EXE_EXAMPLE_ICHOL_THREADS = KokkosExample_ichol_threads
+OBJ_EXAMPLE_ICHOL_THREADS = example_chol_performance_device_pthread.o
+
+EXE_EXAMPLE_ICHOL_CUDA = KokkosExample_ichol_cuda
+OBJ_EXAMPLE_ICHOL_CUDA = example_chol_performance_device_cuda.o
+
+TARGETS = $(EXE_EXAMPLE_ICHOL_THREADS) $(EXE_EXAMPLE_ICHOL_CUDA)
+
+#TEST_TARGETS =
+
+$(EXE_EXAMPLE_ICHOL_THREADS) : $(OBJ_EXAMPLE_ICHOL_THREADS) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) \
+	$(OBJ_EXAMPLE_ICHOL_THREADS) $(KOKKOS_LIBS) $(LIB) \
+	-L${SCOTCH_PATH}/lib -lscotch  -lscotcherr  -lscotcherrexit \
+	-o $(EXE_EXAMPLE_ICHOL_THREADS)
+
+$(EXE_EXAMPLE_ICHOL_CUDA) : $(OBJ_EXAMPLE_ICHOL_CUDA) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LDFLAGS) $(EXTRA_PATH) \
+	$(OBJ_EXAMPLE_ICHOL_CUDA) $(KOKKOS_LIBS) $(LIB) \
+	-L${SCOTCH_PATH}/lib -lscotch  -lscotcherr  -lscotcherrexit \
+	-o $(EXE_EXAMPLE_ICHOL_CUDA)
+
+build_all : $(TARGETS)
+
+test : build_all
+
+clean: kokkos-clean
+	rm -f *.o $(TARGETS)
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS) $(EXAMPLE_HEADERS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
diff --git a/lib/kokkos/example/ichol/example/example_chol_performance_device.hpp b/lib/kokkos/example/ichol/example/example_chol_performance_device.hpp
new file mode 100644
index 0000000000..ca819e4f97
--- /dev/null
+++ b/lib/kokkos/example/ichol/example/example_chol_performance_device.hpp
@@ -0,0 +1,240 @@
+#pragma once
+#ifndef __EXAMPLE_CHOL_PERFORMANCE_DEVICE_HPP__
+#define __EXAMPLE_CHOL_PERFORMANCE_DEVICE_HPP__
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Timer.hpp>
+
+#include "util.hpp"
+
+#include "crs_matrix_base.hpp"
+#include "crs_matrix_view.hpp"
+#include "crs_row_view.hpp"
+
+#include "graph_helper_scotch.hpp"
+#include "symbolic_factor_helper.hpp"
+#include "crs_matrix_helper.hpp"
+
+#include "task_view.hpp"
+
+#include "task_factory.hpp"
+
+#include "chol.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<typename ValueType,
+           typename OrdinalType,
+           typename SizeType = OrdinalType,
+           typename SpaceType = void>
+  int exampleCholPerformanceDevice(const string file_input,
+                                   const int treecut,
+                                   const int prunecut,
+                                   const int seed,
+                                   const int nthreads,
+                                   const int max_task_dependence,
+                                   const int max_concurrency,
+                                   const int team_size,
+                                   const int fill_level,
+                                   const int league_size,
+                                   const bool skip_serial,
+                                   const bool verbose) {
+    typedef ValueType   value_type;
+    typedef OrdinalType ordinal_type;
+    typedef SizeType    size_type;
+    typedef typename
+       Kokkos::Impl::is_space< SpaceType >::host_mirror_space::execution_space
+         HostSpaceType ;
+
+    typedef TaskFactory<Kokkos::Experimental::TaskPolicy<SpaceType>,
+      Kokkos::Experimental::Future<int,SpaceType> > TaskFactoryType;
+
+    typedef CrsMatrixBase<value_type,ordinal_type,size_type,SpaceType>
+      CrsMatrixBaseType;
+
+    typedef CrsMatrixBase<value_type,ordinal_type,size_type,HostSpaceType>
+      CrsMatrixBaseHostType;
+
+    typedef Kokkos::MemoryUnmanaged MemoryUnmanaged ;
+
+    typedef CrsMatrixBase<value_type,ordinal_type,size_type,SpaceType,MemoryUnmanaged >
+      CrsMatrixNestedType;
+
+
+    typedef GraphHelper_Scotch<CrsMatrixBaseHostType> GraphHelperType;
+    typedef SymbolicFactorHelper<CrsMatrixBaseHostType> SymbolicFactorHelperType;
+
+    typedef CrsMatrixView<CrsMatrixNestedType> CrsMatrixViewType;
+    typedef TaskView<CrsMatrixViewType,TaskFactoryType> CrsTaskViewType;
+
+    typedef CrsMatrixBase<CrsTaskViewType,ordinal_type,size_type,SpaceType> CrsHierMatrixBaseType;
+
+    typedef CrsMatrixView<CrsHierMatrixBaseType> CrsHierMatrixViewType;
+    typedef TaskView<CrsHierMatrixViewType,TaskFactoryType> CrsHierTaskViewType;
+
+    int r_val = 0;
+
+    Kokkos::Timer timer;
+    double
+      t_import = 0.0,
+      t_reorder = 0.0,
+      t_symbolic = 0.0,
+      t_flat2hier = 0.0,
+      t_factor_task = 0.0;
+
+    cout << "CholPerformanceDevice:: import input file = " << file_input << endl;
+    CrsMatrixBaseHostType AA("AA");
+    {
+      timer.reset();
+
+      ifstream in;
+      in.open(file_input);
+      if (!in.good()) {
+        cout << "Failed in open the file: " << file_input << endl;
+        return ++r_val;
+      }
+      AA.importMatrixMarket(in);
+
+      t_import = timer.seconds();
+
+      if (verbose) {
+        AA.showMe( std::cout );
+        std::cout << endl;
+      }
+    }
+    cout << "CholPerformanceDevice:: import input file::time = " << t_import << endl;
+
+    cout << "CholPerformanceDevice:: reorder the matrix" << endl;
+    CrsMatrixBaseHostType PA("Permuted AA");
+
+    // '*_UU' is the permuted base upper triangular matrix
+    CrsMatrixBaseHostType host_UU("host_UU");
+    CrsMatrixBaseType     device_UU("UU");
+    CrsHierMatrixBaseType device_HU("HU");;
+
+    // typename CrsMatrixBaseHostType host_UU("host_UU");
+
+    {
+      typename GraphHelperType::size_type_array rptr("Graph::RowPtrArray", AA.NumRows() + 1);
+      typename GraphHelperType::ordinal_type_array cidx("Graph::ColIndexArray", AA.NumNonZeros());
+
+      AA.convertGraph(rptr, cidx);
+      GraphHelperType S("ScotchHelper",
+                        AA.NumRows(),
+                        rptr,
+                        cidx,
+                        seed);
+      {
+        timer.reset();
+
+        S.computeOrdering(treecut, 0);
+        S.pruneTree(prunecut);
+
+        PA.copy(S.PermVector(), S.InvPermVector(), AA);
+
+        t_reorder = timer.seconds();
+
+        if (verbose) {
+          S.showMe( std::cout );
+          std::cout << std::endl ;
+          PA.showMe( std::cout );
+          std::cout << std::endl ;
+        }
+      }
+
+      // Symbolic factorization adds non-zero entries
+      // for factorization levels.
+      // Runs on the host process and currently requires std::sort.
+
+      cout << "CholPerformanceDevice:: reorder the matrix::time = " << t_reorder << endl;
+      {
+        SymbolicFactorHelperType F(PA, league_size);
+        timer.reset();
+        F.createNonZeroPattern(fill_level, Uplo::Upper, host_UU);
+        t_symbolic = timer.seconds();
+        cout << "CholPerformanceDevice:: AA (nnz) = " << AA.NumNonZeros() << ", host_UU (nnz) = " << host_UU.NumNonZeros() << endl;
+
+        if (verbose) {
+          F.showMe( std::cout );
+          std::cout << std::endl ;
+          host_UU.showMe( std::cout );
+          std::cout << std::endl ;
+        }
+      }
+      cout << "CholPerformanceDevice:: symbolic factorization::time = " << t_symbolic << endl;
+
+    //----------------------------------------------------------------------
+    // Allocate device_UU conformal to host_UU 
+    // and deep_copy host_UU arrays to device_UU arrays.
+    // Set up device_HU referencing blocks of device_UU
+
+      {
+        timer.reset();
+
+        device_UU.copy( host_UU );
+
+        CrsMatrixHelper::flat2hier(Uplo::Upper, device_UU, device_HU,
+                                   S.NumBlocks(),
+                                   S.RangeVector(),
+                                   S.TreeVector());
+
+        // Filling non-zero block matrixes' row ranges within block view.
+        // This is performed entirely in the 'device_HU' space.
+
+        CrsMatrixHelper::fillRowViewArray( device_HU );
+
+        t_flat2hier = timer.seconds();
+
+        cout << "CholPerformanceDevice:: Hier (dof, nnz) = " << device_HU.NumRows() << ", " << device_HU.NumNonZeros() << endl;
+      }
+      cout << "CholPerformanceDevice:: copy base matrix and construct hierarchical matrix::time = " << t_flat2hier << endl;
+    }
+
+    cout << "CholPerformanceDevice:: max concurrency = " << max_concurrency << endl;
+
+    const size_t max_task_size = 4*sizeof(CrsTaskViewType)+128;
+    cout << "CholPerformanceDevice:: max task size   = " << max_task_size << endl;
+
+    //----------------------------------------------------------------------
+    // From here onward all work is on the device.
+    //----------------------------------------------------------------------
+
+    {
+      typename TaskFactoryType::policy_type policy(max_concurrency,
+                                                   max_task_size,
+                                                   max_task_dependence,
+                                                   team_size);
+
+      cout << "CholPerformanceDevice:: ByBlocks factorize the matrix:: team_size = " << team_size << endl;
+      CrsHierTaskViewType H( device_HU );
+      {
+        timer.reset();
+        {
+          // auto future = policy.proc_create_team(Chol<Uplo::Upper,AlgoChol::ByBlocks>::
+          auto future = policy.proc_create_team(Chol<Uplo::Upper,AlgoChol::ByBlocks,Variant::Two>::
+                                                TaskFunctor<CrsHierTaskViewType>(policy,H), 0);
+          policy.spawn(future);
+          Kokkos::Experimental::wait(policy);
+        }
+        t_factor_task += timer.seconds();
+
+        cout << "CholPerformanceDevice:: policy.allocated_task_count = "
+             << policy.allocated_task_count()
+             << endl ;
+
+        if (verbose) {
+          host_UU.copy( device_UU );
+          host_UU.showMe( std::cout );
+          std::cout << endl;
+        }
+      }
+      cout << "CholPerformanceDevice:: ByBlocks factorize the matrix::time = " << t_factor_task << endl;
+    }
+
+    return r_val;
+  }
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/example/example_chol_performance_device_cuda.cpp b/lib/kokkos/example/ichol/example/example_chol_performance_device_cuda.cpp
new file mode 100644
index 0000000000..3a0df586b5
--- /dev/null
+++ b/lib/kokkos/example/ichol/example/example_chol_performance_device_cuda.cpp
@@ -0,0 +1,70 @@
+#include <Kokkos_Core.hpp>
+
+#include <Cuda/Kokkos_Cuda_TaskPolicy.hpp>
+
+using namespace std;
+
+typedef double value_type;
+typedef int    ordinal_type;
+typedef int    size_type;
+
+#include "example_chol_performance_device.hpp"
+
+using namespace Tacho;
+
+int main (int argc, char *argv[]) {
+
+  string file_input = "test.mtx";                                                                             
+  int nthreads = 1;                                                                                           
+  int max_task_dependence = 3;                                                                                
+  int max_concurrency = 1024;                                                                                 
+  int team_size = 1;                                                                                          
+  int fill_level = 0;
+  int treecut = 0;
+  int prunecut = 0;
+  int seed = 0;
+  int league_size = 1;                                                                                        
+  bool verbose = false;                                                                                       
+  for (int i=0;i<argc;++i) {                                                                                  
+    if ((strcmp(argv[i],"--file-input")         ==0)) { file_input          = argv[++i];       continue;}     
+    if ((strcmp(argv[i],"--nthreads")           ==0)) { nthreads            = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--max-task-dependence")==0)) { max_task_dependence = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--max-concurrency")    ==0)) { max_concurrency     = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--team-size")          ==0)) { team_size           = atoi(argv[++i]); continue;}     
+
+    if ((strcmp(argv[i],"--fill-level")         ==0)) { fill_level          = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--league-size")        ==0)) { league_size         = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--treecut")            ==0)) { treecut             = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--prunecut")           ==0)) { prunecut            = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--seed")               ==0)) { seed                = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--enable-verbose")     ==0)) { verbose             = true;            continue;}     
+  }                                                                                                           
+
+  int r_val = 0;
+  {
+    typedef Kokkos::Cuda exec_space;
+
+    Kokkos::DefaultHostExecutionSpace::initialize(nthreads);
+
+    exec_space::initialize();
+    exec_space::print_configuration(cout, true);
+
+    r_val = exampleCholPerformanceDevice
+      <value_type,ordinal_type,size_type,exec_space>
+      (file_input,
+       treecut,
+       prunecut,
+       seed,
+       nthreads,
+       max_task_dependence, max_concurrency, team_size,
+       fill_level, league_size,
+       (nthreads != 1), // skip_serial
+       verbose);
+
+    exec_space::finalize();
+
+    Kokkos::DefaultHostExecutionSpace::finalize();
+  }
+
+  return r_val;
+}
diff --git a/lib/kokkos/example/ichol/example/example_chol_performance_device_pthread.cpp b/lib/kokkos/example/ichol/example/example_chol_performance_device_pthread.cpp
new file mode 100644
index 0000000000..68f520cf66
--- /dev/null
+++ b/lib/kokkos/example/ichol/example/example_chol_performance_device_pthread.cpp
@@ -0,0 +1,67 @@
+#include <Kokkos_Core.hpp>
+
+#include <Kokkos_Threads.hpp>
+#include <Threads/Kokkos_Threads_TaskPolicy.hpp>
+
+using namespace std;
+
+typedef double value_type;
+typedef int    ordinal_type;
+typedef int    size_type;
+
+typedef Kokkos::Threads exec_space;
+
+#include "example_chol_performance_device.hpp"
+
+using namespace Tacho;
+
+int main (int argc, char *argv[]) {
+
+  string file_input = "test.mtx";                                                                             
+  int nthreads = 1;                                                                                           
+  int max_task_dependence = 3;                                                                                
+  int max_concurrency = 1024;                                                                                 
+  int team_size = 1;                                                                                          
+  int fill_level = 0;
+  int treecut = 0;
+  int prunecut = 0;
+  int seed = 0;
+  int league_size = 1;                                                                                        
+  bool verbose = false;                                                                                       
+  for (int i=0;i<argc;++i) {                                                                                  
+    if ((strcmp(argv[i],"--file-input")         ==0)) { file_input          = argv[++i];       continue;}     
+    if ((strcmp(argv[i],"--nthreads")           ==0)) { nthreads            = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--max-task-dependence")==0)) { max_task_dependence = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--max-concurrency")    ==0)) { max_concurrency     = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--team-size")          ==0)) { team_size           = atoi(argv[++i]); continue;}     
+
+    if ((strcmp(argv[i],"--fill-level")         ==0)) { fill_level          = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--league-size")        ==0)) { league_size         = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--treecut")            ==0)) { treecut             = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--prunecut")           ==0)) { prunecut            = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--seed")               ==0)) { seed                = atoi(argv[++i]); continue;}     
+    if ((strcmp(argv[i],"--enable-verbose")     ==0)) { verbose             = true;            continue;}     
+  }                                                                                                           
+
+  int r_val = 0;
+  {
+    exec_space::initialize(nthreads);
+    exec_space::print_configuration(cout, true);
+
+    r_val = exampleCholPerformanceDevice
+      <value_type,ordinal_type,size_type,exec_space>
+      (file_input,
+       treecut,
+       prunecut,
+       seed,
+       nthreads,
+       max_task_dependence, max_concurrency, team_size,
+       fill_level, league_size,
+       (nthreads != 1), // skip_serial
+       verbose);
+
+    exec_space::finalize();
+  }
+
+  return r_val;
+}
diff --git a/lib/kokkos/example/ichol/src/chol.hpp b/lib/kokkos/example/ichol/src/chol.hpp
new file mode 100644
index 0000000000..e8aa4e9189
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/chol.hpp
@@ -0,0 +1,92 @@
+#pragma once
+#ifndef __CHOL_HPP__
+#define __CHOL_HPP__
+
+/// \file chol.hpp
+/// \brief Incomplete Cholesky factorization front interface.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+#include "control.hpp"
+#include "partition.hpp"
+
+namespace Tacho { 
+
+  using namespace std;
+
+  // tasking interface
+  // * default behavior is for non-by-blocks tasks
+  // * control is only used for by-blocks algorithms
+  // ===============================================
+  template<int ArgUplo, int ArgAlgo, 
+           int ArgVariant = Variant::One,                  
+           template<int,int> class ControlType = Control>  
+  class Chol {
+  public:
+    
+    // function interface
+    // ==================
+    template<typename ExecViewType>
+    KOKKOS_INLINE_FUNCTION
+    static int invoke(typename ExecViewType::policy_type &policy, 
+                      const typename ExecViewType::policy_type::member_type &member, 
+                      typename ExecViewType::matrix_type &A);
+
+    // task-data parallel interface
+    // ============================
+    template<typename ExecViewType>
+    class TaskFunctor {
+    public:
+      typedef typename ExecViewType::policy_type policy_type;
+      typedef typename policy_type::member_type member_type;
+      typedef int value_type;
+      
+    private:
+      typename ExecViewType::matrix_type _A;
+      
+      policy_type _policy;
+      
+    public:
+      KOKKOS_INLINE_FUNCTION
+      TaskFunctor(const policy_type & P ,
+                  const typename ExecViewType::matrix_type & A)
+        : _A(A),
+          _policy(P)
+      { } 
+      
+      string Label() const { return "Chol"; }
+      
+      // task execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(value_type &r_val) {
+        r_val = Chol::invoke<ExecViewType>(_policy, _policy.member_single(), _A);
+      }
+
+      // task-data execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(const member_type &member, value_type &r_val) {
+
+        const int result = Chol::invoke<ExecViewType>(_policy, member, _A);
+
+        if ( 0 == member.team_rank() ) { r_val = result ; }
+
+      }
+
+    };
+
+  };
+}
+
+
+// unblocked version blas operations
+#include "scale.hpp"
+
+// blocked version blas operations
+#include "gemm.hpp"
+#include "trsm.hpp"
+#include "herk.hpp"
+
+// cholesky
+#include "chol_u.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/chol_u.hpp b/lib/kokkos/example/ichol/src/chol_u.hpp
new file mode 100644
index 0000000000..0465ef8f35
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/chol_u.hpp
@@ -0,0 +1,23 @@
+#pragma once
+#ifndef __CHOL_U_HPP__
+#define __CHOL_U_HPP__
+
+/// \file chol_u.hpp
+/// \brief Upper Cholesky factorization variations
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+// testing task-data parallelism
+// #include "chol_u_unblocked_dummy.hpp"
+
+// flame style implementation
+//#include "chol_unblocked.hpp"  
+//#include "chol_u_blocked.hpp"
+
+// triple for loop
+#include "chol_u_unblocked_opt1.hpp"
+#include "chol_u_unblocked_opt2.hpp"
+
+// partitioned block algorithms: see control.hpp
+#include "chol_u_right_look_by_blocks.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/chol_u_right_look_by_blocks.hpp b/lib/kokkos/example/ichol/src/chol_u_right_look_by_blocks.hpp
new file mode 100644
index 0000000000..e21bafa9f1
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/chol_u_right_look_by_blocks.hpp
@@ -0,0 +1,394 @@
+#pragma once
+#ifndef __CHOL_U_RIGHT_LOOK_BY_BLOCKS_HPP__
+#define __CHOL_U_RIGHT_LOOK_BY_BLOCKS_HPP__
+
+/// \file chol_u_right_look_by_blocks.hpp
+/// \brief Cholesky factorization by-blocks
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+/// The Partitioned-Block Matrix (PBM) is sparse and a block itself is a view of a sparse matrix. 
+/// The algorithm generates tasks with a given sparse block matrix structure.
+
+// basic utils
+#include "util.hpp"
+#include "control.hpp"
+#include "partition.hpp"
+
+namespace Tacho { 
+  
+  using namespace std;
+
+  template< typename CrsTaskViewType >
+  KOKKOS_INLINE_FUNCTION
+  int releaseFutures( typename CrsTaskViewType::matrix_type & A )
+    {
+      typedef typename CrsTaskViewType::ordinal_type      ordinal_type;
+      typedef typename CrsTaskViewType::row_view_type     row_view_type;
+      typedef typename CrsTaskViewType::future_type       future_type;
+      
+      row_view_type a(A,0);
+      
+      const ordinal_type nnz = a.NumNonZeros();
+
+      for (ordinal_type j=0;j<nnz;++j) {
+        a.Value(j).setFuture( future_type() );
+      }
+
+      return nnz ;
+    }
+  
+  // ========================================
+  // detailed workflow of by-blocks algorithm
+  // ========================================
+  template<int ArgVariant, 
+           template<int,int> class ControlType,
+           typename CrsTaskViewType>
+  class CholUpperRightLookByBlocks {
+  public:
+    KOKKOS_INLINE_FUNCTION
+    static int genScalarTask(typename CrsTaskViewType::policy_type &policy,
+                             typename CrsTaskViewType::matrix_type &A) {
+      typedef typename CrsTaskViewType::value_type        value_type;
+      typedef typename CrsTaskViewType::row_view_type     row_view_type;
+      
+      typedef typename CrsTaskViewType::future_type       future_type;
+      typedef typename CrsTaskViewType::task_factory_type task_factory_type;
+      
+      row_view_type a(A, 0); 
+      value_type &aa = a.Value(0);
+      
+      // construct a task
+      future_type f = task_factory_type::create(policy,
+                                                typename Chol<Uplo::Upper,
+                                                CtrlDetail(ControlType,AlgoChol::ByBlocks,ArgVariant,Chol)>
+                                                ::template TaskFunctor<value_type>(policy,aa));
+      
+
+if ( false ) {
+ printf("Chol [%d +%d)x[%d +%d) spawn depend %d\n"
+       , aa.OffsetRows()
+       , aa.NumRows()
+       , aa.OffsetCols()
+       , aa.NumCols()
+       , int( ! aa.Future().is_null() )
+       );
+}
+
+      // manage dependence
+      task_factory_type::addDependence(policy, f, aa.Future());
+      aa.setFuture(f);
+
+      // spawn a task
+      task_factory_type::spawn(policy, f, true /* high priority */ );
+      
+      return 1;
+    }
+    
+    KOKKOS_INLINE_FUNCTION
+    static int genTrsmTasks(typename CrsTaskViewType::policy_type &policy,
+                            typename CrsTaskViewType::matrix_type &A,
+                            typename CrsTaskViewType::matrix_type &B) {
+      typedef typename CrsTaskViewType::ordinal_type      ordinal_type;
+      typedef typename CrsTaskViewType::row_view_type     row_view_type;
+      typedef typename CrsTaskViewType::value_type        value_type;
+
+      typedef typename CrsTaskViewType::future_type       future_type;
+      typedef typename CrsTaskViewType::task_factory_type task_factory_type;
+      
+      row_view_type a(A,0), b(B,0); 
+      value_type &aa = a.Value(0);
+
+if ( false ) {
+  printf("genTrsmTasks after aa.Future().reference_count = %d\n"
+        , aa.Future().reference_count());
+}
+      const ordinal_type nnz = b.NumNonZeros();
+      for (ordinal_type j=0;j<nnz;++j) {
+        typedef typename
+           Trsm< Side::Left,Uplo::Upper,Trans::ConjTranspose,
+                 CtrlDetail(ControlType,AlgoChol::ByBlocks,ArgVariant,Trsm)>
+           ::template TaskFunctor<double,value_type,value_type>
+             FunctorType ;
+
+        value_type &bb = b.Value(j);
+        
+        future_type f = task_factory_type
+          ::create(policy, FunctorType(policy,Diag::NonUnit, 1.0, aa, bb));
+        
+if ( false ) {
+ printf("Trsm [%d +%d)x[%d +%d) spawn depend %d %d\n"
+       , bb.OffsetRows()
+       , bb.NumRows()
+       , bb.OffsetCols()
+       , bb.NumCols()
+       , int( ! aa.Future().is_null() )
+       , int( ! bb.Future().is_null() )
+       );
+}
+
+        // trsm dependence
+        task_factory_type::addDependence(policy, f, aa.Future());
+        
+        // self
+        task_factory_type::addDependence(policy, f, bb.Future());
+        
+        // place task signature on b
+        bb.setFuture(f);
+        
+        // spawn a task
+        task_factory_type::spawn(policy, f, true /* high priority */);              
+      }
+
+if ( false ) {
+  printf("genTrsmTasks after aa.Future().reference_count = %d\n"
+        , aa.Future().reference_count());
+}
+      
+      return nnz ;
+    }
+    
+    KOKKOS_INLINE_FUNCTION
+    static int genHerkTasks(typename CrsTaskViewType::policy_type &policy,
+                            typename CrsTaskViewType::matrix_type &A,
+                            typename CrsTaskViewType::matrix_type &C) {
+      typedef typename CrsTaskViewType::ordinal_type      ordinal_type;
+      typedef typename CrsTaskViewType::value_type        value_type;
+      typedef typename CrsTaskViewType::row_view_type     row_view_type;
+      
+      typedef typename CrsTaskViewType::future_type       future_type;
+      typedef typename CrsTaskViewType::task_factory_type task_factory_type;
+      
+      // case that X.transpose, A.no_transpose, Y.no_transpose
+      
+      row_view_type a(A,0), c; 
+      
+      const ordinal_type nnz = a.NumNonZeros();
+      ordinal_type herk_count = 0 ; 
+      ordinal_type gemm_count = 0 ; 
+
+      // update herk
+      for (ordinal_type i=0;i<nnz;++i) {
+        const ordinal_type row_at_i = a.Col(i);
+        value_type &aa = a.Value(i);
+        
+        c.setView(C, row_at_i);
+        
+        ordinal_type idx = 0;
+        for (ordinal_type j=i;j<nnz && (idx > -2);++j) {
+          const ordinal_type col_at_j = a.Col(j);
+          value_type &bb = a.Value(j);
+          
+          if (row_at_i == col_at_j) {
+            idx = c.Index(row_at_i, idx);
+            if (idx >= 0) {
+              ++herk_count ;
+              value_type &cc = c.Value(idx);
+              future_type f = task_factory_type
+                ::create(policy, 
+                         typename Herk<Uplo::Upper,Trans::ConjTranspose,
+                         CtrlDetail(ControlType,AlgoChol::ByBlocks,ArgVariant,Herk)>
+                         ::template TaskFunctor<double,value_type,value_type>(policy,-1.0, aa, 1.0, cc));
+            
+
+if ( false ) {
+ printf("Herk [%d +%d)x[%d +%d) spawn %d %d\n"
+       , cc.OffsetRows()
+       , cc.NumRows()
+       , cc.OffsetCols()
+       , cc.NumCols()
+       , int( ! aa.Future().is_null() )
+       , int( ! cc.Future().is_null() )
+       );
+}
+
+              // dependence
+              task_factory_type::addDependence(policy, f, aa.Future());              
+            
+              // self
+              task_factory_type::addDependence(policy, f, cc.Future());
+            
+              // place task signature on y
+              cc.setFuture(f);
+
+              // spawn a task
+              task_factory_type::spawn(policy, f);
+            }
+          } else {
+            idx = c.Index(col_at_j, idx);
+            if (idx >= 0) {
+              ++gemm_count ;
+              value_type &cc = c.Value(idx);
+              future_type f = task_factory_type
+                ::create(policy, 
+                         typename Gemm<Trans::ConjTranspose,Trans::NoTranspose,
+                         CtrlDetail(ControlType,AlgoChol::ByBlocks,ArgVariant,Gemm)>
+                         ::template TaskFunctor<double,value_type,value_type,value_type>(policy,-1.0, aa, bb, 1.0, cc));
+            
+
+if ( false ) {
+ printf("Gemm [%d +%d)x[%d +%d) spawn %d %d %d\n"
+       , cc.OffsetRows()
+       , cc.NumRows()
+       , cc.OffsetCols()
+       , cc.NumCols()
+       , int( ! aa.Future().is_null() )
+       , int( ! bb.Future().is_null() )
+       , int( ! cc.Future().is_null() )
+       );
+}
+ 
+              // dependence
+              task_factory_type::addDependence(policy, f, aa.Future());
+              task_factory_type::addDependence(policy, f, bb.Future());
+            
+              // self
+              task_factory_type::addDependence(policy, f, cc.Future());
+            
+              // place task signature on y
+              cc.setFuture(f);
+            
+              // spawn a task
+              task_factory_type::spawn(policy, f);
+            }
+          }
+        }
+      }
+
+if ( false ) {
+printf("genHerkTask Herk(%ld) Gemm(%ld)\n",(long)herk_count,(long)gemm_count);
+}
+    
+      return herk_count + gemm_count ;
+    }
+    
+  };
+  
+  // specialization for different task generation in right looking by-blocks algorithm
+  // =================================================================================
+  template<int ArgVariant, template<int,int> class ControlType>
+  class Chol<Uplo::Upper,AlgoChol::RightLookByBlocks,ArgVariant,ControlType> {
+  public:
+
+    // function interface
+    // ==================
+    template<typename ExecViewType>
+    KOKKOS_INLINE_FUNCTION
+    static int invoke(typename ExecViewType::policy_type &policy, 
+                      const typename ExecViewType::policy_type::member_type &member, 
+                      typename ExecViewType::matrix_type & A,
+                      int checkpoint )
+      {
+        typedef typename ExecViewType::row_view_type  row_view_type ;
+
+        enum { CYCLE = 2 };
+
+        typename ExecViewType::matrix_type
+          ATL, ATR,      A00, A01, A02,
+          ABL, ABR,      A10, A11, A12,
+                         A20, A21, A22;
+
+        Part_2x2(A,  ATL, ATR,
+                 /**/ABL, ABR,
+                 checkpoint, checkpoint, Partition::TopLeft);
+
+        int tasks_spawned = 0 ;
+        int futures_released = 0 ;
+
+        for ( int i = 0 ; i < CYCLE && ATL.NumRows() < A.NumRows() ; ++i ) {
+          Part_2x2_to_3x3(ATL, ATR, /**/  A00, A01, A02,
+                          /*******/ /**/  A10, A11, A12,
+                          ABL, ABR, /**/  A20, A21, A22,
+                          1, 1, Partition::BottomRight);
+          // -----------------------------------------------------
+          // Spawning tasks:
+
+          // A11 = chol(A11) : #task = 1
+          tasks_spawned +=
+          CholUpperRightLookByBlocks<ArgVariant,ControlType,ExecViewType>
+            ::genScalarTask(policy, A11);
+          
+          // A12 = inv(triu(A11)') * A12 : #tasks = non-zero row blocks
+          tasks_spawned +=
+          CholUpperRightLookByBlocks<ArgVariant,ControlType,ExecViewType>
+            ::genTrsmTasks(policy, A11, A12);
+
+          // A22 = A22 - A12' * A12 : #tasks = highly variable
+          tasks_spawned +=
+          CholUpperRightLookByBlocks<ArgVariant,ControlType,ExecViewType>
+            ::genHerkTasks(policy, A12, A22);
+
+          // -----------------------------------------------------
+          // Can release futures of A11 and A12 
+
+          futures_released += releaseFutures<ExecViewType>( A11 );
+          futures_released += releaseFutures<ExecViewType>( A12 );
+
+if ( false ) {
+  printf("Chol iteration(%d) task_count(%d) cumulative: spawn(%d) release(%d)\n"
+        , int(ATL.NumRows())
+        , policy.allocated_task_count()
+        , tasks_spawned , futures_released
+        );
+}
+
+          // -----------------------------------------------------
+          Merge_3x3_to_2x2(A00, A01, A02, /**/ ATL, ATR,
+                           A10, A11, A12, /**/ /******/
+                           A20, A21, A22, /**/ ABL, ABR,
+                           Partition::TopLeft);
+
+        }
+      
+      return ATL.NumRows();
+    }
+    
+    // task-data parallel interface
+    // ============================
+    template<typename ExecViewType>
+    class TaskFunctor {
+    public:
+      typedef typename ExecViewType::policy_type  policy_type;
+      typedef typename ExecViewType::future_type  future_type;
+      typedef typename policy_type::member_type   member_type;
+      typedef int value_type;
+      
+    private:
+      typename ExecViewType::matrix_type _A;
+      
+      policy_type _policy;
+      int         _checkpoint ;
+      
+    public:
+      KOKKOS_INLINE_FUNCTION
+      TaskFunctor(const policy_type & P ,
+                  const typename ExecViewType::matrix_type & A)
+        : _A(A),
+          _policy(P),
+          _checkpoint(0)
+      { } 
+      
+      string Label() const { return "Chol"; }
+      
+      // task-data execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(const member_type &member, value_type &r_val)
+      {
+        if (member.team_rank() == 0) {
+          // Clear out previous dependence
+          _policy.clear_dependence( this );
+
+          _checkpoint = Chol::invoke<ExecViewType>(_policy, member, _A, _checkpoint);
+
+          if ( _checkpoint < _A.NumRows() ) _policy.respawn_needing_memory(this);
+
+          r_val = 0 ;
+        }
+        return ;
+      }
+
+    };
+
+  };
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/chol_u_unblocked_opt1.hpp b/lib/kokkos/example/ichol/src/chol_u_unblocked_opt1.hpp
new file mode 100644
index 0000000000..3bb99c7142
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/chol_u_unblocked_opt1.hpp
@@ -0,0 +1,90 @@
+#pragma once
+#ifndef __CHOL_U_UNBLOCKED_OPT1_HPP__
+#define __CHOL_U_UNBLOCKED_OPT1_HPP__
+
+/// \file chol_u_unblocked_opt1.hpp
+/// \brief Unblocked incomplete Chloesky factorization.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+#include "partition.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<>
+  template<typename CrsExecViewType>
+  KOKKOS_INLINE_FUNCTION
+  int
+  Chol<Uplo::Upper,AlgoChol::UnblockedOpt,Variant::One>
+  ::invoke(typename CrsExecViewType::policy_type &policy,
+           const typename CrsExecViewType::policy_type::member_type &member,
+           typename CrsExecViewType::matrix_type &A) {
+
+    typedef typename CrsExecViewType::value_type        value_type;
+    typedef typename CrsExecViewType::ordinal_type      ordinal_type;
+    typedef typename CrsExecViewType::row_view_type     row_view_type;
+
+    // row_view_type r1t, r2t;
+
+    for (ordinal_type k=0;k<A.NumRows();++k) {
+      //r1t.setView(A, k);
+      row_view_type &r1t = A.RowView(k);
+
+      // extract diagonal from alpha11
+      value_type &alpha = r1t.Value(0);
+
+      if (member.team_rank() == 0) {
+        // if encounter null diag or wrong index, return -(row + 1)
+        if (abs(alpha) == 0.0 || r1t.Col(0) != k)
+          return -(k + 1);
+
+        // error handling should be more carefully designed
+
+        // sqrt on diag
+        // alpha = sqrt(real(alpha));
+        alpha = sqrt(alpha);
+      }
+      member.team_barrier();
+
+      const ordinal_type nnz_r1t = r1t.NumNonZeros();
+
+      if (nnz_r1t) {
+        // inverse scale
+        Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 1, nnz_r1t),
+                             [&](const ordinal_type j) {
+                               r1t.Value(j) /= alpha;
+                             });
+
+        member.team_barrier();
+
+        // hermitian rank update
+        Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 1, nnz_r1t),
+                             [&](const ordinal_type i) {
+                               const ordinal_type row_at_i = r1t.Col(i);
+                               // const value_type   val_at_i = conj(r1t.Value(i));
+                               const value_type   val_at_i = r1t.Value(i);
+                               
+                               //r2t.setView(A, row_at_i);
+                               row_view_type &r2t = A.RowView(row_at_i);
+                               ordinal_type idx = 0;
+                               
+                               for (ordinal_type j=i;j<nnz_r1t && (idx > -2);++j) {
+                                 const ordinal_type col_at_j = r1t.Col(j);
+                                 idx = r2t.Index(col_at_j, idx);
+                                 
+                                 if (idx >= 0) {
+                                   const value_type val_at_j = r1t.Value(j);
+                                   r2t.Value(idx) -= val_at_i*val_at_j;
+                                 }
+                               }
+                             });
+      }
+    }
+    return 0;
+  }
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/chol_u_unblocked_opt2.hpp b/lib/kokkos/example/ichol/src/chol_u_unblocked_opt2.hpp
new file mode 100644
index 0000000000..e7d1dc8262
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/chol_u_unblocked_opt2.hpp
@@ -0,0 +1,154 @@
+#pragma once
+#ifndef __CHOL_U_UNBLOCKED_OPT2_HPP__
+#define __CHOL_U_UNBLOCKED_OPT2_HPP__
+
+/// \file chol_u_unblocked_opt2.hpp
+/// \brief Unblocked incomplete Chloesky factorization; version for data parallel sharing L1 cache.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+#include "partition.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<>
+  template<typename CrsExecViewType>
+  KOKKOS_INLINE_FUNCTION
+  int
+  Chol<Uplo::Upper,AlgoChol::UnblockedOpt,Variant::Two>
+  ::invoke(typename CrsExecViewType::policy_type &policy,
+           const typename CrsExecViewType::policy_type::member_type &member,
+           typename CrsExecViewType::matrix_type &A) {
+
+    typedef typename CrsExecViewType::value_type        value_type;
+    typedef typename CrsExecViewType::ordinal_type      ordinal_type;
+    typedef typename CrsExecViewType::row_view_type     row_view_type;
+
+if ( false && member.team_rank() == 0 ) {
+ printf("Chol [%d +%d)x[%d +%d) begin\n"
+       , A.OffsetRows()
+       , A.NumRows()
+       , A.OffsetCols()
+       , A.NumCols()
+       );
+}
+
+    // row_view_type r1t, r2t;
+
+    for (ordinal_type k=0;k<A.NumRows();++k) {
+      //r1t.setView(A, k);
+      row_view_type &r1t = A.RowView(k);
+
+      // extract diagonal from alpha11
+      value_type &alpha = r1t.Value(0);
+
+      if (member.team_rank() == 0) {
+        // if encounter null diag or wrong index, return -(row + 1)
+        if (abs(alpha) == 0.0 || r1t.Col(0) != k)
+          return -(k + 1);
+
+        // error handling should be more carefully designed
+
+        // sqrt on diag
+        // alpha = sqrt(real(alpha));
+        alpha = sqrt(alpha);
+      }
+      member.team_barrier();
+
+
+if ( false && member.team_rank() == 0 ) {
+ printf("Chol [%d +%d)x[%d +%d) local row %d\n"
+       , A.OffsetRows()
+       , A.NumRows()
+       , A.OffsetCols()
+       , A.NumCols()
+       , int(k)
+       );
+}
+
+
+      const ordinal_type nnz_r1t = r1t.NumNonZeros();
+
+      if (nnz_r1t) {
+        // inverse scale
+        Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 1, nnz_r1t),
+                             [&](const ordinal_type j) {
+                               r1t.Value(j) /= alpha;
+                             });
+
+        member.team_barrier();
+
+
+if ( false && member.team_rank() == 0 ) {
+ printf("Chol [%d +%d)x[%d +%d) local row %d nnz_r1t\n"
+       , A.OffsetRows()
+       , A.NumRows()
+       , A.OffsetCols()
+       , A.NumCols()
+       , int(k)
+       );
+}
+
+        // hermitian rank update
+        for (ordinal_type i=1;i<nnz_r1t;++i) {
+          const ordinal_type row_at_i = r1t.Col(i);
+          // const value_type   val_at_i = conj(r1t.Value(i));
+          const value_type   val_at_i = r1t.Value(i);
+
+          //r2t.setView(A, row_at_i);
+          row_view_type &r2t = A.RowView(row_at_i);
+
+          ordinal_type member_idx = 0 ;
+
+          Kokkos::parallel_for(Kokkos::TeamThreadRange(member, i, nnz_r1t),
+                               [&](const ordinal_type j) {
+                                 if (member_idx > -2) {
+                                   const ordinal_type col_at_j = r1t.Col(j);
+                                   member_idx = r2t.Index(col_at_j, member_idx);
+                                   if (member_idx >= 0) {
+                                     const value_type   val_at_j = r1t.Value(j);
+                                     r2t.Value(member_idx) -= val_at_i*val_at_j;
+                                   }
+                                 }
+                               });
+        }
+      }
+
+
+if ( false ) {
+member.team_barrier();
+if ( member.team_rank() == 0 ) {
+ printf("Chol [%d +%d)x[%d +%d) local row %d end\n"
+       , A.OffsetRows()
+       , A.NumRows()
+       , A.OffsetCols()
+       , A.NumCols()
+       , int(k)
+       );
+}
+}
+
+    }
+
+
+if ( false ) {
+member.team_barrier();
+if ( member.team_rank() == 0 ) {
+ printf("Chol [%d +%d)x[%d +%d) end\n"
+       , A.OffsetRows()
+       , A.NumRows()
+       , A.OffsetCols()
+       , A.NumCols()
+       );
+}
+}
+
+
+    return 0;
+  }
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/control.hpp b/lib/kokkos/example/ichol/src/control.hpp
new file mode 100644
index 0000000000..bf5efef9fd
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/control.hpp
@@ -0,0 +1,110 @@
+#pragma once
+#ifndef __CONTROL_HPP__
+#define __CONTROL_HPP__
+
+#include "util.hpp"
+
+/// \file control.hpp
+/// \brief A collection of control trees composing high-level variants of algorithms.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+/// description is a bit wrong
+
+using namespace std;
+
+namespace Tacho {
+
+  // forward declaration for control tree
+  template<int ArgAlgo, int ArgVariant>
+  struct Control {
+    static constexpr int Self[2] = { ArgAlgo, ArgVariant };
+  };
+
+  // ----------------------------------------------------------------------------------
+
+  // - CholByblocks Variant 1
+  // * partitioned block matrix (blocks are sparse)
+  template<> struct Control<AlgoChol::ByBlocks,Variant::One> {
+    // chol var 1 : nested data parallel for is applied in the second inner loop
+    // chol var 2 : nested data parallel for is applied in the most inner loop
+    static constexpr int Chol[2] = { AlgoChol::UnblockedOpt,     Variant::Two };
+    static constexpr int Trsm[2] = { AlgoTrsm::ForFactorBlocked, Variant::One };
+    static constexpr int Herk[2] = { AlgoHerk::ForFactorBlocked, Variant::One };
+    static constexpr int Gemm[2] = { AlgoGemm::ForFactorBlocked, Variant::One };
+  };
+
+  // - CholByBlocks Variant 2
+  // * diagonal blocks have nested dense blocks
+  template<> struct Control<AlgoChol::ByBlocks,Variant::Two> {
+    static constexpr int Chol[2] = { AlgoChol::UnblockedOpt, Variant::One }; 
+    static constexpr int Trsm[2] = { AlgoTrsm::ForFactorBlocked, Variant::One };
+    static constexpr int Herk[2] = { AlgoHerk::ForFactorBlocked, Variant::One };
+    static constexpr int Gemm[2] = { AlgoGemm::ForFactorBlocked, Variant::One };
+  };
+
+  // - CholByBlocks Variant 3
+  // * all blocks have nested dense blocks (full supernodal algorithm)
+  // template<> struct Control<AlgoChol::ByBlocks,Variant::Three> {
+  //   static constexpr int Chol[2] = { AlgoChol::NestedDenseBlock, Variant::One }; 
+  //   static constexpr int Trsm[2] = { AlgoTrsm::NestedDenseBlock, Variant::One };
+  //   static constexpr int Herk[2] = { AlgoHerk::NestedDenseBlock, Variant::One };
+  //   static constexpr int Gemm[2] = { AlgoGemm::NestedDenseBlock, Variant::One };
+  // };
+
+  // - CholByBlocks Variant 4
+  // * diagonal blocks have nested hier dense blocks (hierarchical task scheduling)
+  // template<> struct Control<AlgoChol::ByBlocks,Variant::Four> {
+  //  static constexpr int Chol[2] = { AlgoChol::NestedDenseByBlocks, Variant::One }; 
+  //  static constexpr int Trsm[2] = { AlgoTrsm::ForFactorBlocked,    Variant::One };
+  //  static constexpr int Herk[2] = { AlgoHerk::ForFactorBlocked,    Variant::One };
+  //  static constexpr int Gemm[2] = { AlgoGemm::ForFactorBlocked,    Variant::One };
+  //};
+
+  // - CholByBlocks Variant 5
+  // * diagonal blocks have nested hier dense blocks (hierarchical task scheduling)
+  // template<> struct Control<AlgoChol::ByBlocks,Variant::Four> {
+  //   static constexpr int Chol[2] = { AlgoChol::NestedDenseByBlocks, Variant::One }; 
+  //   static constexpr int Trsm[2] = { AlgoTrsm::NestedDenseByBlocks, Variant::One };
+  //   static constexpr int Herk[2] = { AlgoHerk::NestedDenseByBlocks, Variant::One };
+  //   static constexpr int Gemm[2] = { AlgoGemm::NestedDenseByBlocks, Variant::One };
+  // };
+
+  // ----------------------------------------------------------------------------------
+
+  // - CholNestedDenseBlock
+  // * branch control between sparse and dense operations
+  template<> struct Control<AlgoChol::NestedDenseBlock,Variant::One> {
+    static constexpr int CholSparse[2] = { AlgoChol::UnblockedOpt,   Variant::One };
+    static constexpr int CholDense[2]  = { AlgoChol::ExternalLapack, Variant::One }; 
+  };
+
+  // - CholNestedDenseBlock
+  // * branch control between sparse and dense operations
+  template<> struct Control<AlgoChol::NestedDenseByBlocks,Variant::One> {
+    static constexpr int CholSparse[2]        = { AlgoChol::UnblockedOpt,  Variant::One };
+    static constexpr int CholDenseByBlocks[2] = { AlgoChol::DenseByBlocks, Variant::One }; 
+  };
+
+  // ----------------------------------------------------------------------------------
+
+  // - CholDenseBlock
+  // * dense matrix Cholesky-by-blocks
+  template<> struct Control<AlgoChol::DenseByBlocks,Variant::One> {
+    static constexpr int Chol[2] = { AlgoChol::ExternalLapack, Variant::One };
+    static constexpr int Trsm[2] = { AlgoTrsm::ExternalBlas,   Variant::One };
+    static constexpr int Herk[2] = { AlgoHerk::ExternalBlas,   Variant::One };
+    static constexpr int Gemm[2] = { AlgoGemm::ExternalBlas,   Variant::One };
+  };
+
+  template<> struct Control<AlgoGemm::DenseByBlocks,Variant::One> {
+    static constexpr int Gemm[2] = { AlgoGemm::ExternalBlas, Variant::One };
+  };
+
+  template<> struct Control<AlgoTrsm::DenseByBlocks,Variant::One> {
+    static constexpr int Gemm[2] = { AlgoGemm::ExternalBlas, Variant::One };
+    static constexpr int Trsm[2] = { AlgoTrsm::ExternalBlas, Variant::One };
+  };
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/coo.hpp b/lib/kokkos/example/ichol/src/coo.hpp
new file mode 100644
index 0000000000..977f17e5c5
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/coo.hpp
@@ -0,0 +1,75 @@
+#pragma once
+#ifndef __COO_HPP__
+#define __COO_HPP__
+
+/// \file coo.hpp
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho { 
+  
+  using namespace std;
+
+  /// \class Coo
+  /// \brief Sparse coordinate format; (i, j, val).
+  template<typename CrsMatType>
+  class Coo {
+  public:
+    typedef typename CrsMatType::ordinal_type ordinal_type;
+    typedef typename CrsMatType::value_type   value_type;
+
+  public:
+    ordinal_type _i,_j;
+    value_type _val;
+
+  public:
+    ordinal_type& Row() { return _i;   } 
+    ordinal_type& Col() { return _j;   }
+    value_type&   Val() { return _val; }
+
+    ordinal_type  Row() const { return _i;   } 
+    ordinal_type  Col() const { return _j;   }
+    value_type    Val() const { return _val; }
+    
+    Coo() {}
+
+    Coo(const ordinal_type i, 
+        const ordinal_type j, 
+        const value_type val) 
+      : _i(i),
+        _j(j),
+        _val(val) 
+    { }
+
+    Coo(const Coo& b)
+      : _i(b._i),
+        _j(b._j),
+        _val(b._val) 
+    { }
+
+    Coo<CrsMatType>& operator=(const Coo<CrsMatType> &y) {
+      this->_i = y._i;
+      this->_j = y._j;
+      this->_val = y._val;
+
+      return *this;
+    }
+
+    /// \brief Compare "less" index i and j only.
+    bool operator<(const Coo<CrsMatType> &y) const {
+      ordinal_type r_val = (this->_i - y._i);
+      return (r_val == 0 ? this->_j < y._j : r_val < 0);
+    }  
+    
+    /// \brief Compare "equality" only index i and j.
+    bool operator==(const Coo<CrsMatType> &y) const {
+      return (this->_i == y._i) && (this->_j == y._j);
+    }  
+ 
+    /// \brief Compare "in-equality" only index i and j.   
+    bool operator!=(const Coo<CrsMatType> &y) const {
+      return !(*this == y);
+    }  
+  };
+  
+}
+#endif
diff --git a/lib/kokkos/example/ichol/src/crs_matrix_base.hpp b/lib/kokkos/example/ichol/src/crs_matrix_base.hpp
new file mode 100644
index 0000000000..ad08b8757e
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/crs_matrix_base.hpp
@@ -0,0 +1,598 @@
+#pragma once
+#ifndef __CRS_MATRIX_BASE_HPP__
+#define __CRS_MATRIX_BASE_HPP__
+
+/// \file crs_matrix_base.hpp
+/// \brief CRS matrix base object interfaces to user provided input matrices.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+#include "coo.hpp"
+
+namespace Tacho { 
+
+  using namespace std;
+
+  template< typename , typename > class TaskView ;
+
+  template < typename CrsMatrixType >
+  struct GetCrsMatrixRowViewType {
+    typedef int type ;
+  };
+
+
+  template < typename CrsMatrixViewType , typename TaskFactoryType >
+  struct GetCrsMatrixRowViewType
+    < TaskView<CrsMatrixViewType,TaskFactoryType> >
+  {
+    typedef typename CrsMatrixViewType::row_view_type type ;
+  };
+
+  /// \class CrsMatrixBase
+  /// \breif CRS matrix base object using Kokkos view and subview
+  template<typename ValueType,
+           typename OrdinalType, 
+           typename SizeType = OrdinalType,
+           typename SpaceType = void,
+           typename MemoryTraits = void>
+  class CrsMatrixBase {
+  public:
+    typedef ValueType    value_type;
+    typedef OrdinalType  ordinal_type;
+    typedef SpaceType    space_type;
+    typedef SizeType     size_type;
+    typedef MemoryTraits memory_traits;
+
+    // 1D view, layout does not matter; no template parameters for that
+    typedef Kokkos::View<size_type*,   space_type,memory_traits> size_type_array;
+    typedef Kokkos::View<ordinal_type*,space_type,memory_traits> ordinal_type_array;
+    typedef Kokkos::View<value_type*,  space_type,memory_traits> value_type_array;
+
+    typedef typename size_type_array::value_type*    size_type_array_ptr;
+    typedef typename ordinal_type_array::value_type* ordinal_type_array_ptr;
+    typedef typename value_type_array::value_type*   value_type_array_ptr;
+
+    // range type
+    template<typename T> using range_type = pair<T,T>;
+
+    // external interface
+    typedef Coo<CrsMatrixBase> ijv_type;
+    
+    friend class CrsMatrixHelper;
+
+  private:
+
+    ordinal_type       _m;       //!< # of rows
+    ordinal_type       _n;       //!< # of cols
+    size_type          _nnz;     //!< # of nonzeros
+    size_type_array    _ap;      //!< pointers to column index and values
+    ordinal_type_array _aj;      //!< column index compressed format
+    value_type_array   _ax;      //!< values
+
+  public:
+
+    typedef typename GetCrsMatrixRowViewType< ValueType >::type row_view_type ;
+    typedef Kokkos::View<row_view_type*,space_type> row_view_type_array;
+
+    row_view_type_array _all_row_views ;
+
+  protected:
+
+    void createInternalArrays(const ordinal_type m, 
+                              const ordinal_type n,
+                              const size_type nnz) {
+      _m = m;
+      _n = n;
+      _nnz = nnz;
+
+      if (static_cast<ordinal_type>(_ap.dimension_0()) < m+1)
+        _ap = size_type_array("CrsMatrixBase::RowPtrArray", m+1);
+      
+      if (static_cast<size_type>(_aj.dimension_0()) < nnz)
+        _aj = ordinal_type_array("CrsMatrixBase::ColsArray", nnz);
+
+      if (static_cast<size_type>(_ax.dimension_0()) < nnz)
+        _ax = value_type_array("CrsMatrixBase::ValuesArray", nnz);
+    }
+
+    // Copy sparse matrix structure from coordinate format in 'mm'
+    // to CRS format in Views _ap, _aj, a_x.
+    void ijv2crs(const vector<ijv_type> &mm) {
+
+      ordinal_type ii = 0;
+      size_type jj = 0;
+      
+      ijv_type prev = mm[0];
+      _ap[ii++] = 0;
+      _aj[jj] = prev.Col();
+      _ax[jj] = prev.Val();
+      ++jj;
+      
+      for (typename vector<ijv_type>::const_iterator it=(mm.begin()+1);it<mm.end();++it) {
+        ijv_type aij = (*it);
+        
+        // row index
+        if (aij.Row() != prev.Row()) {
+          _ap[ii++] = jj; 
+        }
+        
+        if (aij == prev) {
+          --jj;
+          _aj[jj]  = aij.Col();
+          _ax[jj] += aij.Val();
+        } else {
+          _aj[jj] = aij.Col();
+          _ax[jj] = aij.Val();
+        }
+        ++jj;
+        
+        prev = aij;
+      }
+      
+      // add the last index to terminate the storage
+      _ap[ii++] = jj;
+      _nnz = jj;
+    }
+    
+  public:
+
+    KOKKOS_INLINE_FUNCTION
+    void setNumNonZeros() { 
+      if (_m) 
+        _nnz = _ap[_m];
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type NumRows() const { return _m; }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type NumCols() const { return _n; }
+
+    KOKKOS_INLINE_FUNCTION
+    size_type NumNonZeros() const { return _nnz; }
+
+    KOKKOS_INLINE_FUNCTION
+    size_type_array_ptr RowPtr() const { return &_ap[0]; }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type_array_ptr ColPtr() const { return &_aj[0]; }
+
+    KOKKOS_INLINE_FUNCTION
+    value_type_array_ptr ValuePtr() const { return &_ax[0];}
+
+    KOKKOS_INLINE_FUNCTION
+    size_type RowPtr(const ordinal_type i) const { return _ap[i]; }
+    
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type_array_ptr ColsInRow(const ordinal_type i) const { return _aj.data() + _ap[i] ; }
+    
+    KOKKOS_INLINE_FUNCTION
+    value_type_array_ptr ValuesInRow(const ordinal_type i) const { return _ax.data() + _ap[i] ; }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type NumNonZerosInRow(const ordinal_type i) const { return (_ap[i+1] - _ap[i]); } 
+
+    KOKKOS_INLINE_FUNCTION
+    value_type& Value(const ordinal_type k) { return _ax[k]; }
+
+    KOKKOS_INLINE_FUNCTION
+    value_type Value(const ordinal_type k) const { return _ax[k]; }
+
+    /// \brief Default constructor.
+    KOKKOS_INLINE_FUNCTION
+    CrsMatrixBase() 
+      : _m(0),
+        _n(0),
+        _nnz(0),
+        _ap(),
+        _aj(),
+        _ax()
+    { }
+
+    /// \brief Constructor with label
+    CrsMatrixBase(const string & ) 
+      : _m(0),
+        _n(0),
+        _nnz(0),
+        _ap(),
+        _aj(),
+        _ax()
+    { }
+
+    /// \brief Copy constructor (shallow copy), for deep-copy use a method copy
+    template<typename VT,
+             typename OT,
+             typename ST,
+             typename SpT,
+             typename MT>
+    CrsMatrixBase(const CrsMatrixBase<VT,OT,ST,SpT,MT> &b) 
+      : _m(b._m),
+        _n(b._n),
+        _nnz(b._nnz),
+        _ap(b._ap), 
+        _aj(b._aj),
+        _ax(b._ax) 
+    { }
+
+    /// \brief Constructor to allocate internal data structures.
+    CrsMatrixBase(const string & ,
+                  const ordinal_type m, 
+                  const ordinal_type n, 
+                  const ordinal_type nnz) 
+      : _m(m),
+        _n(n),
+        _nnz(nnz),
+        _ap("CrsMatrixBase::RowPtrArray", m+1),
+        _aj("CrsMatrixBase::ColsArray", nnz),
+        _ax("CrsMatrixBase::ValuesArray", nnz)
+    { }
+
+    /// \brief Constructor to attach external arrays to the matrix.
+    CrsMatrixBase(const string &,
+                  const ordinal_type m, 
+                  const ordinal_type n, 
+                  const ordinal_type nnz,
+                  const size_type_array &ap,
+                  const ordinal_type_array &aj,
+                  const value_type_array &ax) 
+      : _m(m),
+        _n(n),
+        _nnz(nnz),
+        _ap(ap), 
+        _aj(aj),
+        _ax(ax) 
+    { }
+    
+  // Allow the copy function access to the input CrsMatrixBase
+  // private data.
+  template<typename, typename, typename, typename, typename>
+  friend class CrsMatrixBase ;
+
+  public:
+    /// \brief deep copy of matrix b, potentially different spaces
+    template< typename SpT >
+    int 
+    copy(const CrsMatrixBase<ValueType,OrdinalType,SizeType,SpT,MemoryTraits> &b) {
+
+      space_type::execution_space::fence();
+
+      createInternalArrays(b._m, b._n, b._nnz);
+
+      space_type::execution_space::fence();
+
+      const auto ap_range = range_type<ordinal_type>(0, min(_ap.dimension_0(), b._ap.dimension_0()));
+      const auto aj_range = range_type<size_type>   (0, min(_aj.dimension_0(), b._aj.dimension_0()));
+      const auto ax_range = range_type<size_type>   (0, min(_ax.dimension_0(), b._ax.dimension_0()));
+
+      Kokkos::deep_copy(Kokkos::subview(  _ap, ap_range), 
+                        Kokkos::subview(b._ap, ap_range));
+      Kokkos::deep_copy(Kokkos::subview(  _aj, aj_range),
+                        Kokkos::subview(b._aj, aj_range));
+
+      Kokkos::deep_copy(Kokkos::subview(  _ax, ax_range),
+                        Kokkos::subview(b._ax, ax_range));
+
+      space_type::execution_space::fence();
+
+      return 0;
+    }
+
+    /// \brief deep copy of lower/upper triangular of matrix b
+    int 
+    copy(const int uplo, 
+         const CrsMatrixBase &b) { 
+
+      createInternalArrays(b._m, b._n, b._nnz);
+
+      // assume that matrix b is sorted.
+      switch (uplo) {
+      case Uplo::Lower: {
+        _nnz = 0;
+        for (ordinal_type i=0;i<_m;++i) {
+          size_type jbegin = b._ap[i];
+          size_type jend   = b._ap[i+1];
+          _ap[i] = _nnz;
+          for (size_type j=jbegin;j<jend && (i >= b._aj[j]);++j,++_nnz) {
+            _aj[_nnz] = b._aj[j];
+            _ax[_nnz] = b._ax[j]; 
+          }
+        }
+        _ap[_m] = _nnz;
+        break;
+      }
+      case Uplo::Upper: {
+        _nnz = 0;
+        for (ordinal_type i=0;i<_m;++i) {
+          size_type j = b._ap[i];
+          size_type jend = b._ap[i+1];
+          _ap[i] = _nnz;
+          for ( ;j<jend && (i > b._aj[j]);++j) ;
+          for ( ;j<jend;++j,++_nnz) {
+            _aj[_nnz] = b._aj[j];
+            _ax[_nnz] = b._ax[j]; 
+          }
+        }
+        _ap[_m] = _nnz;
+        break;
+      }
+      }
+
+      return 0;
+    }
+
+    /// \brief deep copy of matrix b with given permutation vectors
+    template<typename VT,
+             typename OT,
+             typename ST,
+             typename SpT,
+             typename MT>
+    int
+    copy(const typename CrsMatrixBase<VT,OT,ST,SpT,MT>::ordinal_type_array &p,
+         const typename CrsMatrixBase<VT,OT,ST,SpT,MT>::ordinal_type_array &ip,
+         const CrsMatrixBase<VT,OT,ST,SpT,MT> &b) {
+
+      createInternalArrays(b._m, b._n, b._nnz);
+
+      // Question:: do I need to use Kokkos::vector ? 
+      //            in other words, where do we permute matrix in factoriztion ?
+      //            permuting a matrix is a kernel ? 
+      vector<ijv_type> tmp;
+
+      // any chance to use parallel_for ?
+      _nnz = 0;
+      for (ordinal_type i=0;i<_m;++i) {
+        ordinal_type ii = ip[i];
+
+        size_type jbegin = b._ap[ii];
+        size_type jend   = b._ap[ii+1];
+
+        _ap[i] = _nnz;
+        for (size_type j=jbegin;j<jend;++j) {
+          ordinal_type jj = p[b._aj[j]];
+          ijv_type aij(i, jj, b._ax[j]);
+          tmp.push_back(aij);
+        }
+
+        sort(tmp.begin(), tmp.end(), less<ijv_type>());
+        for (auto it=tmp.begin();it<tmp.end();++it) {
+          ijv_type aij = (*it);
+
+          _aj[_nnz] = aij.Col();
+          _ax[_nnz] = aij.Val();
+          ++_nnz;
+        }
+        tmp.clear();
+      }
+      _ap[_m] = _nnz;
+
+      return 0;
+    }
+
+    /// \brief add the matrix b into this non-zero entires
+    template<typename VT,
+             typename OT,
+             typename ST,
+             typename SpT,
+             typename MT>
+    int 
+    add(const CrsMatrixBase<VT,OT,ST,SpT,MT> &b) { 
+
+      const ordinal_type m = min(b._m, _m);
+      for (ordinal_type i=0;i<m;++i) {
+        const size_type jaend = _ap[i+1];
+        const size_type jbend = b._ap[i+1];
+
+        size_type ja = _ap[i];
+        size_type jb = b._ap[i];
+        
+        for ( ;jb<jbend;++jb) {
+          for ( ;(_aj[ja]<b._aj[jb] && ja<jaend);++ja);
+          _ax[ja] += (_aj[ja] == b._aj[jb])*b._ax[jb];
+        }
+      }
+
+      return 0;
+    }
+
+    int symmetrize(const int uplo, 
+                   const bool conjugate = false) {
+      vector<ijv_type> mm;
+      mm.reserve(_nnz*2);
+
+      for (ordinal_type i=0;i<_m;++i) {
+        const size_type jbegin = _ap[i];
+        const size_type jend   = _ap[i+1];
+        for (size_type jj=jbegin;jj<jend;++jj) {
+          const ordinal_type j = _aj[jj];
+          const value_type val = (conjugate ? conj(_ax[j]) : _ax[j]);
+          if        (uplo == Uplo::Lower && i > j) {
+            mm.push_back(ijv_type(i, j, val));
+            mm.push_back(ijv_type(j, i, val));
+          } else if (uplo == Uplo::Upper && i < j) {
+            mm.push_back(ijv_type(i, j, val));
+            mm.push_back(ijv_type(j, i, val));
+          } else if (i == j) {
+            mm.push_back(ijv_type(i, i, val));
+          }
+        }
+      }
+      sort(mm.begin(), mm.end(), less<ijv_type>());
+
+      createInternalArrays(_m, _n, mm.size());
+      
+      ijv2crs(mm);
+      
+      return 0;
+    }
+
+    int hermitianize(int uplo) {
+      return symmetrize(uplo, true);
+    }
+
+    ostream& showMe(ostream &os) const {
+      streamsize prec = os.precision();
+      os.precision(8);
+      os << scientific;
+
+      os << " -- CrsMatrixBase -- " << endl
+         << "    # of Rows          = " << _m << endl
+         << "    # of Cols          = " << _n << endl
+         << "    # of NonZeros      = " << _nnz << endl
+         << endl
+         << "    RowPtrArray length = " << _ap.dimension_0() << endl
+         << "    ColArray    length = " << _aj.dimension_0() << endl 
+         << "    ValueArray  length = " << _ax.dimension_0() << endl
+         << endl;
+      
+      const int w = 10;
+      if (_ap.size() && _aj.size() && _ax.size()) {
+        os << setw(w) <<  "Row" << "  " 
+           << setw(w) <<  "Col" << "  " 
+           << setw(w) <<  "Val" << endl;
+        for (ordinal_type i=0;i<_m;++i) {
+          size_type jbegin = _ap[i], jend = _ap[i+1];
+          for (size_type j=jbegin;j<jend;++j) {
+            value_type val = _ax[j];
+            os << setw(w) <<      i << "  " 
+               << setw(w) << _aj[j] << "  " 
+               << setw(w) <<    val << endl;
+          }
+        }
+      }
+
+      os.unsetf(ios::scientific);
+      os.precision(prec);
+
+      return os;
+    }
+
+    int importMatrixMarket(ifstream &file) {
+
+      vector<ijv_type> mm; 
+      const ordinal_type mm_base = 1; 
+
+      {
+        string header;
+        if (file.is_open()) {
+          getline(file, header);
+          while (file.good()) {
+            char c = file.peek();
+            if (c == '%' || c == '\n') {
+              file.ignore(256, '\n');
+            continue;
+            }
+            break;
+          }
+        } else {
+          ERROR(MSG_INVALID_INPUT(file));
+        }
+
+        // check the header
+        bool symmetry = (header.find("symmetric") != string::npos);
+
+        // read matrix specification
+        ordinal_type m, n;
+        size_type nnz;
+        
+        file >> m >> n >> nnz;
+        
+        mm.reserve(nnz*(symmetry ? 2 : 1));
+        for (size_type i=0;i<nnz;++i) {
+          ordinal_type row, col;
+          value_type val;
+          file >> row >> col >> val;
+          
+          row -= mm_base;
+          col -= mm_base;
+          
+          mm.push_back(ijv_type(row, col, val));
+          if (symmetry && row != col)
+            mm.push_back(ijv_type(col, row, val));
+        }
+        sort(mm.begin(), mm.end(), less<ijv_type>());
+      
+        // construct workspace and set variables
+        createInternalArrays(m, n, mm.size());
+      }
+      
+      // change mm to crs
+      ijv2crs(mm);
+      
+      return 0;
+    }
+    
+    int exportMatrixMarket(ofstream &file,
+                           const string comment,
+                           const int uplo = 0) {
+      streamsize prec = file.precision();
+      file.precision(8);
+      file << scientific;
+
+      file << "%%MatrixMarket matrix coordinate "
+           << (is_fundamental<value_type>::value ? "real " : "complex ")
+           << ((uplo == Uplo::Upper || uplo == Uplo::Lower) ? "symmetric " : "general ")
+           << endl;
+
+      file << comment << endl;
+      
+      // cnt nnz
+      size_type nnz = 0;
+      for (ordinal_type i=0;i<_m;++i) {
+        const size_type jbegin = _ap[i], jend = _ap[i+1];
+        for (size_type j=jbegin;j<jend;++j) {
+          if (uplo == Uplo::Upper && i <= _aj[j]) ++nnz;
+          if (uplo == Uplo::Lower && i >= _aj[j]) ++nnz;
+          if (!uplo) ++nnz;
+        }
+      }
+      file << _m << " " << _n << " " << nnz << endl;
+
+      const int w = 10;
+      for (ordinal_type i=0;i<_m;++i) {
+        const size_type jbegin = _ap[i], jend = _ap[i+1];
+        for (size_type j=jbegin;j<jend;++j) {
+          bool flag = false;
+          if (uplo == Uplo::Upper && i <= _aj[j]) flag = true;
+          if (uplo == Uplo::Lower && i >= _aj[j]) flag = true;
+          if (!uplo) flag = true;
+          if (flag) {
+            value_type val = _ax[j];
+            file << setw(w) << (     i+1) << "  " 
+                 << setw(w) << (_aj[j]+1) << "  " 
+                 << setw(w) <<    val << endl;
+          }
+        }
+      }
+
+      file.unsetf(ios::scientific);
+      file.precision(prec);
+
+      return 0;
+    }
+
+    //----------------------------------------------------------------------
+
+    int convertGraph(size_type_array rptr,
+                     ordinal_type_array cidx) const {
+      ordinal_type ii = 0;
+      size_type jj = 0;
+
+      for (ordinal_type i=0;i<_m;++i) {
+        size_type jbegin = _ap[i], jend = _ap[i+1];
+        rptr[ii++] = jj;
+        for (size_type j=jbegin;j<jend;++j)
+          if (i != _aj[j])
+            cidx[jj++] = _aj[j];
+      }
+      rptr[ii] = jj;
+
+      return 0;
+    }
+
+    //----------------------------------------------------------------------
+
+  };
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/crs_matrix_base_import.hpp b/lib/kokkos/example/ichol/src/crs_matrix_base_import.hpp
new file mode 100644
index 0000000000..e1ff0f3a9f
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/crs_matrix_base_import.hpp
@@ -0,0 +1,104 @@
+#pragma once
+#ifndef __CRS_MATRIX_BASE_IMPL_HPP__
+#define __CRS_MATRIX_BASE_IMPL_HPP__
+
+/// \file crs_matrix_base_impl.hpp
+/// \brief Implementation of external interfaces to CrsMatrixBase
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho { 
+
+  using namespace std;
+
+  template<typename VT,
+           typename OT,
+           typename ST,
+           typename SpT,
+           typename MT>
+  inline int 
+  CrsMatrixBase<VT,OT,ST,SpT,MT>::importMatrixMarket(ifstream &file) {
+    // skip initial title comments
+    {
+      ordinal_type m, n;
+      size_type nnz;
+          
+      while (file.good()) {
+        char c = file.peek();
+        if (c == '%' || c == '\n') {
+          file.ignore(256, '\n');
+          continue;
+        }
+        break;
+      }
+          
+      // read matrix specification
+      file >> m >> n >> nnz;
+          
+      // construct workspace and set variables
+      createInternalArrays(m, n, nnz);
+    }
+
+    // read the coordinate format (matrix-market)
+    vector<ijv_type> mm; 
+    mm.reserve(_nnz);
+    {
+      // matrix market use one base index
+      const ordinal_type mm_base = 1; 
+
+      for (size_type i=0;i<_nnz;++i) {
+        ijv_type aij;
+        file >> aij.Row() >> aij.Col() >> aij.Val();
+
+        // one base to zero base
+        aij.Row() -= mm_base;
+        aij.Col() -= mm_base;
+            
+        mm.push_back(aij);
+      }
+      sort(mm.begin(), mm.end(), less<ijv_type>());
+    }
+
+    // change mm to crs
+    {
+      ordinal_type ii = 0;
+      size_type jj = 0;
+
+      ijv_type prev = mm[0];
+      _ap[ii++] = 0;
+      _aj[jj] = prev.Col();
+      _ax[jj] = prev.Val();
+      ++jj;
+
+      for (typename vector<ijv_type>::iterator it=(mm.begin()+1);it<mm.end();++it) {
+        ijv_type aij = (*it);
+        
+        // row index
+        if (aij.Row() != prev.Row()) {
+          _ap[ii++] = jj; 
+        }
+            
+        if (aij == prev) {
+          --jj;
+          _aj[jj]  = aij.Col();
+          _ax[jj] += aij.Val();
+        } else {
+          _aj[jj] = aij.Col();
+          _ax[jj] = aij.Val();
+        }
+        ++jj;
+          
+        prev = aij;
+      }
+          
+      // add the last index to terminate the storage
+      _ap[ii++] = jj;
+      _nnz = jj;
+    }
+      
+    return 0;
+  }
+  
+}
+
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/crs_matrix_helper.hpp b/lib/kokkos/example/ichol/src/crs_matrix_helper.hpp
new file mode 100644
index 0000000000..5b80e77935
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/crs_matrix_helper.hpp
@@ -0,0 +1,71 @@
+#pragma once
+#ifndef __CRS_MATRIX_HELPER_HPP__
+#define __CRS_MATRIX_HELPER_HPP__
+
+/// \file crs_matrix_helper.hpp
+/// \brief This file includes utility functions to convert between flat and hierarchical matrices.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)  
+
+#include "util.hpp"
+
+namespace Tacho { 
+
+  using namespace std;
+
+  class CrsMatrixHelper {
+  public:
+
+    template< typename CrsHierBase >
+    static int fillRowViewArray( CrsHierBase & HU );
+
+    template<typename CrsFlatBase>
+    static int
+    filterZeros(CrsFlatBase &flat);
+    
+    /// \brief Transform a scalar flat matrix to hierarchical matrix of matrices 1x1; testing only.
+    template<typename CrsFlatBase,
+             typename CrsHierBase>
+    static int
+    flat2hier(CrsFlatBase &flat, 
+              CrsHierBase &hier);
+
+    /// \brief Transform a scalar flat matrix to upper hierarchical matrix given scotch info. 
+    template<typename CrsFlatBase,
+             typename CrsHierBase,
+             typename HostOrdinalTypeArray >
+    static int
+    flat2hier(int uplo, 
+              CrsFlatBase &flat, 
+              CrsHierBase &hier,
+              const typename CrsHierBase::ordinal_type       nblks,
+              const HostOrdinalTypeArray range,
+              const HostOrdinalTypeArray tree);
+
+    /// \brief Transform a scalar flat matrix to upper hierarchical matrix given scotch info. 
+    template<typename CrsFlatBase,
+             typename CrsHierBase,
+             typename HostOrdinalTypeArray >
+    static int
+    flat2hier_upper(CrsFlatBase &flat, 
+                    CrsHierBase &hier,
+                    const typename CrsHierBase::ordinal_type       nblks,
+                    const HostOrdinalTypeArray range,
+                    const HostOrdinalTypeArray tree);
+
+    /// \brief Transform a scalar flat matrix to lower hierarchical matrix given scotch info. 
+    template<typename CrsFlatBase,
+             typename CrsHierBase,
+             typename HostOrdinalTypeArray >
+    static int
+    flat2hier_lower(CrsFlatBase &flat, 
+                    CrsHierBase &hier,
+                    const typename CrsHierBase::ordinal_type       nblks,
+                    const HostOrdinalTypeArray range,
+                    const HostOrdinalTypeArray tree);
+  };
+
+}
+
+#include "crs_matrix_helper_impl.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/crs_matrix_helper_impl.hpp b/lib/kokkos/example/ichol/src/crs_matrix_helper_impl.hpp
new file mode 100644
index 0000000000..0fc4c9f1b8
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/crs_matrix_helper_impl.hpp
@@ -0,0 +1,364 @@
+
+#ifndef __CRS_MATRIX_HELPER_IMPL_HPP__
+#define __CRS_MATRIX_HELPER_IMPL_HPP__
+
+/// \file crs_matrix_helper_impl.hpp
+/// \brief This file includes utility functions to convert between flat and hierarchical matrices.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template< typename CrsHierBase >
+  struct FunctorFillRowViewArray {
+
+    typedef typename CrsHierBase::ordinal_type         ordinal_type ;
+    typedef typename CrsHierBase::row_view_type_array  row_view_type_array ;
+    typedef typename CrsHierBase::value_type_array     ax_type ;
+
+    typedef ordinal_type value_type ;
+
+    row_view_type_array _all_row_views ;
+    ax_type             _ax ;
+
+    FunctorFillRowViewArray( const row_view_type_array & arg_all_row_views
+                           , const ax_type             & arg_ax )
+      : _all_row_views( arg_all_row_views )
+      , _ax( arg_ax )
+      {}
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()( ordinal_type k , ordinal_type & value ) const
+      { value += _ax(k).NumRows(); }
+
+    KOKKOS_INLINE_FUNCTION
+    void operator()( ordinal_type k , ordinal_type & value , bool final ) const
+      {
+        if ( final ) {
+          const int begin = value ;
+          const int end   = begin + _ax(k).NumRows();
+
+          auto sub = Kokkos::subview( _all_row_views, Kokkos::pair<int,int>(begin,end) );
+
+          _ax(k).setRowViewArray( sub );
+        }
+
+        value += _ax(k).NumRows();
+      }
+  };
+
+  template< typename CrsHierBase >
+  int CrsMatrixHelper::fillRowViewArray( CrsHierBase & device_HU )
+  {
+    typedef typename CrsHierBase::row_view_type_array row_view_type_array ;
+    typedef typename CrsHierBase::space_type          space_type ;
+
+    ordinal_type total_row_view_count = 0 ;
+
+    Kokkos::RangePolicy< space_type >
+      range_policy( 0 , device_HU.NumNonZeros() );
+
+    space_type::fence();
+
+    {
+      FunctorFillRowViewArray< CrsHierBase >
+         functor( row_view_type_array() , device_HU._ax );
+
+
+      Kokkos::parallel_reduce( range_policy , functor , total_row_view_count );
+    }
+
+    device_HU._all_row_views =
+      row_view_type_array("RowViews",total_row_view_count);
+
+    space_type::fence();
+
+    {
+      FunctorFillRowViewArray< CrsHierBase >
+         functor( device_HU._all_row_views , device_HU._ax );
+
+      Kokkos::parallel_scan( range_policy , functor );
+    }
+
+    space_type::fence();
+
+    return 0 ;
+  }
+  
+  template<typename CrsFlatBase>
+  int
+  CrsMatrixHelper::filterZeros(CrsFlatBase &flat) {
+    typedef typename CrsFlatBase::ordinal_type           ordinal_type;
+    typedef typename CrsFlatBase::size_type              size_type;
+    typedef typename CrsFlatBase::value_type             value_type;
+    
+    typedef typename CrsFlatBase::ordinal_type_array_ptr ordinal_type_array_ptr;
+    typedef typename CrsFlatBase::value_type_array_ptr   value_type_array_ptr;
+    
+    size_type nz = 0;
+    const value_type zero(0);
+    
+    for (ordinal_type k=0;k<flat.NumNonZeros();++k) 
+      nz += (flat.Value(k) == zero) ;
+    
+    if (nz) {
+      CrsFlatBase resized(flat.Label() + "::ZeroFiltered", 
+                          flat.NumRows(),
+                          flat.NumCols(),
+                          flat.NumNonZeros() - nz);
+      
+      ordinal_type_array_ptr rows = resized.RowPtr(); rows[0] = 0;
+      ordinal_type_array_ptr cols = resized.ColPtr();
+      value_type_array_ptr vals = resized.ValuePtr();    
+      
+      size_type nnz = 0;
+      for (ordinal_type i=0;i<flat.NumRows();++i) {
+        const ordinal_type nnz_in_row = flat.NumNonZerosInRow(i);
+        const ordinal_type_array_ptr cols_in_row = flat.ColsInRow(i);
+        const value_type_array_ptr vals_in_row = flat.ValuesInRow(i);
+        
+        for (ordinal_type j=0;j<nnz_in_row;++j) {
+          if (vals_in_row[j] != zero) {
+            cols[nnz] = cols_in_row[j];
+            vals[nnz] = vals_in_row[j];
+            ++nnz;
+          }
+        }
+        rows[i+1] = nnz;
+      }
+      flat = resized;
+      resized.setNumNonZeros();
+    }
+
+    return 0;
+  }
+
+
+  template<typename CrsFlatBase,
+           typename CrsHierBase>
+  int
+  CrsMatrixHelper::flat2hier(CrsFlatBase &flat,
+                             CrsHierBase &hier) {
+    typedef typename CrsHierBase::ordinal_type           ordinal_type;
+    typedef typename CrsHierBase::size_type              size_type;
+    typedef typename CrsHierBase::ordinal_type_array_ptr ordinal_type_array_ptr;
+
+    size_type nnz = 0;
+
+    hier.createInternalArrays(flat.NumRows(), flat.NumCols(), flat.NumNonZeros());
+
+    for (ordinal_type i=0;i<flat.NumRows();++i) {
+      ordinal_type jsize = flat.NumNonZerosInRow(i);
+
+      hier._ap[i] = nnz;
+      ordinal_type_array_ptr ci = flat.ColsInRow(i);
+      for (ordinal_type j=0;j<jsize;++j,++nnz) {
+        hier._aj[nnz] = ci[j];
+        hier._ax[nnz].setView( flat,     i, 1,
+                              /**/   ci[j], 1);
+      }
+    }
+
+    hier._ap[flat.NumRows()] = nnz;
+    hier._nnz = nnz;
+
+    return 0;
+  }
+
+  template< typename CrsFlatBase ,
+            typename CrsHierBase ,
+            typename HostOrdinalTypeArray >
+  int
+  CrsMatrixHelper::flat2hier(int uplo,
+                             CrsFlatBase &flat,
+                             CrsHierBase &hier,
+                             const typename CrsHierBase::ordinal_type       nblks,
+                             const HostOrdinalTypeArray range ,
+                             const HostOrdinalTypeArray tree) {
+    switch(uplo) {
+    case Uplo::Upper: return flat2hier_upper(flat, hier, nblks, range, tree);
+    case Uplo::Lower: return flat2hier_lower(flat, hier, nblks, range, tree);
+    }
+    return -1;
+  }
+
+  template<typename CrsFlatBase,
+           typename CrsHierBase,
+           typename HostOrdinalTypeArray >
+  int
+  CrsMatrixHelper::flat2hier_upper(CrsFlatBase & device_flat, 
+                                   CrsHierBase & device_hier,
+                                   const typename CrsHierBase::ordinal_type       nblks,
+                                   const HostOrdinalTypeArray range,
+                                   const HostOrdinalTypeArray tree) {
+    typedef typename CrsHierBase::ordinal_type            ordinal_type;
+    typedef typename CrsHierBase::size_type               size_type;
+    
+    //typedef typename CrsHierBase::ordinal_type_array     ordinal_type_array;
+    //typedef typename CrsHierBase::ordinal_type_array_ptr ordinal_type_array_ptr;
+    //typedef typename CrsHierBase::value_type_array_ptr   value_type_array_ptr;
+    
+    size_type nnz = 0;
+    
+    // count nnz and nnz in rows for the upper triangular hier matrix
+    for (ordinal_type i=0;i<nblks;++i) 
+      for (ordinal_type j=i;j != -1;++nnz,j=tree[j]) ;
+    
+    // create upper triangular block matrix
+    device_hier.createInternalArrays(nblks, nblks, nnz);    
+
+    typename CrsHierBase::size_type_array::HostMirror
+      host_ap = Kokkos::create_mirror_view( device_hier._ap );
+
+    typename CrsHierBase::ordinal_type_array::HostMirror
+      host_aj = Kokkos::create_mirror_view( device_hier._aj );
+
+    typename CrsHierBase::value_type_array::HostMirror
+      host_ax = Kokkos::create_mirror_view( device_hier._ax );
+
+    nnz = 0;
+    for (ordinal_type i=0;i<nblks;++i) {
+      host_ap[i] = nnz;
+      for (ordinal_type j=i;j != -1;++nnz,j=tree[j]) {
+        host_aj[nnz] = j;
+        host_ax[nnz].setView( device_flat, range[i], (range[i+1] - range[i]),
+                             /**/          range[j], (range[j+1] - range[j]));
+
+        // this checking might more expensive 
+        // and attempts to access device memory from the host
+        // if (!host_ax[nnz].countNumNonZeros())
+        //  --nnz;
+      }
+    }
+    
+    host_ap[nblks] = nnz;
+
+    Kokkos::deep_copy( device_hier._ap , host_ap );
+    Kokkos::deep_copy( device_hier._aj , host_aj );
+    Kokkos::deep_copy( device_hier._ax , host_ax );
+
+    device_hier._nnz = nnz;
+
+    return 0;
+  }
+
+  // template<typename CrsFlatBase,
+  //          typename CrsHierBase>
+  // int
+  // CrsMatrixHelper::flat2hier_upper(CrsFlatBase &flat,
+  //                                  CrsHierBase &hier,
+  //                                  const typename CrsHierBase::ordinal_type       nblks,
+  //                                  const typename CrsHierBase::ordinal_type_array range,
+  //                                  const typename CrsHierBase::ordinal_type_array tree) {
+  //   typedef typename CrsHierBase::ordinal_type            ordinal_type;
+  //   typedef typename CrsHierBase::size_type               size_type;
+
+  //   typedef typename CrsHierBase::ordinal_type_array     ordinal_type_array;
+  //   //typedef typename CrsHierBase::ordinal_type_array_ptr ordinal_type_array_ptr;
+  //   //typedef typename CrsHierBase::value_type_array_ptr   value_type_array_ptr;
+
+  //   ordinal_type_array sibling("CrsMatrixHelper::flat2hier_upper::sibling", nblks);
+
+  //   // check the end of adjacent siblings (if not adjacent, they are separators)
+  //   ordinal_type p = tree[0];
+  //   for (ordinal_type i=1;i<nblks;++i) {
+  //     const ordinal_type j = tree[i];
+  //     if (p != j) {
+  //       p = j;
+  //       sibling[i-1] = -1;
+  //     }
+  //   }
+  //   sibling[nblks-1] = -1;
+
+  //   size_type nnz = 0;
+
+  //   // count nnz and nnz in rows for the upper triangular hier matrix
+  //   for (ordinal_type i=0;i<nblks;++i) {                  // search for all rows
+  //     for (ordinal_type j=i;j != -1;j=tree[j]) {          // move up
+  //       ordinal_type k=j;
+  //       do {
+  //         ++nnz;
+  //       } while (sibling[k++] != -1);
+  //     }
+  //   }
+
+  //   // create upper triangular block matrix
+  //   hier.createInternalArrays(nblks, nblks, nnz);
+
+  //   nnz = 0;
+  //   for (ordinal_type i=0;i<nblks;++i) {
+  //     hier._ap[i] = nnz;
+  //     for (ordinal_type j=i;j != -1;j=tree[j]) {
+  //       ordinal_type k=j;
+  //       do {
+  //         hier._aj[nnz] = k;
+  //         hier._ax[nnz].setView( flat, range[i], (range[i+1] - range[i]),
+  //                               /**/   range[k], (range[k+1] - range[k]));
+
+  //         // this checking might more expensive
+  //         if (hier._ax[nnz].hasNumNonZeros())
+  //           ++nnz;
+  //       } while (sibling[k++] != -1);
+  //     }
+  //   }
+  //   hier._ap[nblks] = nnz;
+  //   hier._nnz = nnz;
+
+  //   return 0;
+  // }
+
+  template<typename CrsFlatBase,
+           typename CrsHierBase,
+           typename HostOrdinalTypeArray >
+  int
+  CrsMatrixHelper::flat2hier_lower(CrsFlatBase &flat,
+                                   CrsHierBase &hier,
+                                   const typename CrsHierBase::ordinal_type       nblks,
+                                   const HostOrdinalTypeArray range,
+                                   const HostOrdinalTypeArray tree) {
+    ERROR(MSG_NOT_YET_IMPLEMENTED);
+
+    // typedef typename CrsHierBase::ordinal_type           ordinal_type;
+    // typedef typename CrsHierBase::size_type              size_type;
+
+    // typedef typename CrsHierBase::ordinal_type_array     ordinal_type_array;
+    // //typedef typename CrsHierBase::ordinal_type_array_ptr ordinal_type_array_ptr;
+    // //typedef typename CrsHierBase::value_type_array_ptr   value_type_array_ptr;
+
+    // ordinal_type_array tmp = ordinal_type_array("flat2hier:tmp", nblks+1);
+    // size_type nnz = 0;
+
+    // // count nnz and nnz in rows for lower triangular matrix
+    // for (ordinal_type i=0;i<nblks;++i)
+    //   for (ordinal_type j=i;j != -1;++nnz) {
+    //     ++tmp[j];
+    //     j = tree[j];
+    //   }
+
+    // // count nnz and nnz in rows for lower triangular matrix
+    // hier.createInternalArrays(nblks, nblks, nnz);
+    // for (ordinal_type i=1;i<(nblks+1);++i)
+    //   hier._ap[i] = hier._ap[i-1] + tmp[i-1];
+
+    // for (ordinal_type i=0;i<(nblks+1);++i)
+    //   tmp[i] = hier._ap[i];
+
+    // for (ordinal_type i=0;i<nblks;++i)
+    //   for (ordinal_type j=i;j != -1;j=tree[j]) {
+    //     hier._aj[tmp[j]] = i;
+    //     hier._ax[tmp[j]].setView( flat, range[j], (range[j+1] - range[j]),
+    //                              /**/   range[i], (range[i+1] - range[i]));
+    //     ++tmp[j];
+    //   }
+
+    return 0;
+  }
+
+}
+
+
+#endif
+
diff --git a/lib/kokkos/example/ichol/src/crs_matrix_view.hpp b/lib/kokkos/example/ichol/src/crs_matrix_view.hpp
new file mode 100644
index 0000000000..2a55e6fac9
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/crs_matrix_view.hpp
@@ -0,0 +1,226 @@
+#pragma once
+#ifndef __CRS_MATRIX_VIEW_HPP__
+#define __CRS_MATRIX_VIEW_HPP__
+
+/// \file crs_matrix_view.hpp
+/// \brief CRS matrix view object creates 2D view to setup a computing region.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+
+namespace Tacho { 
+
+  using namespace std;
+
+  template<typename CrsMatBaseType>  
+  class CrsRowView;
+
+  template<typename CrsMatBaseType>
+  class CrsMatrixView {
+  public:
+    typedef typename CrsMatBaseType::space_type    space_type;
+    
+    typedef typename CrsMatBaseType::value_type    value_type;
+    typedef typename CrsMatBaseType::ordinal_type  ordinal_type;
+    typedef typename CrsMatBaseType::size_type     size_type;
+
+    typedef CrsMatBaseType             mat_base_type;
+    typedef CrsRowView<mat_base_type>  row_view_type;
+
+    // be careful this use rcp and atomic operation
+    // - use setView to create a view if _rows is not necessary
+    // - copy constructor and assignment operator will do soft copy of the object
+    typedef Kokkos::View<row_view_type*,space_type,Kokkos::MemoryUnmanaged> row_view_type_array;
+    
+  private:
+    CrsMatBaseType _base;    // shallow copy of the base object
+    ordinal_type  _offm;     // offset in rows
+    ordinal_type  _offn;     // offset in cols
+    ordinal_type  _m;        // # of rows
+    ordinal_type  _n;        // # of cols
+
+    row_view_type_array _rows;
+    
+  public:
+
+    KOKKOS_INLINE_FUNCTION
+    void setRowViewArray( const row_view_type_array & arg_rows )
+      {
+        _rows = arg_rows ;
+
+        for (ordinal_type i=0;i<_m;++i) {
+          _rows[i].setView(*this, i);
+        }
+      }
+
+    KOKKOS_INLINE_FUNCTION
+    row_view_type& RowView(const ordinal_type i) const { return _rows[i]; }
+
+    KOKKOS_INLINE_FUNCTION
+    void setView(const CrsMatBaseType &base,
+                 const ordinal_type offm, const ordinal_type m,
+                 const ordinal_type offn, const ordinal_type n) {
+      _base = base;
+
+      _offm = offm; _m = m;
+      _offn = offn; _n = n;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    const CrsMatBaseType & BaseObject() const { return _base; }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type  OffsetRows() const { return _offm; }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type  OffsetCols() const { return _offn; }
+
+    KOKKOS_INLINE_FUNCTION    
+    ordinal_type  NumRows() const { return _m; }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type  NumCols() const { return _n; }
+
+    KOKKOS_INLINE_FUNCTION
+    bool hasNumNonZeros() const { 
+      const ordinal_type m = NumRows();
+      for (ordinal_type i=0;i<m;++i) {
+        row_view_type row;
+        row.setView(*this, i);
+        if (row.NumNonZeros()) return true;
+      }
+      return false;
+    }
+
+    inline
+    size_type countNumNonZeros() const { 
+      size_type nnz = 0;
+      const ordinal_type m = NumRows();
+      for (ordinal_type i=0;i<m;++i) {
+        row_view_type row;
+        row.setView(*this, i);
+        nnz += row.NumNonZeros();
+      }
+      return nnz; 
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    CrsMatrixView()
+      : _base(),
+        _offm(0),
+        _offn(0),
+        _m(0),
+        _n(0),
+        _rows()
+    { } 
+
+    KOKKOS_INLINE_FUNCTION
+    CrsMatrixView(const CrsMatrixView &b)
+      : _base(b._base),
+        _offm(b._offm),
+        _offn(b._offn),
+        _m(b._m),
+        _n(b._n),
+        _rows(b._rows)
+    { } 
+
+    KOKKOS_INLINE_FUNCTION
+    CrsMatrixView(const CrsMatBaseType & b)
+      : _base(b),
+        _offm(0),
+        _offn(0),
+        _m(b.NumRows()),
+        _n(b.NumCols()),
+        _rows()
+    { } 
+
+    CrsMatrixView(const CrsMatBaseType & b,
+                  const ordinal_type offm, const ordinal_type m,
+                  const ordinal_type offn, const ordinal_type n) 
+      : _base(b),
+        _offm(offm),
+        _offn(offn),
+        _m(m),
+        _n(n),
+        _rows()
+    { } 
+
+    ostream& showMe(ostream &os) const {
+      const int w = 4;
+      os << "CrsMatrixView, "
+         << " Offs ( " << setw(w) << _offm << ", " << setw(w) << _offn << " ); "
+         << " Dims ( " << setw(w) << _m    << ", " << setw(w) << _n    << " ); "
+         << " NumNonZeros = " << countNumNonZeros() << ";";
+
+      return os;
+    }
+
+  };
+}
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if ! KOKKOS_USING_EXP_VIEW
+
+namespace Kokkos {
+  namespace Impl {
+    
+    //  The Kokkos::View allocation will by default assign each allocated datum to zero.
+    //  This is not the required initialization behavior when
+    //  Tacho::CrsRowView and Tacho::CrsMatrixView
+    //  are used within a Kokkos::View.
+    //  Create a partial specialization of the Kokkos::Impl::AViewDefaultConstruct
+    //  to replace the assignment initialization with placement new initialization.
+    //
+    //  This work-around is necessary until a TBD design refactorization of Kokkos::View.
+    
+    template< class ExecSpace , typename T >
+    struct ViewDefaultConstruct< ExecSpace , Tacho::CrsRowView<T> , true >
+    {
+      typedef Tacho::CrsRowView<T> type ;
+      type * const m_ptr ;
+      
+      KOKKOS_FORCEINLINE_FUNCTION
+      void operator()( const typename ExecSpace::size_type& i ) const
+      { new(m_ptr+i) type(); }
+      
+      ViewDefaultConstruct( type * pointer , size_t capacity )
+        : m_ptr( pointer )
+      {
+        Kokkos::RangePolicy< ExecSpace > range( 0 , capacity );
+        parallel_for( range , *this );
+        ExecSpace::fence();
+      }
+    };
+    
+    template< class ExecSpace , typename T >
+    struct ViewDefaultConstruct< ExecSpace , Tacho::CrsMatrixView<T> , true >
+    {
+      typedef Tacho::CrsMatrixView<T> type ;
+      type * const m_ptr ;
+      
+      KOKKOS_FORCEINLINE_FUNCTION
+      void operator()( const typename ExecSpace::size_type& i ) const
+      { new(m_ptr+i) type(); }
+      
+      ViewDefaultConstruct( type * pointer , size_t capacity )
+        : m_ptr( pointer )
+      {
+        Kokkos::RangePolicy< ExecSpace > range( 0 , capacity );
+        parallel_for( range , *this );
+        ExecSpace::fence();
+      }
+    };
+
+  } // namespace Impl
+} // namespace Kokkos
+
+#endif /* #if ! KOKKOS_USING_EXP_VIEW */
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/crs_row_view.hpp b/lib/kokkos/example/ichol/src/crs_row_view.hpp
new file mode 100644
index 0000000000..8556bcb9e6
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/crs_row_view.hpp
@@ -0,0 +1,185 @@
+#pragma once
+#ifndef __CRS_ROW_VIEW_HPP__
+#define __CRS_ROW_VIEW_HPP__
+
+/// \file crs_row_view.hpp
+/// \brief A view to a row extracted from CrsMatrixView.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho { 
+
+  using namespace std;
+
+  /// \class CrsRowView
+  template<typename CrsMatBaseType>
+  class CrsRowView {
+  public:
+    typedef typename CrsMatBaseType::ordinal_type           ordinal_type;
+    typedef typename CrsMatBaseType::value_type             value_type;
+    typedef typename CrsMatBaseType::ordinal_type_array_ptr ordinal_type_array_ptr;
+    typedef typename CrsMatBaseType::value_type_array_ptr   value_type_array_ptr;
+    
+  private:
+    // row info
+    ordinal_type _offn, _n;    
+
+    // this assumes a contiguous memory buffer
+    ordinal_type_array_ptr _aj, _ajn; // column index compressed format in row
+    value_type_array_ptr   _ax;                // values 
+
+    static KOKKOS_INLINE_FUNCTION
+    typename CrsMatBaseType::ordinal_type_array_ptr
+    lower_bound( typename CrsMatBaseType::ordinal_type_array_ptr begin ,
+                 typename CrsMatBaseType::ordinal_type_array_ptr const end ,
+                 typename CrsMatBaseType::ordinal_type           const val )
+      {
+         typename CrsMatBaseType::ordinal_type_array_ptr it = begin ;
+         int count = end - begin ;
+         int step = 0 ;
+         while (count>0) {
+           it = begin ;
+           it += ( step = (count >> 1) );
+           if (*it<val) {
+             begin=++it;
+             count-=step+1;
+           }
+           else { count=step; }
+         }
+         return begin;
+      }
+
+  public:
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type OffsetCols() const { return _offn; }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type NumCols() const { return _n; }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type NumNonZeros() const { return _ajn - _aj; } 
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type Col(const ordinal_type j) const { return _aj[j] - _offn; }
+
+    KOKKOS_INLINE_FUNCTION
+    value_type& Value(const ordinal_type j) { return _ax[j]; }
+
+    KOKKOS_INLINE_FUNCTION
+    value_type Value(const ordinal_type j) const { return _ax[j]; }
+    
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type Index(const ordinal_type col ) const {
+      const ordinal_type loc = _offn + col ;
+      // binary search
+      ordinal_type_array_ptr aj = CrsRowView::lower_bound(_aj, _ajn, loc);
+
+      // if found, return index for the location, 
+      // otherwise return -1 (not found), -2 (end of array)
+      return (aj < _ajn ? (*aj == loc ? aj - _aj : -1) : -2);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    ordinal_type Index(const ordinal_type col,
+                       const ordinal_type prev ) const {
+      const ordinal_type loc = _offn + col;
+      ordinal_type_array_ptr aj = _aj + prev;
+
+      // binary search
+      // aj = lower_bound(aj, _ajn, loc);
+
+      // linear search from prev: this gains about 45 % faster
+      for ( ;aj < _ajn && *aj<loc; ++aj); 
+
+      // if found, return index for the location, 
+      // otherwise return -1 (not found), -2 (end of array)
+      return (aj < _ajn ? (*aj == loc ? aj - _aj : -1) : -2);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    value_type ValueAtColumn(const ordinal_type col) const {
+      const ordinal_type j = Index(col);
+      return (j < 0 ? value_type(0) : _ax[j]);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    CrsRowView()
+      : _offn(0),
+        _n(0),
+        _aj(),
+        _ajn(),
+        _ax() 
+    { }
+
+
+    KOKKOS_INLINE_FUNCTION
+    CrsRowView(const ordinal_type           offn,
+               const ordinal_type           n,
+               const ordinal_type_array_ptr aj,
+               const ordinal_type_array_ptr ajn,
+               const value_type_array_ptr   ax) 
+      : _offn(offn),
+        _n(n),
+        _aj(aj),
+        _ajn(ajn),
+        _ax(ax) 
+    { }
+
+    KOKKOS_INLINE_FUNCTION
+    CrsRowView(const CrsMatrixView<CrsMatBaseType> &A, 
+               const ordinal_type i) {
+      this->setView(A, i);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    CrsRowView(const CrsMatBaseType &A, 
+               const ordinal_type i) {
+      this->setView(A, i);
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void setView(const CrsMatrixView<CrsMatBaseType> &A, 
+                 const ordinal_type i) {
+      _offn = A.OffsetCols();
+      _n    = A.NumCols();
+
+      const ordinal_type ii = A.OffsetRows() + i;
+
+      const typename CrsMatBaseType::ordinal_type_array_ptr cols = A.BaseObject().ColsInRow(ii);
+      const typename CrsMatBaseType::ordinal_type_array_ptr next = A.BaseObject().ColsInRow(ii+1);
+      const typename CrsMatBaseType::value_type_array_ptr   vals = A.BaseObject().ValuesInRow(ii);
+
+      // [cols..next) is sorted so a log(N) search could performed
+      _aj  = CrsRowView::lower_bound(cols, next, _offn);
+      _ajn = CrsRowView::lower_bound(_aj,  next, _offn+_n);
+
+      _ax  = &vals[_aj - cols];
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    void setView(const CrsMatBaseType &A, 
+                 const ordinal_type i) {
+      _offn = 0;
+      _n    = A.NumCols();
+      _aj   = A.ColsInRow(i);
+      _ajn  = A.ColsInRow(i+1);
+      _ax   = A.ValuesInRow(i);
+    }
+
+    ostream& showMe(ostream &os) const {                                                
+      const ordinal_type nnz = NumNonZeros();
+      const ordinal_type offset = OffsetCols();
+      os << "  offset = " << offset
+         << ", nnz = " << nnz
+         << endl; 
+      for (ordinal_type j=0;j<nnz;++j) {
+        const value_type val = _ax[j];
+        os << "(" << Col(j) << ", "
+           << val << ")"
+           << endl;
+      }
+      return os;
+    }
+  };
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/dot.hpp b/lib/kokkos/example/ichol/src/dot.hpp
new file mode 100644
index 0000000000..acf927e068
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/dot.hpp
@@ -0,0 +1,74 @@
+#pragma once
+#ifndef __DOT_HPP__
+#define __DOT_HPP__
+
+/// \file dot.hpp
+/// \brief Sparse dot product.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+/// dot_type result = x^H y
+
+namespace Tacho { 
+
+  using namespace std;
+
+  template<typename T> struct DotTraits {
+    typedef T dot_type;
+
+    static KOKKOS_FORCEINLINE_FUNCTION 
+    dot_type 
+    // dot(const T &x, const T &y) { return conj<T>(x)*y; }
+    dot(const T &x, const T &y) { return x*y; }
+  }; 
+
+  template<typename CrsRowViewType>
+  KOKKOS_INLINE_FUNCTION 
+  typename CrsRowViewType::value_type
+  dot(const CrsRowViewType x, const CrsRowViewType y) {
+    typedef typename CrsRowViewType::ordinal_type ordinal_type;
+    typedef typename CrsRowViewType::value_type   value_type;
+
+    typedef DotTraits<value_type> dot_traits;
+
+    value_type r_val(0);
+
+    const ordinal_type nnz_x = x.NumNonZeros();
+    const ordinal_type nnz_y = y.NumNonZeros();
+
+    for (ordinal_type jx=0, jy=0;jx<nnz_x && jy<nnz_y;) {
+      const ordinal_type diff = x.Col(jx) - y.Col(jy);
+      const ordinal_type sign = (0 < diff) - (diff < 0);
+      switch (sign) {
+      case  0:
+        r_val += dot_traits::dot(x.Value(jx++), y.Value(jy++));
+        break;
+      case -1: ++jx; break;
+      case  1: ++jy; break;
+      }
+    }
+    
+    return r_val;
+  }
+
+  template<typename CrsRowViewType>
+  KOKKOS_INLINE_FUNCTION 
+  typename CrsRowViewType::value_type
+  dot(const CrsRowViewType x) {
+    typedef typename CrsRowViewType::ordinal_type ordinal_type;
+    typedef typename CrsRowViewType::value_type   value_type;
+
+    typedef DotTraits<value_type> dot_traits;
+
+    value_type r_val(0);
+
+    const ordinal_type nnz = x.NumNonZeros();
+
+    for (ordinal_type j=0;j<nnz;++j) 
+      r_val += dot_traits::dot(x.Value(j), x.Value(j));
+    
+    return r_val;
+  }
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/gemm.hpp b/lib/kokkos/example/ichol/src/gemm.hpp
new file mode 100644
index 0000000000..33c6058ec6
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/gemm.hpp
@@ -0,0 +1,99 @@
+#pragma once
+#ifndef __GEMM_HPP__
+#define __GEMM_HPP__
+
+/// \file gemm.hpp
+/// \brief Sparse matrix-matrix multiplication on given sparse patterns.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+#include "control.hpp"
+#include "partition.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<int ArgTransA, int ArgTransB, int ArgAlgo,
+           int ArgVariant = Variant::One,
+           template<int,int> class ControlType = Control>
+  struct Gemm {
+
+    // data-parallel interface
+    // =======================
+    template<typename ScalarType,
+             typename ExecViewTypeA,
+             typename ExecViewTypeB,
+             typename ExecViewTypeC>
+    KOKKOS_INLINE_FUNCTION
+    static int invoke(typename ExecViewTypeA::policy_type &policy,
+                      const typename ExecViewTypeA::policy_type::member_type &member,
+                      const ScalarType alpha,
+                      typename ExecViewTypeA::matrix_type &A,
+                      typename ExecViewTypeB::matrix_type &B,
+                      const ScalarType beta,
+                      typename ExecViewTypeC::matrix_type &C);
+
+    // task-data parallel interface
+    // ============================
+    template<typename ScalarType,
+             typename ExecViewTypeA,
+             typename ExecViewTypeB,
+             typename ExecViewTypeC>
+    class TaskFunctor {
+    public:
+      typedef typename ExecViewTypeA::policy_type policy_type;
+      typedef typename policy_type::member_type member_type;
+      typedef int value_type;
+
+    private:
+      ScalarType _alpha, _beta;
+      typename ExecViewTypeA::matrix_type _A;
+      typename ExecViewTypeB::matrix_type _B;
+      typename ExecViewTypeC::matrix_type _C;
+
+      policy_type _policy;
+
+    public:
+      KOKKOS_INLINE_FUNCTION
+      TaskFunctor(const policy_type & P,
+                  const ScalarType alpha,
+                  const typename ExecViewTypeA::matrix_type & A,
+                  const typename ExecViewTypeB::matrix_type & B,
+                  const ScalarType beta,
+                  const typename ExecViewTypeC::matrix_type & C)
+        : _alpha(alpha),
+          _beta(beta),
+          _A(A),
+          _B(B),
+          _C(C),
+          _policy(P)
+      { }
+
+      string Label() const { return "Gemm"; }
+
+      // task execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(value_type &r_val) {
+        r_val = Gemm::invoke<ScalarType,ExecViewTypeA,ExecViewTypeB,ExecViewTypeC>(_policy, _policy.member_single(),
+                             _alpha, _A, _B, _beta, _C);
+      }
+
+      // task-data execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(const member_type &member, value_type &r_val) {
+        r_val = Gemm::invoke<ScalarType,ExecViewTypeA,ExecViewTypeB,ExecViewTypeC>(_policy, member,
+                             _alpha, _A, _B, _beta, _C);
+      }
+
+    };
+
+  };
+
+}
+
+
+// #include "gemm_nt_nt.hpp"
+#include "gemm_ct_nt.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/gemm_ct_nt.hpp b/lib/kokkos/example/ichol/src/gemm_ct_nt.hpp
new file mode 100644
index 0000000000..13d2518cab
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/gemm_ct_nt.hpp
@@ -0,0 +1,12 @@
+#pragma once
+#ifndef __GEMM_CT_NT_HPP__
+#define __GEMM_CT_NT_HPP__
+
+/// \file gemm_ct_nt.hpp
+/// \brief Sparse matrix-matrix multiplication on given sparse patterns.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "gemm_ct_nt_for_factor_blocked.hpp"
+// #include "gemm_ct_nt_for_tri_solve_blocked.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/gemm_ct_nt_for_factor_blocked.hpp b/lib/kokkos/example/ichol/src/gemm_ct_nt_for_factor_blocked.hpp
new file mode 100644
index 0000000000..88a4658482
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/gemm_ct_nt_for_factor_blocked.hpp
@@ -0,0 +1,108 @@
+#pragma once
+#ifndef __GEMM_CT_NT_FOR_FACTOR_BLOCKED_HPP__
+#define __GEMM_CT_NT_FOR_FACTOR_BLOCKED_HPP__
+
+/// \file gemm_ct_nt_for_factor_blocked.hpp
+/// \brief Sparse matrix-matrix multiplication on given sparse patterns.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho {
+
+  using namespace std;
+
+  // Gemm used in the factorization phase
+  // ====================================
+  template<>
+  template<typename ScalarType,
+           typename CrsExecViewTypeA,
+           typename CrsExecViewTypeB,
+           typename CrsExecViewTypeC>
+  KOKKOS_INLINE_FUNCTION
+  int
+  Gemm<Trans::ConjTranspose,Trans::NoTranspose,
+       AlgoGemm::ForFactorBlocked>
+  ::invoke(typename CrsExecViewTypeA::policy_type &policy,
+           const typename CrsExecViewTypeA::policy_type::member_type &member,
+           const ScalarType alpha,
+           typename CrsExecViewTypeA::matrix_type &A,
+           typename CrsExecViewTypeB::matrix_type &B,
+           const ScalarType beta,
+           typename CrsExecViewTypeC::matrix_type &C) {
+    typedef typename CrsExecViewTypeA::ordinal_type      ordinal_type;
+    typedef typename CrsExecViewTypeA::value_type        value_type;
+    typedef typename CrsExecViewTypeA::row_view_type     row_view_type;
+
+
+if ( false && member.team_rank() == 0 ) {
+ printf("Gemm [%d +%d)x[%d +%d)\n"
+       , C.OffsetRows()
+       , C.NumRows()
+       , C.OffsetCols()
+       , C.NumCols()
+       );
+}
+
+    // scale the matrix C with beta
+    scaleCrsMatrix<ScalarType,CrsExecViewTypeC>(member, beta, C);
+
+    // Sparse matrix-matrix multiply:
+    // C(i,j) += alpha*A'(i,k)*B(k,j)
+
+    const ordinal_type mA = A.NumRows();
+    for (ordinal_type k=0;k<mA;++k) {
+      row_view_type &a = A.RowView(k);
+      const ordinal_type nnz_a = a.NumNonZeros();
+
+      row_view_type &b = B.RowView(k);
+      const ordinal_type nnz_b = b.NumNonZeros();
+
+      if (nnz_a > 0 && nnz_b > 0 ) {
+#if 0
+        Kokkos::parallel_for(
+          Kokkos::TeamThreadRange(member, 0, nnz_a),
+          [&](const ordinal_type i) {
+             const ordinal_type row_at_i  = a.Col(i);
+             const value_type   val_at_ik = a.Value(i);
+             // const value_type   val_at_ik = conj(a.Value(i));
+
+             row_view_type &c = C.RowView(row_at_i);
+
+             ordinal_type idx = 0;
+             for (ordinal_type j=0;j<nnz_b && (idx > -2);++j) {
+                const ordinal_type col_at_j  = b.Col(j);
+                const value_type   val_at_kj = b.Value(j);
+
+                idx = c.Index(col_at_j, idx);
+                if (idx >= 0)
+                  c.Value(idx) += alpha*val_at_ik*val_at_kj;
+                }
+          });
+#else
+        Kokkos::parallel_for(
+          Kokkos::TeamThreadRange(member, 0, nnz_a * nnz_b ),
+          [&](const ordinal_type ii) {
+             const ordinal_type i = ii / nnz_a ;
+             const ordinal_type j = ii % nnz_a ;
+
+             row_view_type &c = C.RowView( a.Col(i) );
+
+             // Binary search for c's index of b.Col(j)
+             const ordinal_type idx = c.Index( b.Col(j) );
+
+             if (idx >= 0) {
+               // const value_type   val_at_ik = conj(a.Value(i));
+               c.Value(idx) += alpha * a.Value(i) * b.Value(j);
+             }
+          });
+#endif
+
+        member.team_barrier();
+      }
+    }
+
+    return 0;
+  }
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/graph_helper_scotch.hpp b/lib/kokkos/example/ichol/src/graph_helper_scotch.hpp
new file mode 100644
index 0000000000..d2dd004579
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/graph_helper_scotch.hpp
@@ -0,0 +1,427 @@
+#pragma once
+#ifndef __GRAPH_HELPER_SCOTCH_HPP__
+#define __GRAPH_HELPER_SCOTCH_HPP__
+
+/// \file graph_helper_scotch.hpp
+/// \brief Interface to scotch reordering
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "scotch.h"
+#include "util.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<class CrsMatBaseType>
+  class GraphHelper_Scotch : public Disp {
+  public:
+    typedef typename CrsMatBaseType::ordinal_type ordinal_type;
+    typedef typename CrsMatBaseType::size_type    size_type;
+
+    typedef typename CrsMatBaseType::ordinal_type_array ordinal_type_array;
+    typedef typename CrsMatBaseType::size_type_array    size_type_array;
+
+  private:
+    string _label;
+
+    // scotch main data structure
+    SCOTCH_Graph _graph;
+    SCOTCH_Num _strat;
+    int _level;
+
+    // scotch input has no diagonal contribution
+    ordinal_type _base,_m;
+    ordinal_type_array _cidx;
+
+    size_type _nnz;
+    size_type_array _rptr;
+
+    // scotch output
+    ordinal_type _cblk;
+    ordinal_type_array _perm,_peri,_range,_tree;
+
+    // status flag
+    bool _is_ordered;
+
+  public:
+
+    void setLabel(string label) { _label = label; }
+    string Label() const { return _label; }
+
+    size_type NumNonZeros() const { return _nnz; }
+    ordinal_type NumRows() const { return _m; }
+
+    size_type_array RowPtrVector() const { return _rptr; }
+    ordinal_type_array ColIndexVector() const { return _cidx; }
+
+    ordinal_type_array PermVector()    const { return _perm; }
+    ordinal_type_array InvPermVector() const { return _peri; }
+
+    ordinal_type_array RangeVector()   const { return _range; }
+    ordinal_type_array TreeVector()    const { return _tree; }
+
+    ordinal_type NumBlocks() const { return _cblk; }
+
+    GraphHelper_Scotch() = default;
+
+    // convert graph first
+    GraphHelper_Scotch(const string label,
+                       const ordinal_type m,
+                       const size_type_array rptr,
+                       const ordinal_type_array cidx,
+                       const int seed = GraphHelper::DefaultRandomSeed) {
+
+      _label = "GraphHelper_Scotch::" + label;
+
+      _is_ordered = false;
+      _cblk  = 0;
+
+      // scotch does not allow self-contribution (diagonal term in sparse matrix)
+      _base  = 0; //A.BaseVal();
+      _m     = m; // A.NumRows();
+      _nnz   = rptr[m]; //A.NumNonZeros();
+
+      _rptr  = rptr; //size_type_array(_label+"::RowPtrArray", _m+1);
+      _cidx  = cidx; //ordinal_type_array(_label+"::ColIndexArray", _nnz);
+
+      _perm  = ordinal_type_array(_label+"::PermutationArray", _m);
+      _peri  = ordinal_type_array(_label+"::InvPermutationArray", _m);
+      _range = ordinal_type_array(_label+"::RangeArray", _m);
+      _tree  = ordinal_type_array(_label+"::TreeArray", _m);
+
+      // create a graph structure without diagonals
+      _strat = 0;
+      _level = 0;
+
+      //A.convertGraph(_nnz, _rptr, _cidx);
+
+      int ierr = 0;
+      ordinal_type *rptr_ptr = reinterpret_cast<ordinal_type*>(_rptr.ptr_on_device());
+      ordinal_type *cidx_ptr = reinterpret_cast<ordinal_type*>(_cidx.ptr_on_device());
+
+      if (seed != GraphHelper::DefaultRandomSeed) {
+        SCOTCH_randomSeed(seed);
+        SCOTCH_randomReset();
+      }
+
+      ierr = SCOTCH_graphInit(&_graph);CHKERR(ierr);
+      ierr = SCOTCH_graphBuild(&_graph,             // scotch graph
+                               _base,               // base value
+                               _m,                  // # of vertices
+                               rptr_ptr,                // column index array pointer begin
+                               rptr_ptr+1,              // column index array pointer end
+                               NULL,                // weights on vertices (optional)
+                               NULL,                // label array on vertices (optional)
+                               _nnz,                // # of nonzeros
+                               cidx_ptr,                // column index array
+                               NULL);CHKERR(ierr);  // edge load array (optional)
+      ierr = SCOTCH_graphCheck(&_graph);CHKERR(ierr);
+    }
+    GraphHelper_Scotch(const GraphHelper_Scotch &b) = default;
+
+    virtual~GraphHelper_Scotch() {
+      SCOTCH_graphFree(&_graph);
+    }
+
+    void setStratGraph(const SCOTCH_Num strat = 0) {
+      _strat = strat;
+    }
+
+    void setTreeLevel(const int level = 0) {
+      _level = level;
+    }
+
+    int computeOrdering(const ordinal_type treecut = 0,
+                        const ordinal_type minblksize = 0) {
+      int ierr = 0;
+
+      // pointers for global graph ordering
+      ordinal_type *perm  = _perm.ptr_on_device();
+      ordinal_type *peri  = _peri.ptr_on_device();
+      ordinal_type *range = _range.ptr_on_device();
+      ordinal_type *tree  = _tree.ptr_on_device();
+
+      {
+        const int level = (_level ? _level : max(1, int(log2(_m)-treecut))); // level = log2(_nnz)+10;
+        SCOTCH_Strat stradat;
+        SCOTCH_Num straval = _strat;
+                              //(SCOTCH_STRATLEVELMAX));//   |
+                              //SCOTCH_STRATLEVELMIN   |
+                              //SCOTCH_STRATLEAFSIMPLE |
+                              //SCOTCH_STRATSEPASIMPLE);
+
+        ierr = SCOTCH_stratInit(&stradat);CHKERR(ierr);
+
+        // if both are zero, do not run strategy
+        if (_strat || _level) {
+          cout << "GraphHelper_Scotch:: User provide a strategy and/or level" << endl
+               << "                     strategy = " << _strat << ", level =  " << _level << endl;
+          ierr = SCOTCH_stratGraphOrderBuild (&stradat, straval, level, 0.2);CHKERR(ierr);
+        }
+        ierr = SCOTCH_graphOrder(&_graph,
+                                 &stradat,
+                                 perm,
+                                 peri,
+                                 &_cblk,
+                                 range,
+                                 tree);CHKERR(ierr);
+        SCOTCH_stratExit(&stradat);
+      }
+
+#if 0
+      {
+        // assume there are multiple roots
+        range[_cblk+1] = range[_cblk]; // dummy range
+        tree[_cblk] = -1;              // dummy root
+        for (ordinal_type i=0;i<_cblk;++i)
+          if (tree[i] == -1)           // multiple roots becomes children of the hummy root
+            tree[i] = (_cblk+1);
+        ++_cblk;                       // include the dummy root
+      }
+#endif
+
+      // provided blksize is greater than 0, reorder internally
+      // if (treecut > 0 && minblksize > 0) {
+      //   // graph array
+      //   ordinal_type *rptr_ptr = reinterpret_cast<ordinal_type*>(_rptr.ptr_on_device());
+      //   ordinal_type *cidx_ptr = reinterpret_cast<ordinal_type*>(_cidx.ptr_on_device());
+
+      //   // create workspace in
+      //   size_type_array    rptr_work = size_type_array(_label+"::Block::RowPtrArray", _m+1);
+      //   ordinal_type_array cidx_work = ordinal_type_array(_label+"::Block::ColIndexArray", _nnz);
+
+      //   // create workspace output
+      //   ordinal_type_array perm_work  = ordinal_type_array(_label+"::Block::PermutationArray", _m);
+      //   ordinal_type_array peri_work  = ordinal_type_array(_label+"::Block::InvPermutationArray", _m);
+      //   ordinal_type_array range_work = ordinal_type_array(_label+"::Block::RangeArray", _m);
+      //   ordinal_type_array tree_work  = ordinal_type_array(_label+"::Block::TreeArray", _m);
+
+      //   // scotch input
+      //   ordinal_type *rptr_blk = reinterpret_cast<ordinal_type*>(rptr_work.ptr_on_device());
+      //   ordinal_type *cidx_blk = reinterpret_cast<ordinal_type*>(cidx_work.ptr_on_device());
+
+      //   size_type nnz = 0;
+      //   rptr_blk[0] = nnz;
+
+      //   for (ordinal_type iblk=0;iblk<_cblk;++iblk) {
+      //     // allocate graph
+      //     SCOTCH_Graph graph;
+
+      //     ierr = SCOTCH_graphInit(&graph);CHKERR(ierr);
+
+      //     SCOTCH_Strat stradat;
+      //     SCOTCH_Num straval = (/*SCOTCH_STRATLEVELMAX   |
+      //                             SCOTCH_STRATLEVELMIN   |*/
+      //                           SCOTCH_STRATLEAFSIMPLE |
+      //                           SCOTCH_STRATSEPASIMPLE);
+
+      //     ierr = SCOTCH_stratInit(&stradat);CHKERR(ierr);
+      //     ierr = SCOTCH_stratGraphOrderBuild(&stradat, straval, 0, 0.2);CHKERR(ierr);
+
+      //     const ordinal_type ibegin = range[iblk], iend = range[iblk+1], m = iend - ibegin;
+
+      //     // scotch output
+      //     ordinal_type cblk_blk = 0;
+
+      //     ordinal_type *perm_blk  = perm_work.ptr_on_device()  + ibegin;
+      //     ordinal_type *peri_blk  = peri_work.ptr_on_device()  + ibegin;
+      //     ordinal_type *range_blk = range_work.ptr_on_device() + ibegin;
+      //     ordinal_type *tree_blk  = tree_work.ptr_on_device()  + ibegin;
+
+      //     // if each blk is greater than the given minblksize, reorder internally
+      //     if (m > minblksize) {
+      //       for (int i=ibegin;i<iend;++i) {
+      //         const ordinal_type ii = peri[i];
+      //         const ordinal_type jbegin = rptr_ptr[ii];
+      //         const ordinal_type jend = rptr_ptr[ii+1];
+
+      //         for (int j=jbegin;j<jend;++j) {
+      //           const ordinal_type jj = perm[cidx_ptr[j]];
+      //           if (ibegin <= jj && jj < iend)
+      //             cidx_blk[nnz++] = (jj - ibegin);
+      //         }
+      //         rptr_blk[i+1] = nnz;
+      //       }
+      //       const size_type nnz_blk = nnz - rptr_blk[ibegin];
+
+      //       ierr = SCOTCH_graphBuild(&graph,             // scotch graph
+      //                                0,                  // base value
+      //                                m,                  // # of vertices
+      //                                &rptr_blk[ibegin],  // column index array pointer begin
+      //                                &rptr_blk[ibegin]+1,// column index array pointer end
+      //                                NULL,               // weights on vertices (optional)
+      //                                NULL,               // label array on vertices (optional)
+      //                                nnz_blk,            // # of nonzeros
+      //                                cidx_blk,           // column index array
+      //                                NULL);CHKERR(ierr); // edge load array (optional)
+      //       ierr = SCOTCH_graphCheck(&graph);CHKERR(ierr);
+      //       ierr = SCOTCH_graphOrder(&graph,
+      //                                &stradat,
+      //                                perm_blk,
+      //                                peri_blk,
+      //                                &cblk_blk,
+      //                                range_blk,
+      //                                tree_blk);CHKERR(ierr);
+      //     } else {
+      //       for (ordinal_type i=0;i<m;++i) {
+      //         perm_blk[i] = i;
+      //         peri_blk[i] = i;
+      //       }
+      //       range_blk[1] = m;
+      //       tree_blk[0] = -1;
+      //     }
+
+      //     SCOTCH_stratExit(&stradat);
+      //     SCOTCH_graphFree(&graph);
+
+      //     for (ordinal_type i=0;i<m;++i) {
+      //       const ordinal_type ii = peri_blk[i] + ibegin;
+      //       peri_blk[i] = peri[ii];
+      //     }
+      //     for (ordinal_type i=0;i<m;++i) {
+      //       const ordinal_type ii = i + ibegin;
+      //       peri[ii] = peri_blk[i];
+      //     }
+
+      //   }
+
+      //   for (ordinal_type i=0;i<_m;++i)
+      //     perm[peri[i]] = i;
+      // }
+
+      _is_ordered = true;
+
+      //cout << "SCOTCH level = " << level << endl;
+      //cout << "Range   Tree " << endl;
+      //for (int i=0;i<_cblk;++i)
+      //  cout << _range[i] << " :: " << i << " " << _tree[i] << endl;
+
+      return 0;
+    }
+
+    int pruneTree(const ordinal_type cut) {
+      if (cut <=0 ) return 0;
+
+      ordinal_type_array work = ordinal_type_array(_label+"::WorkArray", _cblk+1);
+      for (ordinal_type iter=0;iter<cut && _cblk > 1;++iter) {
+        // horizontal merging
+        {
+          ordinal_type cnt = 0;
+          ordinal_type parent = _tree[0];
+          work[0] = cnt;
+          for (ordinal_type i=1;i<_cblk;++i) {
+            const ordinal_type myparent = _tree[i];
+            if (myparent == parent) {
+              work[i] = cnt;
+            } else {
+              parent = _tree[i];
+              work[i] = ++cnt;
+            }
+          }
+          work[_cblk] = ++cnt;
+
+          ordinal_type prev = -2;
+          const ordinal_type root = _cblk - 1;
+          for (ordinal_type i=0;i<root;++i) {
+            const ordinal_type myparent = _tree[i];
+            const ordinal_type me = work[i];
+
+            _tree[me] = work[myparent];
+            if (prev != me) {
+              _range[me] = _range[i];
+              prev = me;
+            }
+          }
+          {
+            const ordinal_type me = work[root];
+            _tree[me] = -1;
+            _range[me] = _range[root];
+
+            _range[work[root+1]] = _range[root+1];
+            _cblk = cnt;
+          }
+        }
+
+        // vertical merging
+        if (_cblk == 2) {
+          _tree[0] = -1;
+          _range[0] = 0;
+          _range[1] = _range[2];
+          _cblk = 1;
+        } else {
+          ordinal_type cnt = 0;
+          for (ordinal_type i=0;i<_cblk;++i) {
+            const ordinal_type diff = _tree[i+1] - _tree[i];
+            work[i] = (diff == 1 ? cnt : cnt++);
+          }
+          work[_cblk] = cnt;
+
+          ordinal_type prev = -2;
+          const ordinal_type root = _cblk - 1;
+          for (ordinal_type i=0;i<root;++i) {
+            const ordinal_type myparent = _tree[i];
+            const ordinal_type me = work[i];
+
+            _tree[me] = work[myparent];
+            if (prev != me) {
+              _range[me] = _range[i];
+              prev = me;
+            }
+          }
+          {
+            const ordinal_type me = work[root];
+            _tree[me] = -1;
+            _range[me] = _range[root];
+
+            _range[work[root+1]] = _range[root+1];
+            _cblk = cnt;
+          }
+        }
+      }
+
+      // cleaning
+      {
+        for (ordinal_type i=(_cblk+1);i<_m;++i) {
+          _tree[i] = 0;
+          _range[i] = 0;
+        }
+        _tree[_cblk] = 0;
+      }
+
+      return 0;
+    }
+
+    ostream& showMe(ostream &os) const {
+      streamsize prec = os.precision();
+      os.precision(15);
+      os << scientific;
+
+      os << " -- Scotch input -- " << endl
+         << "    Base Value     = " << _base << endl
+         << "    # of Rows      = " << _m << endl
+         << "    # of NonZeros  = " << _nnz << endl;
+
+      if (_is_ordered)
+        os << " -- Ordering -- " << endl
+           << "    CBLK   = " << _cblk << endl
+           << "  PERM     PERI     RANG     TREE" << endl;
+
+      const int w = 6;
+      for (ordinal_type i=0;i<_m;++i)
+        os << setw(w) << _perm[i] << "   "
+           << setw(w) << _peri[i] << "   "
+           << setw(w) << _range[i] << "   "
+           << setw(w) << _tree[i] << endl;
+
+      os.unsetf(ios::scientific);
+      os.precision(prec);
+
+      return os;
+    }
+
+  };
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/herk.hpp b/lib/kokkos/example/ichol/src/herk.hpp
new file mode 100644
index 0000000000..548c495c44
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/herk.hpp
@@ -0,0 +1,91 @@
+#pragma once
+#ifndef __HERK_HPP__
+#define __HERK_HPP__
+
+/// \file herk.hpp
+/// \brief Sparse hermitian rank one update on given sparse patterns.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+#include "control.hpp"
+#include "partition.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<int ArgUplo, int ArgTrans, int ArgAlgo,
+           int ArgVariant = Variant::One,
+           template<int,int> class ControlType = Control>
+  struct Herk {
+
+    // data-parallel interface
+    // =======================
+    template<typename ScalarType,
+             typename ExecViewTypeA,
+             typename ExecViewTypeC>
+    KOKKOS_INLINE_FUNCTION
+    static int invoke(typename ExecViewTypeA::policy_type &policy,
+                      const typename ExecViewTypeA::policy_type::member_type &member,
+                      const ScalarType alpha,
+                      typename ExecViewTypeA::matrix_type &A,
+                      const ScalarType beta,
+                      typename ExecViewTypeC::matrix_type &C);
+
+    // task-data parallel interface
+    // ============================
+    template<typename ScalarType,
+             typename ExecViewTypeA,
+             typename ExecViewTypeC>
+    class TaskFunctor {
+    public:
+      typedef typename ExecViewTypeA::policy_type policy_type;
+      typedef typename policy_type::member_type member_type;
+      typedef int value_type;
+
+    private:
+      ScalarType _alpha, _beta;
+      typename ExecViewTypeA::matrix_type _A;
+      typename ExecViewTypeC::matrix_type _C;
+
+      policy_type _policy;
+
+    public:
+      KOKKOS_INLINE_FUNCTION
+      TaskFunctor(const policy_type & P,
+                  const ScalarType alpha,
+                  const typename ExecViewTypeA::matrix_type & A,
+                  const ScalarType beta,
+                  const typename ExecViewTypeC::matrix_type & C)
+        : _alpha(alpha),
+          _beta(beta),
+          _A(A),
+          _C(C),
+          _policy(P)
+      { }
+
+      string Label() const { return "Herk"; }
+
+      // task execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(value_type &r_val) {
+        r_val = Herk::invoke<ScalarType,ExecViewTypeA,ExecViewTypeC>(_policy, _policy.member_single(), 
+                             _alpha, _A, _beta, _C);
+      }
+
+      // task-data execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(const member_type &member, value_type &r_val) {
+        r_val = Herk::invoke<ScalarType,ExecViewTypeA,ExecViewTypeC>(_policy, member, 
+                             _alpha, _A, _beta, _C);
+      }
+
+    };
+
+  };
+
+}
+
+#include "herk_u_ct.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/herk_u_ct.hpp b/lib/kokkos/example/ichol/src/herk_u_ct.hpp
new file mode 100644
index 0000000000..6de4a2fa56
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/herk_u_ct.hpp
@@ -0,0 +1,11 @@
+#pragma once
+#ifndef __HERK_U_CT_HPP__
+#define __HERK_U_CT_HPP__
+
+/// \file herk_u_ct.hpp
+/// \brief Sparse hermitian rank one update on given sparse patterns.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "herk_u_ct_for_factor_blocked.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/herk_u_ct_for_factor_blocked.hpp b/lib/kokkos/example/ichol/src/herk_u_ct_for_factor_blocked.hpp
new file mode 100644
index 0000000000..58bba2be3c
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/herk_u_ct_for_factor_blocked.hpp
@@ -0,0 +1,103 @@
+#pragma once
+#ifndef __HERK_U_CT_FOR_FACTOR_BLOCKED_HPP__
+#define __HERK_U_CT_FOR_FACTOR_BLOCKED_HPP__
+
+/// \file herk_u_ct_for_factor_blocked.hpp
+/// \brief Sparse hermitian rank one update on given sparse patterns.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho {
+
+  using namespace std;
+
+
+  // Herk used in the factorization phase
+  // ====================================
+  template<>
+  template<typename ScalarType,
+           typename CrsExecViewTypeA,
+           typename CrsExecViewTypeC>
+  KOKKOS_INLINE_FUNCTION
+  int
+  Herk<Uplo::Upper,Trans::ConjTranspose,
+       AlgoHerk::ForFactorBlocked>
+  ::invoke(typename CrsExecViewTypeA::policy_type &policy,
+           const typename CrsExecViewTypeA::policy_type::member_type &member,
+           const ScalarType alpha,
+           typename CrsExecViewTypeA::matrix_type &A,
+           const ScalarType beta,
+           typename CrsExecViewTypeC::matrix_type &C) {
+    typedef typename CrsExecViewTypeA::ordinal_type      ordinal_type;
+    typedef typename CrsExecViewTypeA::value_type        value_type;
+    typedef typename CrsExecViewTypeA::row_view_type     row_view_type;
+
+
+if ( false && member.team_rank() == 0 ) {
+ printf("Herk [%d +%d)x[%d +%d)\n"
+       , C.OffsetRows()
+       , C.NumRows()
+       , C.OffsetCols()
+       , C.NumCols()
+       );
+}
+
+    // scale the matrix C with beta
+    scaleCrsMatrix<ScalarType,CrsExecViewTypeC>(member, beta, C);
+
+    // C(i,j) += alpha*A'(i,k)*A(k,j)
+    for (ordinal_type k=0;k<A.NumRows();++k) {
+      row_view_type &a = A.RowView(k);
+      const ordinal_type nnz = a.NumNonZeros();
+
+      if (nnz > 0) {
+
+#if 0
+
+        Kokkos::parallel_for(
+          Kokkos::TeamThreadRange(member, 0, nnz),
+            [&](const ordinal_type i) {
+              const ordinal_type row_at_i  = a.Col(i);
+               // const value_type   val_at_ik = conj(a.Value(i));
+               const value_type   val_at_ik = a.Value(i);
+
+               row_view_type &c = C.RowView(row_at_i);
+
+               ordinal_type idx = 0;
+               for (ordinal_type j=i;j<nnz && (idx > -2);++j) {
+                 const ordinal_type col_at_j  = a.Col(j);
+                 const value_type   val_at_kj = a.Value(j);
+
+                 idx = c.Index(col_at_j, idx);
+                 if (idx >= 0)
+                   c.Value(idx) += alpha*val_at_ik*val_at_kj;
+               }
+             });
+#else
+
+        Kokkos::parallel_for(
+          Kokkos::TeamThreadRange(member, 0, nnz*nnz),
+            [&](const ordinal_type ii) {
+               const ordinal_type i = ii / nnz ;
+               const ordinal_type j = ii % nnz ;
+
+               row_view_type &c = C.RowView( a.Col(i) );
+
+               const ordinal_type idx = c.Index( a.Col(j) );
+
+               if (idx >= 0) {
+                 c.Value(idx) += alpha* a.Value(i) * a.Value(j);
+               }
+             });
+
+#endif
+
+        member.team_barrier();
+      }
+    }
+
+    return 0;
+  }
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/norm.hpp b/lib/kokkos/example/ichol/src/norm.hpp
new file mode 100644
index 0000000000..be77ee0dcf
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/norm.hpp
@@ -0,0 +1,82 @@
+#pragma once
+#ifndef __NORM_HPP__
+#define __NORM_HPP__
+
+/// \file norm.hpp
+/// \brief Compute norm of sparse or dense matrices.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<typename DenseExecViewType>
+  KOKKOS_INLINE_FUNCTION
+  auto
+  normOneDenseMatrix(DenseExecViewType &A) -> decltype(real(typename DenseExecViewType::value_type())) {
+    typedef typename DenseExecViewType::ordinal_type  ordinal_type;
+    typedef typename DenseExecViewType::value_type    value_type;
+    typedef decltype(real(value_type())) norm_type;
+
+    const ordinal_type mA = A.NumRows();
+    const ordinal_type nA = A.NumCols();
+
+    norm_type r_val = 0.0;
+
+    for (ordinal_type j=0;j<nA;++j) {
+      norm_type col_sum_at_j = 0.0;
+      for (ordinal_type i=0;i<mA;++i)
+        col_sum_at_j += abs(A.Value(i,j));
+      r_val = max(r_val, col_sum_at_j);
+    }
+    return r_val;
+  }
+
+  template<typename DenseExecViewType>
+  KOKKOS_INLINE_FUNCTION
+  auto
+  normInfDenseMatrix(DenseExecViewType &A) -> decltype(real(typename DenseExecViewType::value_type())) {
+    typedef typename DenseExecViewType::ordinal_type  ordinal_type;
+    typedef typename DenseExecViewType::value_type    value_type;
+    typedef decltype(real(value_type())) norm_type;
+
+    const ordinal_type mA = A.NumRows();
+    const ordinal_type nA = A.NumCols();
+
+    norm_type r_val = 0.0;
+
+    for (ordinal_type i=0;i<mA;++i) {
+      norm_type row_sum_at_i = 0.0;
+      for (ordinal_type j=0;j<nA;++j) 
+        row_sum_at_i += abs(A.Value(i,j));
+      r_val = max(r_val, row_sum_at_i);
+    }
+    return r_val;
+  }
+  
+  template<typename DenseExecViewType>
+  KOKKOS_INLINE_FUNCTION
+  auto
+  normFrobeniusDenseMatrix(DenseExecViewType &A) -> decltype(real(typename DenseExecViewType::value_type())) {
+    typedef typename DenseExecViewType::ordinal_type  ordinal_type;
+    typedef typename DenseExecViewType::value_type    value_type;
+    typedef decltype(real(value_type())) norm_type;
+
+    const ordinal_type mA = A.NumRows();
+    const ordinal_type nA = A.NumCols();
+
+    norm_type r_val = 0.0;
+
+    for (ordinal_type i=0;i<mA;++i) 
+      for (ordinal_type j=0;j<nA;++j) {
+        value_type val = A.Value(i,j);
+        // r_val += conj(val)*val;
+        r_val += val*val;
+      }
+    return sqrt(r_val);
+  }
+
+}
+
+#endif
+
diff --git a/lib/kokkos/example/ichol/src/partition.hpp b/lib/kokkos/example/ichol/src/partition.hpp
new file mode 100644
index 0000000000..a3e9f7095a
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/partition.hpp
@@ -0,0 +1,381 @@
+
+#ifndef __PARTITION_HPP__
+#define __PARTITION_HPP__
+
+/// \file partition.hpp
+/// \brief Matrix partitioning utilities.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho { 
+
+  using namespace std;
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Part_2x2(const MatView A, MatView &ATL, MatView &ATR, 
+           /**************/ MatView &ABL, MatView &ABR,
+           const typename MatView::ordinal_type bm, 
+           const typename MatView::ordinal_type bn,
+           const int quadrant) {
+    typename MatView::ordinal_type bmm, bnn;
+
+    switch (quadrant) {
+    case Partition::TopLeft:
+      bmm = min(bm, A.NumRows());
+      bnn = min(bn, A.NumCols());                
+      
+      ATL.setView(A.BaseObject(),
+                  A.OffsetRows(), bmm,
+                  A.OffsetCols(), bnn);
+      break;
+    case Partition::TopRight:
+    case Partition::BottomLeft:
+      Kokkos::abort("Tacho::Part_2x2 Not yet implemented");
+      break;
+    case Partition::BottomRight:
+      bmm = A.NumRows() - min(bm, A.NumRows());
+      bnn = A.NumCols() - min(bn, A.NumCols());                
+      
+      ATL.setView(A.BaseObject(),
+                  A.OffsetRows(), bmm,
+                  A.OffsetCols(), bnn);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_2x2 Invalid Input");
+      break;
+    }
+    
+    ATR.setView(A.BaseObject(),
+                A.OffsetRows(),                 ATL.NumRows(),
+                A.OffsetCols() + ATL.NumCols(), A.NumCols() - ATL.NumCols());
+    
+    ABL.setView(A.BaseObject(),
+                A.OffsetRows() + ATL.NumRows(), A.NumRows() - ATL.NumRows(),
+                A.OffsetCols(),                 ATL.NumCols());
+    
+    ABR.setView(A.BaseObject(),
+                A.OffsetRows() + ATL.NumRows(), A.NumRows() - ATL.NumRows(),
+                A.OffsetCols() + ATL.NumCols(), A.NumCols() - ATL.NumCols());
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Part_1x2(const MatView A, MatView &AL, MatView &AR, 
+           const typename MatView::ordinal_type bn,
+           const int side) {
+    typename MatView::ordinal_type bmm, bnn;
+
+    switch (side) {
+    case Partition::Left:
+      bmm = A.NumRows();
+      bnn = min(bn, A.NumCols());
+      
+      AL.setView(A.BaseObject(),
+                 A.OffsetRows(), bmm,
+                 A.OffsetCols(), bnn);
+      break;
+    case Partition::Right:
+      bmm = A.NumRows();
+      bnn = A.NumCols() - min(bn, A.NumCols());
+
+      AL.setView(A.BaseObject(),
+                 A.OffsetRows(), bmm,
+                 A.OffsetCols(), bnn);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_1x2 Invalid Input");
+      break;
+    }
+
+    AR.setView(A.BaseObject(),
+               A.OffsetRows(),                A.NumRows(),
+               A.OffsetCols() + AL.NumCols(), A.NumCols() - AL.NumCols());
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Part_2x1(const MatView A, MatView &AT, 
+           /*************/  MatView &AB, 
+           const typename MatView::ordinal_type bm,
+           const int side) {
+    typename MatView::ordinal_type bmm, bnn;
+    
+    switch (side) {
+    case Partition::Top:
+      bmm = min(bm, A.NumRows());
+      bnn = A.NumCols();
+      
+      AT.setView(A.BaseObject(),
+                 A.OffsetRows(), bmm,
+                 A.OffsetCols(), bnn);
+      break;
+    case Partition::Bottom:
+      bmm = A.NumRows() - min(bm, A.NumRows());
+      bnn = A.NumCols();
+
+      AT.setView(A.BaseObject(),
+                 A.OffsetRows(), bmm,
+                 A.OffsetCols(), bnn);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_2x1 Invalid Input");
+      break;
+    }
+    
+    AB.setView(A.BaseObject(),
+               A.OffsetRows() + AT.NumRows(), A.NumRows() - AT.NumRows(),
+               A.OffsetCols(),                A.NumCols());
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Part_2x2_to_3x3(const MatView ATL, const MatView ATR, MatView &A00, MatView &A01, MatView &A02,
+                  /***********************************/ MatView &A10, MatView &A11, MatView &A12,
+                  const MatView ABL, const MatView ABR, MatView &A20, MatView &A21, MatView &A22,
+                  const typename MatView::ordinal_type bm, 
+                  const typename MatView::ordinal_type bn,
+                  const int quadrant) {
+    switch (quadrant) {
+    case Partition::TopLeft:
+      Part_2x2(ATL, A00, A01,
+               /**/ A10, A11, 
+               bm, bn, Partition::BottomRight);
+
+      Part_2x1(ATR, A02, 
+               /**/ A12,
+               bm, Partition::Bottom);
+
+      Part_1x2(ABL, A20, A21,
+               bn, Partition::Right);
+
+      A22.setView(ABR.BaseObject(),
+                  ABR.OffsetRows(), ABR.NumRows(),
+                  ABR.OffsetCols(), ABR.NumCols());
+      break;
+    case Partition::TopRight:
+    case Partition::BottomLeft:
+      Kokkos::abort("Tacho::Part_???");
+      break;
+    case Partition::BottomRight:
+      A00.setView(ATL.BaseObject(),
+                  ATL.OffsetRows(), ATL.NumRows(),
+                  ATL.OffsetCols(), ATL.NumCols());
+
+      Part_1x2(ATR, A01, A02,
+               bn, Partition::Left);
+
+      Part_2x1(ABL, A10, 
+               /**/ A20,
+               bm, Partition::Top);
+
+      Part_2x2(ABR, A11, A12,
+               /**/ A21, A22, 
+               bm, bn, Partition::TopLeft);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_???");
+      break;
+    }
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Part_2x1_to_3x1(const MatView AT, MatView &A0, 
+                  /***************/ MatView &A1, 
+                  const MatView AB, MatView &A2, 
+                  const typename MatView::ordinal_type bm, 
+                  const int side) {
+    switch (side) {
+    case Partition::Top:
+      Part_2x1(AT,  A0, 
+               /**/ A1,
+               bm, Partition::Bottom);
+
+      A2.setView(AB.BaseObject(),
+                 AB.OffsetRows(), AB.NumRows(),
+                 AB.OffsetCols(), AB.NumCols());
+      break;
+    case Partition::Bottom:
+      A0.setView(AT.BaseObject(),
+                 AT.OffsetRows(), AT.NumRows(),
+                 AT.OffsetCols(), AT.NumCols());
+
+      Part_2x1(AB,  A1, 
+               /**/ A2,
+               bm, Partition::Top);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_???");
+      break;
+    }
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Part_1x2_to_1x3(const MatView AL, const MatView AR, 
+                  MatView &A0, MatView &A1, MatView &A2,
+                  const typename MatView::ordinal_type bn, 
+                  const int side) {
+    switch (side) {
+    case Partition::Left:
+      Part_1x2(AL,  A0, A1,
+               bn, Partition::Right);
+
+      A2.setView(AR.BaseObaject(),
+                 AR.OffsetRows(), AR.NumRows(),
+                 AR.OffsetCols(), AR.NumCols());
+      break;
+    case Partition::Right:
+      A0.setView(AL.BaseObject(),
+                 AL.OffsetRows(), AL.NumRows(),
+                 AL.OffsetCols(), AL.NumCols());
+
+      Part_1x2(AR,  A1, A2,
+               bn, Partition::Left);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_???");
+      break;
+    }
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Merge_2x2(const MatView ATL, const MatView ATR, 
+            const MatView ABL, const MatView ABR, MatView &A) {
+    A.setView(ATL.BaseObject(),
+              ATL.OffsetRows(), ATL.NumRows() + ABR.NumRows(), 
+              ATL.OffsetCols(), ATL.NumCols() + ABR.NumCols());
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Merge_1x2(const MatView AL, const MatView AR, MatView &A) {
+    A.setView(AL.BaseObject(),
+              AL.OffsetRows(), AL.NumRows(),
+              AL.OffsetCols(), AL.NumCols() + AR.NumCols());
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Merge_2x1(const MatView AT, 
+            const MatView AB, MatView &A) {
+    A.setView(AT.BaseObject(),
+              AT.OffsetRows(), AT.NumRows() + AB.NumRows(),
+              AT.OffsetCols(), AT.NumCols());
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Merge_3x3_to_2x2(const MatView A00, const MatView A01, const MatView A02, MatView &ATL, MatView &ATR, 
+                   const MatView A10, const MatView A11, const MatView A12,
+                   const MatView A20, const MatView A21, const MatView A22, MatView &ABL, MatView &ABR,
+                   const int quadrant) {
+    switch (quadrant) {
+    case Partition::TopLeft:
+      Merge_2x2(A00, A01, 
+                A10, A11, ATL);
+      
+      Merge_2x1(A02, 
+                A12, ATR);
+
+      Merge_1x2(A20, A21, ABL);
+      
+      ABR.setView(A22.BaseObject(),
+                  A22.OffsetRows(), A22.NumRows(),
+                  A22.OffsetCols(), A22.NumCols());
+      break;
+    case Partition::TopRight:
+    case Partition::BottomLeft:
+      Kokkos::abort("Tacho::Part_???");
+      break;
+    case Partition::BottomRight:
+      ATL.setView(A00.BaseObject(),
+                  A00.OffsetRows(), A00.NumRows(),
+                  A00.OffsetCols(), A00.NumCols());
+
+      Merge_1x2(A01, A02, ATR);
+
+      Merge_2x1(A10, 
+                A20, ABL);
+
+      Merge_2x2(A11, A12, 
+                A21, A22, ABR);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_???");
+      break;
+    }
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Merge_3x1_to_2x1(const MatView A0, MatView &AT, 
+                   const MatView A1, 
+                   const MatView A2, MatView &AB, 
+                   const int side) {
+    switch (side) {
+    case Partition::Top:
+      Merge_2x1(A0, 
+                A1, AT);
+
+      AB.setView(A2.BaseObject(),
+                 A2.OffsetRows(), A2.NumRows(),
+                 A2.OffsetCols(), A2.NumCols());
+      break;
+    case Partition::Bottom:
+      AT.setView(A0.BaseObject(),
+                 A0.OffsetRows(), A0.NumRows(),
+                 A0.OffsetCols(), A0.NumCols());
+
+      Merge_2x1(A1, 
+                A2, AB);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_???");
+      break;
+    }
+  }
+
+  template<typename MatView>
+  KOKKOS_INLINE_FUNCTION 
+  void 
+  Merge_1x3_to_1x2(const MatView A0, const MatView A1, const MatView A2, 
+                   MatView &AL, MatView &AR, 
+                   const int side) {
+    switch (side) {
+    case Partition::Left:
+      Merge_1x2(A0, A1, AL);
+
+      AR.setView(A2.BaseObject(),
+                 A2.OffsetRows(), A2.NumRows(),
+                 A2.OffsetCols(), A2.NumCols());
+      break;
+    case Partition::Right:
+      AL.setView(A0.BaseObject(),
+                 A0.OffsetRows(), A0.NumRows(),
+                 A0.OffsetCols(), A0.NumCols());
+
+      Merge_1x2(A1, A2, AR);
+      break;
+    default:
+      Kokkos::abort("Tacho::Part_???");
+      break;
+    }
+  }
+
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/scale.hpp b/lib/kokkos/example/ichol/src/scale.hpp
new file mode 100644
index 0000000000..3152520966
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/scale.hpp
@@ -0,0 +1,92 @@
+#pragma once
+#ifndef __SCALE_HPP__
+#define __SCALE_HPP__
+
+/// \file scale.hpp
+/// \brief Scaling sparse matrix.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<typename T> struct ScaleTraits {
+    typedef T scale_type;
+    // assume built-in types have appropriate type conversion
+    static constexpr T one = 1 ;
+    static constexpr T zero = 0 ;
+  };
+
+
+  template<typename ScalarType,
+           typename CrsExecViewType>
+  KOKKOS_INLINE_FUNCTION
+  int
+  scaleCrsMatrix(const typename CrsExecViewType::policy_type::member_type &member,
+                 const ScalarType alpha,
+                 typename CrsExecViewType::matrix_type &A) {
+    typedef typename CrsExecViewType::ordinal_type  ordinal_type;
+    typedef typename CrsExecViewType::value_type    value_type;
+    typedef typename CrsExecViewType::row_view_type row_view_type;
+
+    if (alpha == ScaleTraits<value_type>::one) {
+      // do nothing
+    } else {
+      const ordinal_type mA = A.NumRows();
+      if (mA > 0) {
+        Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 0, mA),
+                             [&](const ordinal_type i) {
+                               row_view_type &row = A.RowView(i);
+                               for (ordinal_type j=0;j<row.NumNonZeros();++j)
+                                 row.Value(j) *= alpha;
+                             });
+        member.team_barrier();
+      }
+    }
+
+    return 0;
+  }
+
+  template<typename ScalarType,
+           typename DenseExecViewType>
+  KOKKOS_INLINE_FUNCTION
+  int
+  scaleDenseMatrix(const typename DenseExecViewType::policy_type::member_type &member,
+                   const ScalarType alpha,
+                   DenseExecViewType &A) {
+    typedef typename DenseExecViewType::ordinal_type  ordinal_type;
+    typedef typename DenseExecViewType::value_type    value_type;
+
+    if (alpha == ScaleTraits<value_type>::one) {
+      // do nothing
+    } else {
+      if (A.BaseObject().ColStride() > A.BaseObject().RowStride()) {
+        const ordinal_type nA = A.NumCols();
+        if (nA > 0) {
+          Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 0, nA),
+                               [&](const ordinal_type j) {
+                                 for (ordinal_type i=0;i<A.NumRows();++i)
+                                   A.Value(i, j) *= alpha;
+                               });
+          member.team_barrier();
+        }
+      } else {
+        const ordinal_type mA = A.NumRows();
+        if (mA > 0) {
+          Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 0, mA),
+                               [&](const ordinal_type i) {
+                                 for (ordinal_type j=0;j<A.NumCols();++j)
+                                   A.Value(i, j) *= alpha;
+                               });
+          member.team_barrier();
+        }
+      }
+    }
+
+    return 0;
+  }
+
+}
+
+#endif
+
diff --git a/lib/kokkos/example/ichol/src/symbolic_factor_helper.hpp b/lib/kokkos/example/ichol/src/symbolic_factor_helper.hpp
new file mode 100644
index 0000000000..f6c381a998
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/symbolic_factor_helper.hpp
@@ -0,0 +1,379 @@
+#pragma once
+#ifndef __SYMBOLIC_FACTOR_HELPER_HPP__
+#define __SYMBOLIC_FACTOR_HELPER_HPP__
+
+/// \file symbolic_factor_helper.hpp
+/// \brief The class compute a nonzero pattern with a given level of fills
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<class CrsMatrixType>
+  class SymbolicFactorHelper : public Disp {
+  public:
+    typedef typename CrsMatrixType::ordinal_type ordinal_type;
+    typedef typename CrsMatrixType::size_type    size_type;
+
+    typedef typename Kokkos::HostSpace::execution_space  host_exec_space ;
+
+    typedef typename CrsMatrixType::ordinal_type_array ordinal_type_array;
+    typedef typename CrsMatrixType::size_type_array    size_type_array;
+    typedef typename CrsMatrixType::value_type_array   value_type_array;
+
+  private:
+    string _label;                   // name of this class
+
+    // matrix index base
+    CrsMatrixType _A;                // input matrix
+    ordinal_type _m, _n;             // matrix dimension
+
+    struct crs_graph {
+      size_type_array _ap;           // row ptr array
+      ordinal_type_array _aj;        // col index array
+      size_type _nnz;                // # of nonzeros
+    };
+    typedef struct crs_graph crs_graph_type;
+    crs_graph_type _in, _out;
+
+    typedef Kokkos::View<ordinal_type**, Kokkos::LayoutLeft, host_exec_space> league_specific_ordinal_type_array;
+    typedef typename league_specific_ordinal_type_array::value_type* league_specific_ordinal_type_array_ptr;
+
+    int _lsize;
+    league_specific_ordinal_type_array _queue, _visited, _distance;
+
+    void createInternalWorkSpace() {
+      _queue    = league_specific_ordinal_type_array(_label+"::QueueArray",    _m, _lsize);
+      _visited  = league_specific_ordinal_type_array(_label+"::VisitedArray",  _m, _lsize);
+      _distance = league_specific_ordinal_type_array(_label+"::DistanceArray", _m, _lsize);
+    }
+
+    void freeInternalWorkSpace() {
+      _queue    = league_specific_ordinal_type_array();
+      _visited  = league_specific_ordinal_type_array();
+      _distance = league_specific_ordinal_type_array();
+    }
+
+  public:
+
+    void setLabel(string label) { _label = label; }
+    string Label() const { return _label; }
+
+    SymbolicFactorHelper(const CrsMatrixType &A,
+                         const int lsize = (host_exec_space::thread_pool_size(0)/
+                                            host_exec_space::thread_pool_size(2)))  {
+
+      _label = "SymbolicFactorHelper::" ;
+
+      // matrix index base and the number of rows
+      _A = A;
+
+      _m = _A.NumRows();
+      _n = _A.NumCols();
+
+      // allocate memory for input crs matrix
+      _in._nnz = _A.NumNonZeros();
+      _in._ap  = size_type_array(_label+"::Input::RowPtrArray", _m+1);
+      _in._aj  = ordinal_type_array(_label+"::Input::ColIndexArray", _in._nnz);
+
+      // adjust graph structure; A is assumed to have a graph without its diagonal
+      A.convertGraph(_in._ap, _in._aj);
+      _in._nnz = _in._ap[_m];
+
+      // league size
+      _lsize = lsize;
+
+      // create workspace per league
+      createInternalWorkSpace();
+    }
+    virtual~SymbolicFactorHelper() {
+      freeInternalWorkSpace();
+    }
+
+    class Queue {
+    private:
+      league_specific_ordinal_type_array_ptr _q;
+      ordinal_type _begin, _end;
+
+    public:
+      Queue(league_specific_ordinal_type_array_ptr q)
+        : _q(q),_begin(0),_end(0) { }
+
+      ordinal_type size() const { return _end - _begin; }
+      bool empty() const { return !size(); }
+
+      void push(const ordinal_type val) { _q[_end++] = val; }
+      ordinal_type pop() { return _q[_begin++]; }
+      ordinal_type end() { return _end; }
+      void reset() { _begin = 0; _end = 0; }
+    };
+
+    class FunctorComputeNonZeroPatternInRow {
+    public:
+      typedef Kokkos::TeamPolicy<host_exec_space> policy_type;
+
+    private:
+      ordinal_type _level, _m;
+      crs_graph_type _graph;
+
+      league_specific_ordinal_type_array _queue;
+      league_specific_ordinal_type_array _visited;
+      league_specific_ordinal_type_array _distance;
+
+      size_type_array _ap;
+      ordinal_type_array _aj;
+
+      ordinal_type _phase;
+
+    public:
+      FunctorComputeNonZeroPatternInRow(const ordinal_type level,
+                                        const ordinal_type m,
+                                        const crs_graph_type &graph,
+                                        league_specific_ordinal_type_array &queue,
+                                        league_specific_ordinal_type_array &visited,
+                                        league_specific_ordinal_type_array &distance,
+                                        size_type_array &ap,
+                                        ordinal_type_array &aj)
+        : _level(level), _m(m), _graph(graph),
+          _queue(queue), _visited(visited), _distance(distance),
+          _ap(ap), _aj(aj), _phase(0)
+      { }
+
+      void setPhaseCountNumNonZeros() { _phase = 0; }
+      void setPhaseComputeColIndex()  { _phase = 1; }
+
+      inline
+      void operator()(const typename policy_type::member_type &member) const {
+        const int lrank = member.league_rank();
+        const int lsize = member.league_size();
+
+        league_specific_ordinal_type_array_ptr queue    = &_queue(0, lrank);
+        league_specific_ordinal_type_array_ptr distance = &_distance(0, lrank);
+        league_specific_ordinal_type_array_ptr visited  = &_visited(0, lrank);
+
+        for (ordinal_type i=0;i<_m;++i)
+          visited[i] = 0;
+
+        // shuffle rows to get better load balance;
+        // for instance, if ND is applied, more fills are generated in the last seperator.
+        for (ordinal_type i=lrank;i<_m;i+=lsize) {
+
+          size_type cnt = 0;
+
+          // account for the diagonal
+          switch (_phase) {
+          case 0:
+            cnt = 1;
+            break;
+          case 1:
+            cnt = _ap[i];
+            _aj[cnt++] = i;
+            break;
+          }
+
+          {
+            Queue q(queue); // fixed size queue
+
+            // initialize work space
+            q.push(i);
+            distance[i] = 0;
+
+            const ordinal_type id = (i+1);
+            visited[i] = id;
+
+            // breath first search for i
+            while (!q.empty()) {
+              const ordinal_type h = q.pop();
+              // loop over j adjancy
+              const ordinal_type jbegin = _graph._ap[h], jend = _graph._ap[h+1];
+              for (ordinal_type j=jbegin;j<jend;++j) {
+                const ordinal_type t = _graph._aj[j];
+                if (visited[t] != id) {
+                  visited[t] = id;
+
+                  if (t < i && (_level < 0 || distance[h] < _level)) {
+                    q.push(t);
+                    distance[t] = distance[h] + 1;
+                  }
+                  if (t > i) {
+                    switch (_phase) {
+                    case 0:
+                      ++cnt;
+                      break;
+                    case 1:
+                      _aj[cnt++] = t;
+                      break;
+                    }
+                  }
+                }
+              }
+            }
+
+            // clear work space
+            for (ordinal_type j=0;j<q.end();++j) {
+              const ordinal_type jj = queue[j];
+              distance[jj] = 0;
+            }
+            q.reset();
+          }
+          switch (_phase) {
+          case 0:
+            _ap[i+1] = cnt;
+            break;
+          case 1:
+            sort(_aj.data() + _ap[i] , _aj.data() + _ap[i+1]);
+            break;
+          }
+        }
+      }
+    };
+
+    class FunctorCountOffsetsInRow {
+    public:
+      typedef Kokkos::RangePolicy<host_exec_space> policy_type;
+      typedef size_type value_type;
+
+    private:
+      size_type_array _off_in_rows;
+
+    public:
+      FunctorCountOffsetsInRow(size_type_array &off_in_rows)
+        : _off_in_rows(off_in_rows)
+      { }
+
+      KOKKOS_INLINE_FUNCTION
+      void init(value_type &update) const {
+        update = 0;
+      }
+
+      KOKKOS_INLINE_FUNCTION
+      void operator()(const typename policy_type::member_type &i, value_type &update, const bool final) const {
+        update += _off_in_rows(i);
+        if (final)
+          _off_in_rows(i) = update;
+      }
+
+      KOKKOS_INLINE_FUNCTION
+      void join(volatile value_type &update,
+                volatile const value_type &input) const {
+        update += input;
+      }
+    };
+
+    int createNonZeroPattern(const ordinal_type level,
+                             const int uplo,
+                             CrsMatrixType &F) {
+      // all output array should be local and rcp in Kokkos::View manage memory (de)allocation
+      size_type_array ap = size_type_array(_label+"::Output::RowPtrArray", _m+1);
+
+      // later determined
+      ordinal_type_array aj;
+      value_type_array ax;
+      size_type nnz  = 0;
+
+      {
+        FunctorComputeNonZeroPatternInRow functor(level, _m, _in,
+                                                  _queue,
+                                                  _visited,
+                                                  _distance,
+                                                  ap,
+                                                  aj);
+
+        functor.setPhaseCountNumNonZeros();
+        Kokkos::parallel_for(typename FunctorComputeNonZeroPatternInRow::policy_type(_lsize, 1), functor);
+      }
+      {
+        FunctorCountOffsetsInRow functor(ap);
+        Kokkos::parallel_scan(typename FunctorCountOffsetsInRow::policy_type(0, _m+1), functor);
+      }
+
+      nnz  = ap[_m];
+      aj = ordinal_type_array(_label+"::Output::ColIndexArray", nnz);
+      ax = value_type_array(_label+"::Output::ValueArray", nnz);
+
+      {
+        FunctorComputeNonZeroPatternInRow functor(level, _m, _in,
+                                                  _queue,
+                                                  _visited,
+                                                  _distance,
+                                                  ap,
+                                                  aj);
+
+        functor.setPhaseComputeColIndex();
+        Kokkos::parallel_for(typename FunctorComputeNonZeroPatternInRow::policy_type(_lsize, 1), functor);
+      }
+
+      {
+        F = CrsMatrixType("dummy", _m, _n, nnz, ap, aj, ax);
+        F.add(_A);
+      }
+
+      // record the symbolic factors
+      _out._nnz = nnz;
+      _out._ap = ap;
+      _out._aj = aj;
+
+      return 0;
+    }
+
+    int createNonZeroPattern(const int uplo,
+                             CrsMatrixType &F) {
+      return createNonZeroPattern(-1, uplo, F);
+    }
+
+    ostream& showMe(ostream &os) const {
+      streamsize prec = os.precision();
+      os.precision(15);
+      os << scientific;
+
+      const int w = 6;
+
+      os << " -- Matrix Dimension -- " << endl
+         << "    # of Rows  = " << _m << endl
+         << "    # of Cols  = " << _n << endl;
+
+      os << endl;
+
+      os << " -- Input Graph Without Diagonals -- " << endl
+         << "    # of NonZeros  = " << _in._nnz << endl ;
+
+      os << " -- Input Graph :: RowPtr -- " << endl;
+      {
+        const ordinal_type n0 = _in._ap.dimension_0();
+        for (ordinal_type i=0;i<n0;++i)
+          os << setw(w) << i
+             << setw(w) << _in._ap[i]
+             << endl;
+      }
+
+      os << endl;
+
+      os << " -- Output Graph With Diagonals-- " << endl
+         << "    # of NonZeros  = " << _out._nnz << endl ;
+
+      os << " -- Output Graph :: RowPtr -- " << endl;
+      {
+        const ordinal_type n0 = _out._ap.dimension_0();
+        for (ordinal_type i=0;i<n0;++i)
+          os << setw(w) << i
+             << setw(w) << _out._ap[i]
+             << endl;
+      }
+
+      os.unsetf(ios::scientific);
+      os.precision(prec);
+
+      return os;
+    }
+
+  };
+
+}
+
+#endif
+
+
+
diff --git a/lib/kokkos/example/ichol/src/symbolic_task.hpp b/lib/kokkos/example/ichol/src/symbolic_task.hpp
new file mode 100644
index 0000000000..f6cdc28ab1
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/symbolic_task.hpp
@@ -0,0 +1,118 @@
+#pragma once
+#ifndef __SYMBOLIC_TASK_HPP__
+#define __SYMBOLIC_TASK_HPP__
+
+/// \file symbolic_task.hpp
+/// \brief Provides tasking interface with graphviz output.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho { 
+  
+  using namespace std;
+
+  /// \brief Graphviz color mapping for the generated tasks.
+  static map<string,string> g_graphviz_color = {
+    { "chol/scalar", "indianred2"},
+    { "chol/trsm",   "orange2"   },
+    { "chol/gemm",   "lightblue2"} };
+
+  class SymbolicTaskQueue;
+
+  class SymbolicTask {
+  private:
+    string _name;
+    set<SymbolicTask*> _dep_tasks;
+
+  public:
+    // at this moment, make the queue global
+    // but this should be local and work with 
+    // multiple queues with separate thread teams
+    typedef SymbolicTaskQueue queue;
+
+    SymbolicTask() 
+      : _name("no-name") 
+    { }
+    
+    SymbolicTask(const SymbolicTask &b) 
+      : _name(b._name)
+    { }
+    
+    SymbolicTask(const string name) 
+      : _name(name) 
+    { }
+
+    int addDependence(SymbolicTask *b) {
+      if (b != NULL) 
+        _dep_tasks.insert(b);
+      return 0;
+    }
+
+    int clearDependence() {
+      _dep_tasks.clear();
+      return 0;
+    }
+
+    ostream& showMe(ostream &os) const {
+      os << "    uid = " << this << " , name = " << _name << ", # of deps = " << _dep_tasks.size()  << endl;
+      if (_dep_tasks.size()) {
+        for (auto it=_dep_tasks.begin();it!=_dep_tasks.end();++it) 
+          os << "          " << (*it) << " , name = " << (*it)->_name << endl;
+      }
+      return os;
+    }    
+
+    ostream& graphviz(ostream &os) const {
+      os << (long)(this) 
+         << " [label=\"" << _name ;
+      auto it = g_graphviz_color.find(_name);
+      if (it != g_graphviz_color.end())
+        os << "\" ,style=filled,color=\"" << it->second << "\" "; 
+      os << "];";
+      for (auto it=_dep_tasks.begin();it!=_dep_tasks.end();++it) 
+        os << (long)(*it) << " -> " << (long)this << ";";
+      return (os << endl);
+    }
+
+  };
+
+  static vector<SymbolicTask*> g_queue;
+
+  class SymbolicTaskQueue {
+  public:
+    static SymbolicTask* push(SymbolicTask *task) {
+      g_queue.push_back(task);
+      return g_queue.back();
+    }
+
+    static int clear() {
+      for (auto it=g_queue.begin();it!=g_queue.end();++it)
+        delete (*it);
+      g_queue.clear();
+      return 0;
+    }
+
+    static ostream& showMe(ostream &os) {
+      if (g_queue.size()) {
+        os << " -- Symbolic Task Queue -- " << endl;
+        for (auto it=g_queue.begin();it!=g_queue.end();++it)
+          (*it)->showMe(os);
+      } else {
+        os << " -- Symbolic Task Queue is empty -- " << endl;
+      }
+      return os;
+    }
+
+    static ostream& graphviz(ostream &os, 
+                             const double width = 7.5,
+                             const double length = 10.0) {
+      os << "digraph TaskGraph {" << endl;
+      os << "size=\"" << width << "," << length << "\";" << endl;
+      for (auto it=g_queue.begin();it!=g_queue.end();++it) 
+        (*it)->graphviz(os);
+      os << "}" << endl;
+      return (os << endl);
+    }
+  };
+  
+}
+#endif
diff --git a/lib/kokkos/example/ichol/src/task_factory.hpp b/lib/kokkos/example/ichol/src/task_factory.hpp
new file mode 100644
index 0000000000..b829da6737
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/task_factory.hpp
@@ -0,0 +1,77 @@
+#pragma once
+#ifndef __TASK_FACTORY_HPP__
+#define __TASK_FACTORY_HPP__
+
+/// \file task_factory.hpp
+/// \brief A wrapper for task policy and future with a provided space type.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho { 
+
+  using namespace std;
+
+  /// \class TaskFactory
+  /// \brief Minimal interface to Kokkos tasking.
+  ///
+  /// TaskFactory is attached to blocks as a template argument in order to 
+  /// create and manage tasking future objects. Note that policy (shared 
+  /// pointer to the task generator) is not a member object in this class.
+  /// This class includes minimum interface for tasking with type decralation 
+  /// of the task policy and template alias of future so that future objects 
+  /// generated in this class will match to their policy and its execution space. 
+  ///
+  template<typename PolicyType,        
+           typename FutureType>
+  class TaskFactory {
+  private:
+    static constexpr int _max_task_dependence = 10 ;
+
+  public:
+    typedef PolicyType policy_type;
+    typedef FutureType future_type;
+    
+    template<typename TaskFunctorType>
+    static KOKKOS_INLINE_FUNCTION
+    future_type create(policy_type &policy, const TaskFunctorType &func) {
+
+      future_type f ;
+      // while ( f.is_null() ) {
+        f = policy.task_create_team(func, _max_task_dependence);
+      // }
+      if ( f.is_null() ) Kokkos::abort("task_create_team FAILED, out of memory");
+      return f ;
+    }
+    
+    static KOKKOS_INLINE_FUNCTION
+    void spawn(policy_type &policy, const future_type &obj, bool priority = false ) {
+      policy.spawn(obj,priority);
+    }
+    
+    static KOKKOS_INLINE_FUNCTION
+    void addDependence(policy_type &policy, 
+                       const future_type &after, const future_type &before) {
+      policy.add_dependence(after, before);
+    }
+
+    template<typename TaskFunctorType>
+    static  KOKKOS_INLINE_FUNCTION
+    void addDependence(policy_type &policy, 
+                       TaskFunctorType *after, const future_type &before) {
+      policy.add_dependence(after, before);
+    }
+
+    template<typename TaskFunctorType>
+    static  KOKKOS_INLINE_FUNCTION
+    void clearDependence(policy_type &policy, TaskFunctorType *func) {
+      policy.clear_dependence(func);
+    }
+
+    template<typename TaskFunctorType>
+    static KOKKOS_INLINE_FUNCTION
+    void respawn(policy_type &policy, TaskFunctorType *func) {
+      policy.respawn(func);
+    }
+  };
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/task_view.hpp b/lib/kokkos/example/ichol/src/task_view.hpp
new file mode 100644
index 0000000000..ce280a325f
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/task_view.hpp
@@ -0,0 +1,104 @@
+#pragma once
+#ifndef __TASK_VIEW_HPP__
+#define __TASK_VIEW_HPP__
+
+/// \file task_view.hpp
+/// \brief Task view is inherited from matrix view and have a member for the task handler.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+namespace Tacho { 
+
+  using namespace std;
+
+  template<typename MatrixViewType,
+           typename TaskFactoryType>
+  class TaskView : public MatrixViewType {
+  public:
+    typedef          MatrixViewType                matrix_type ;
+    typedef typename MatrixViewType::value_type    value_type;
+    typedef typename MatrixViewType::ordinal_type  ordinal_type;
+
+    typedef TaskFactoryType task_factory_type;
+    typedef typename task_factory_type::policy_type policy_type;
+    typedef typename task_factory_type::future_type future_type;
+
+  private:
+    future_type _f;
+
+  public:
+    KOKKOS_INLINE_FUNCTION
+    void setFuture(const future_type &f)
+      { _f = f; }
+
+    KOKKOS_INLINE_FUNCTION
+    future_type Future() const { return _f; }
+
+    KOKKOS_INLINE_FUNCTION
+    ~TaskView() = default ;
+
+    KOKKOS_INLINE_FUNCTION
+    TaskView() 
+      : MatrixViewType(), _f()
+    { } 
+
+    TaskView(const TaskView &b) = delete ;
+
+    KOKKOS_INLINE_FUNCTION
+    TaskView(typename MatrixViewType::mat_base_type const & b) 
+      : MatrixViewType(b), _f() 
+    { }
+
+    KOKKOS_INLINE_FUNCTION
+    TaskView(typename MatrixViewType::mat_base_type const & b,
+             const ordinal_type offm, const ordinal_type m,
+             const ordinal_type offn, const ordinal_type n) 
+      : MatrixViewType(b, offm, m, offn, n), _f() 
+    { }
+
+  };
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if ! KOKKOS_USING_EXP_VIEW
+
+namespace Kokkos {
+  namespace Impl {
+
+    //  The Kokkos::View allocation will by default assign each allocated datum to zero.
+    //  This is not the required initialization behavior when
+    //  non-trivial objects are used within a Kokkos::View.
+    //  Create a partial specialization of the Kokkos::Impl::AViewDefaultConstruct
+    //  to replace the assignment initialization with placement new initialization.
+    //
+    //  This work-around is necessary until a TBD design refactorization of Kokkos::View.
+
+    template< class ExecSpace , typename T1, typename T2 >
+    struct ViewDefaultConstruct< ExecSpace , Tacho::TaskView<T1,T2> , true >
+    {
+      typedef Tacho::TaskView<T1,T2> type ;
+      type * const m_ptr ;
+
+      KOKKOS_FORCEINLINE_FUNCTION
+      void operator()( const typename ExecSpace::size_type& i ) const
+      { new(m_ptr+i) type(); }
+
+      ViewDefaultConstruct( type * pointer , size_t capacity )
+        : m_ptr( pointer )
+      {
+        Kokkos::RangePolicy< ExecSpace > range( 0 , capacity );
+        parallel_for( range , *this );
+        ExecSpace::fence();
+      }
+    };
+
+  } // namespace Impl
+} // namespace Kokkos
+
+#endif /* #if ! KOKKOS_USING_EXP_VIEW */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/trsm.hpp b/lib/kokkos/example/ichol/src/trsm.hpp
new file mode 100644
index 0000000000..b4a6a7df48
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/trsm.hpp
@@ -0,0 +1,92 @@
+#pragma once
+#ifndef __TRSM_HPP__
+#define __TRSM_HPP__
+
+/// \file trsm.hpp
+/// \brief Sparse triangular solve on given sparse patterns and multiple rhs.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+
+#include "util.hpp"
+#include "control.hpp"
+#include "partition.hpp"
+
+namespace Tacho {
+
+  using namespace std;
+
+  template<int ArgSide,int ArgUplo, int ArgTrans, int ArgAlgo,
+           int ArgVariant = Variant::One,
+           template<int,int> class ControlType = Control>
+  struct Trsm {
+
+    // data-parallel interface
+    // =======================
+    template<typename ScalarType,
+             typename ExecViewTypeA,
+             typename ExecViewTypeB>
+    KOKKOS_INLINE_FUNCTION
+    static int invoke(typename ExecViewTypeA::policy_type &policy,
+                      const typename ExecViewTypeA::policy_type::member_type &member,
+                      const int diagA,
+                      const ScalarType alpha,
+                      typename ExecViewTypeA::matrix_type &A,
+                      typename ExecViewTypeB::matrix_type &B);
+
+    // task-data parallel interface
+    // ============================
+    template<typename ScalarType,
+             typename ExecViewTypeA,
+             typename ExecViewTypeB>
+    class TaskFunctor {
+    public:
+      typedef typename ExecViewTypeA::policy_type policy_type;
+      typedef typename policy_type::member_type member_type;
+      typedef int value_type;
+
+    private:
+      int _diagA;
+      ScalarType _alpha;
+      typename ExecViewTypeA::matrix_type _A;
+      typename ExecViewTypeB::matrix_type _B;
+
+      policy_type _policy;
+
+    public:
+      KOKKOS_INLINE_FUNCTION
+      TaskFunctor(const policy_type & P,
+                  const int diagA,
+                  const ScalarType alpha,
+                  const ExecViewTypeA & A,
+                  const ExecViewTypeB & B)
+        : _diagA(diagA),
+          _alpha(alpha),
+          _A(A),
+          _B(B),
+          _policy(P)
+      { }
+
+      string Label() const { return "Trsm"; }
+
+      // task execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(value_type &r_val) {
+        r_val = Trsm::invoke<ScalarType,ExecViewTypeA,ExecViewTypeB>(_policy, _policy.member_single(),
+                             _diagA, _alpha, _A, _B);
+      }
+
+      // task-data execution
+      KOKKOS_INLINE_FUNCTION
+      void apply(const member_type &member, value_type &r_val) {
+        r_val = Trsm::invoke<ScalarType,ExecViewTypeA,ExecViewTypeB>(_policy, member, 
+                             _diagA, _alpha, _A, _B);
+      }
+
+    };
+  };
+
+}
+
+// #include "trsm_l_u_nt.hpp"
+#include "trsm_l_u_ct.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/trsm_l_u_ct.hpp b/lib/kokkos/example/ichol/src/trsm_l_u_ct.hpp
new file mode 100644
index 0000000000..b6f3289474
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/trsm_l_u_ct.hpp
@@ -0,0 +1,14 @@
+#pragma once
+#ifndef __TRSM_L_U_CT_HPP__
+#define __TRSM_L_U_CT_HPP__
+
+/// \file trsm_l_u_ct.hpp
+/// \brief Sparse triangular solve on given sparse patterns and multiple rhs.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+///
+#include "gemm.hpp"
+
+#include "trsm_l_u_ct_for_factor_blocked.hpp"
+// #include "trsm_l_u_ct_for_tri_solve_blocked.hpp"
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/trsm_l_u_ct_for_factor_blocked.hpp b/lib/kokkos/example/ichol/src/trsm_l_u_ct_for_factor_blocked.hpp
new file mode 100644
index 0000000000..7414e5d80f
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/trsm_l_u_ct_for_factor_blocked.hpp
@@ -0,0 +1,185 @@
+#pragma once
+#ifndef __TRSM_L_U_CT_FOR_FACTOR_BLOCKED_HPP__
+#define __TRSM_L_U_CT_FOR_FACTOR_BLOCKED_HPP__
+
+/// \file trsm_l_u_ct_for_factor_blocked.hpp
+/// \brief Sparse triangular solve on given sparse patterns and multiple rhs.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+///
+
+namespace Tacho {
+
+  using namespace std;
+
+  // Trsm used in the factorization phase: data parallel on b1t
+  // ==========================================================
+  template<>
+  template<typename ScalarType,
+           typename CrsExecViewTypeA,
+           typename CrsExecViewTypeB>
+  KOKKOS_INLINE_FUNCTION
+  int
+  Trsm<Side::Left,Uplo::Upper,Trans::ConjTranspose,
+       AlgoTrsm::ForFactorBlocked,Variant::One>
+  ::invoke(typename CrsExecViewTypeA::policy_type &policy,
+           const typename CrsExecViewTypeA::policy_type::member_type &member,
+           const int diagA,
+           const ScalarType alpha,
+           typename CrsExecViewTypeA::matrix_type &A,
+           typename CrsExecViewTypeB::matrix_type &B) {
+    typedef typename CrsExecViewTypeA::ordinal_type      ordinal_type;
+    typedef typename CrsExecViewTypeA::value_type        value_type;
+    typedef typename CrsExecViewTypeA::row_view_type     row_view_type;
+
+
+if ( false && member.team_rank() == 0 ) {
+ printf("Trsm [%d +%d)x[%d +%d)\n"
+       , B.OffsetRows()
+       , B.NumRows()
+       , B.OffsetCols()
+       , B.NumCols()
+       );
+}
+
+    // scale the matrix B with alpha
+    scaleCrsMatrix<ScalarType,CrsExecViewTypeB>(member, alpha, B);
+
+    // Solve a system: AX = B -> B := inv(A) B
+    const ordinal_type mA = A.NumRows();
+    const ordinal_type nB = B.NumCols();
+
+    if (nB > 0) {
+      for (ordinal_type k=0;k<mA;++k) {
+        row_view_type &a = A.RowView(k);
+        // const value_type cdiag = std::conj(a.Value(0)); // for complex<T>
+        const value_type cdiag = a.Value(0);
+
+        // invert
+        row_view_type &b1 = B.RowView(k);
+        const ordinal_type nnz_b1 = b1.NumNonZeros();
+
+        if (diagA != Diag::Unit && nnz_b1 > 0) {
+          // b1t = b1t / conj(diag)
+          Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 0, nnz_b1),
+                               [&](const ordinal_type j) {
+                                 b1.Value(j) /= cdiag;
+                               });
+        }
+
+        // update
+        const ordinal_type nnz_a = a.NumNonZeros();
+        if (nnz_a > 0) {
+          // B2 = B2 - trans(conj(a12t)) b1t
+          Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 0, nnz_b1),
+                               [&](const ordinal_type j) {
+                                 // grab b1
+                                 const ordinal_type col_at_j = b1.Col(j);
+                                 const value_type   val_at_j = b1.Value(j);
+
+                                 for (ordinal_type i=1;i<nnz_a;++i) {
+                                   // grab a12t
+                                   const ordinal_type row_at_i = a.Col(i);
+                                   // const value_type   val_at_i = conj(a.Value(i));
+                                   const value_type   val_at_i = a.Value(i);
+
+                                   // grab b2
+                                   row_view_type &b2 = B.RowView(row_at_i);
+
+                                   // check and update
+                                   ordinal_type idx = 0;
+                                   idx = b2.Index(col_at_j, idx);
+                                   if (idx >= 0)
+                                     b2.Value(idx) -= val_at_i*val_at_j;
+                                 }
+                               });
+        }
+        member.team_barrier();
+      }
+    }
+
+    return 0;
+  }
+
+  // Trsm used in the factorization phase: data parallel on a1t
+  // ==========================================================
+  template<>
+  template<typename ScalarType,
+           typename CrsExecViewTypeA,
+           typename CrsExecViewTypeB>
+  KOKKOS_INLINE_FUNCTION
+  int
+  Trsm<Side::Left,Uplo::Upper,Trans::ConjTranspose,
+       AlgoTrsm::ForFactorBlocked,Variant::Two>
+  ::invoke(typename CrsExecViewTypeA::policy_type &policy,
+           const typename CrsExecViewTypeA::policy_type::member_type &member,
+           const int diagA,
+           const ScalarType alpha,
+           typename CrsExecViewTypeA::matrix_type &A,
+           typename CrsExecViewTypeB::matrix_type &B) {
+    typedef typename CrsExecViewTypeA::ordinal_type      ordinal_type;
+    typedef typename CrsExecViewTypeA::value_type        value_type;
+    typedef typename CrsExecViewTypeA::row_view_type     row_view_type;
+
+    // scale the matrix B with alpha
+    scaleCrsMatrix<ScalarType,CrsExecViewTypeB>(member, alpha, B);
+
+    // Solve a system: AX = B -> B := inv(A) B
+    const ordinal_type mA = A.NumRows();
+    const ordinal_type nB = B.NumCols();
+
+    if (nB > 0) {
+      for (ordinal_type k=0;k<mA;++k) {
+        row_view_type &a = A.RowView(k);
+        // const value_type cdiag = conj(a.Value(0));
+        const value_type cdiag = a.Value(0);
+
+        // invert
+        row_view_type &b1 = B.RowView(k);
+        const ordinal_type nnz_b1 = b1.NumNonZeros();
+
+        if (diagA != Diag::Unit && nnz_b1 > 0) {
+          // b1t = b1t / conj(diag)
+          Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 0, nnz_b1),
+                               [&](const ordinal_type j) {
+                                 b1.Value(j) /= cdiag;
+                               });
+          member.team_barrier();
+        }
+
+        // update
+        const ordinal_type nnz_a = a.NumNonZeros();
+        if (nnz_a > 0) {
+          // B2 = B2 - trans(conj(a12t)) b1t
+          Kokkos::parallel_for(Kokkos::TeamThreadRange(member, 1, nnz_a),
+                               [&](const ordinal_type i) {
+                                 // grab a12t
+                                 const ordinal_type row_at_i = a.Col(i);
+                                 // const value_type   val_at_i = conj(a.Value(i));
+                                 const value_type   val_at_i = a.Value(i);
+
+                                 // grab b2
+                                 row_view_type &b2 = B.RowView(row_at_i);
+
+                                 ordinal_type idx = 0;
+                                 for (ordinal_type j=0;j<nnz_b1 && (idx > -2);++j) {
+                                   // grab b1
+                                   const ordinal_type col_at_j = b1.Col(j);
+                                   const value_type   val_at_j = b1.Value(j);
+
+                                   // check and update
+                                   idx = b2.Index(col_at_j, idx);
+                                   if (idx >= 0)
+                                     b2.Value(idx) -= val_at_i*val_at_j;
+                                 }
+                               });
+          member.team_barrier();
+        }
+      }
+    }
+
+    return 0;
+  }
+
+}
+
+#endif
diff --git a/lib/kokkos/example/ichol/src/util.cpp b/lib/kokkos/example/ichol/src/util.cpp
new file mode 100644
index 0000000000..ef220c48c1
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/util.cpp
@@ -0,0 +1,4 @@
+
+
+static int dummy = 1;
+
diff --git a/lib/kokkos/example/ichol/src/util.hpp b/lib/kokkos/example/ichol/src/util.hpp
new file mode 100644
index 0000000000..020475bc52
--- /dev/null
+++ b/lib/kokkos/example/ichol/src/util.hpp
@@ -0,0 +1,237 @@
+#pragma once
+#ifndef __UTIL_HPP__
+#define __UTIL_HPP__
+
+#include <stdio.h>
+#include <string.h>
+
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <fstream>
+#include <vector>
+#include <set>
+#include <map>
+#include <algorithm>
+#include <memory>
+
+#include <cmath>
+#include <complex>
+
+#include <limits>
+
+/// \file util.hpp
+/// \brief Utility functions and constant integer class like an enum class.
+/// \author Kyungjoo Kim (kyukim@sandia.gov)
+///
+/// This provides utility functions for implementing mini-app for incomplete
+/// sparse matrix factorization with task-data parallelism e.g., parameter
+/// classes, error handling, ostream << overloading.
+///
+/// Note: The reference of the "static const int" members in the enum-like
+/// classes should not be used as function arguments but their values only.
+
+
+using namespace std;
+
+namespace Tacho {
+
+#undef CHKERR
+#define CHKERR(ierr)                                                    \
+  if (ierr != 0) { cout << endl << ">> Error in " << __FILE__ << ", " << __LINE__ << " : " << ierr << endl; }
+
+#define MSG_NOT_YET_IMPLEMENTED ">> Not yet implemented"
+#define MSG_INVALID_INPUT(what) ">> Invaid input argument: " #what
+#define MSG_INVALID_TEMPLATE_ARGS ">> Invaid template arguments"
+#define ERROR(msg)                                                      \
+  { cout << endl << ">> Error in " << __FILE__ << ", " << __LINE__ << endl << msg << endl; }
+
+  // control id
+#undef  Ctrl
+#define Ctrl(name,algo,variant) name<algo,variant>
+
+  // control leaf
+#undef CtrlComponent
+#define CtrlComponent(name,algo,variant,component,id)                  \
+  Ctrl(name,algo,variant)::component[id]
+
+  // control recursion
+#undef CtrlDetail
+#define CtrlDetail(name,algo,variant,component) \
+  CtrlComponent(name,algo,variant,component,0),CtrlComponent(name,algo,variant,component,1),name
+
+  /// \class GraphHelper
+  class GraphHelper {
+  public:
+    static const int DefaultRandomSeed = -1;
+  };
+
+
+  /// \class Partition
+  /// \brief Matrix partition parameters.
+  class Partition {
+  public:
+    static const int Top         = 101;
+    static const int Bottom      = 102;
+
+    static const int Left        = 201;
+    static const int Right       = 202;
+
+    static const int TopLeft     = 401;
+    static const int TopRight    = 402;
+    static const int BottomLeft  = 403;
+    static const int BottomRight = 404;
+  };
+
+  /// \class Uplo
+  /// \brief Matrix upper/lower parameters.
+  class Uplo {
+  public:
+    static const int Upper = 501;
+    static const int Lower = 502;
+  };
+
+  /// \class Side
+  /// \brief Matrix left/right parameters.
+  class Side {
+  public:
+    static const int Left  = 601;
+    static const int Right = 602;
+  };
+
+  /// \class Diag
+  /// \brief Matrix unit/non-unit diag parameters.
+  class Diag {
+  public:
+    static const int Unit    = 701;
+    static const int NonUnit = 702;
+  };
+
+  /// \class Trans
+  /// \brief Matrix upper/lower parameters.
+  class Trans {
+  public:
+    static const int Transpose     = 801;
+    static const int ConjTranspose = 802;
+    static const int NoTranspose   = 803;
+  };
+
+  /// \class Loop
+  /// \brief outer/innner parameters
+  class Loop {
+  public:
+    static const int Outer = 901;
+    static const int Inner = 902;
+    static const int Fused = 903;
+  };
+
+  class Variant {
+  public:
+    static const int One   = 1;
+    static const int Two   = 2;
+    static const int Three = 3;
+    static const int Four  = 4;
+  };
+
+  /// \class AlgoChol
+  /// \brief Algorithmic variants in sparse factorization and sparse BLAS operations.
+  class AlgoChol {
+  public:
+    // One side factorization on flat matrices
+    static const int Dummy                  = 1000;
+    static const int Unblocked              = 1001;
+    static const int UnblockedOpt           = 1002;
+    static const int Blocked                = 1101; // testing only
+
+    static const int RightLookByBlocks      = 1201; // backbone structure is right looking
+    static const int ByBlocks               = RightLookByBlocks;
+
+    static const int NestedDenseBlock       = 1211;
+    static const int NestedDenseByBlocks    = 1212;
+
+    static const int RightLookDenseByBlocks = 1221;
+    static const int DenseByBlocks          = RightLookDenseByBlocks;
+
+    static const int ExternalLapack         = 1231;
+    static const int ExternalPardiso        = 1232;
+  };
+
+  // aliasing name space
+  typedef AlgoChol AlgoTriSolve;
+
+  class AlgoBlasLeaf {
+  public:
+    // One side factorization on flat matrices
+    static const int ForFactorBlocked = 2001;
+
+    // B and C are dense matrices and used for solve phase
+    static const int ForTriSolveBlocked = 2011;
+
+    static const int ExternalBlas = 2021;
+  };
+
+  class AlgoGemm : public AlgoBlasLeaf {
+  public:
+    static const int DenseByBlocks = 2101;
+  };
+
+  class AlgoTrsm : public AlgoBlasLeaf {
+  public:
+    static const int DenseByBlocks = 2201;
+  };
+
+  class AlgoHerk : public AlgoBlasLeaf {
+  public:
+    static const int DenseByBlocks = 2301;
+  };
+
+  /// \brief Interface for overloaded stream operators.
+  template<typename T>
+  inline
+  ostream& operator<<(ostream &os, const unique_ptr<T> &p) {
+    return p->showMe(os);
+  }
+
+  /// \class Disp
+  /// \brief Interface for the stream operator.
+  class Disp {
+    friend ostream& operator<<(ostream &os, const Disp &disp);
+  public:
+    Disp() { }
+    virtual ostream& showMe(ostream &os) const {
+      return os;
+    }
+  };
+
+  /// \brief Implementation of the overloaded stream operator.
+  inline
+  ostream& operator<<(ostream &os, const Disp &disp) {
+    return disp.showMe(os);
+  }
+
+  template<typename T> struct NumericTraits {};
+
+  template<>
+  struct NumericTraits<float> {
+    typedef float real_type;
+    static real_type epsilon() { return numeric_limits<float>::epsilon(); }
+  };
+  template<>
+  struct NumericTraits<double> {
+    typedef double real_type;
+    static real_type epsilon() { return numeric_limits<double>::epsilon(); }
+  };
+  template<>
+  struct NumericTraits<complex<float> > {
+    typedef float real_type;
+    static real_type epsilon() { return numeric_limits<float>::epsilon(); }
+  };
+  template<>
+  struct NumericTraits<complex<double> > {
+    typedef double real_type;
+    static real_type epsilon() { return numeric_limits<double>::epsilon(); }
+  };
+
+}
+
+#endif
diff --git a/lib/kokkos/example/md_skeleton/CMakeLists.txt b/lib/kokkos/example/md_skeleton/CMakeLists.txt
new file mode 100644
index 0000000000..28412c3784
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/CMakeLists.txt
@@ -0,0 +1,16 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(SOURCES "")
+SET(LIBRARIES "")
+
+FILE(GLOB SOURCES *.cpp )
+
+TRIBITS_ADD_EXECUTABLE(
+  md_skeleton 
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  DEPLIBS ${LIBRARIES}
+  )
+
diff --git a/lib/kokkos/example/md_skeleton/Makefile b/lib/kokkos/example/md_skeleton/Makefile
new file mode 100644
index 0000000000..bf8fbea3e0
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/Makefile
@@ -0,0 +1,53 @@
+KOKKOS_PATH ?= ../..
+
+MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
+SRC_DIR := $(dir $(MAKEFILE_PATH))
+
+SRC = $(wildcard $(SRC_DIR)/*.cpp)
+OBJ = $(SRC:$(SRC_DIR)/%.cpp=%.o)
+
+#SRC = $(wildcard *.cpp)
+#OBJ = $(SRC:%.cpp=%.o)
+
+default: build
+	echo "Start Build"
+
+# use installed Makefile.kokkos
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = $(NVCC_WRAPPER)
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS = 
+EXE = $(addsuffix .cuda, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "Cuda,OpenMP"
+#KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS =  
+EXE = $(addsuffix .host, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "OpenMP"
+#KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+LIB =
+
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: 
+	rm -f *.a *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:$(SRC_DIR)/%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
diff --git a/lib/kokkos/example/md_skeleton/README b/lib/kokkos/example/md_skeleton/README
new file mode 100644
index 0000000000..1ce682b0a6
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/README
@@ -0,0 +1,3 @@
+To build this example on a 2012-model Macbook Pro with NVIDIA Kepler GPU:
+
+./build.cuda_std g++_osx cuda_osx 30 opt
diff --git a/lib/kokkos/example/md_skeleton/force.cpp b/lib/kokkos/example/md_skeleton/force.cpp
new file mode 100644
index 0000000000..a31944f859
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/force.cpp
@@ -0,0 +1,192 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+/* Define values which set the max number of registers used for the Force Kernel
+ * Its 32 * 2048 / (KOKKOS_CUDA_MAX_THREADS * KOKKOS_CUDA_MIN_BLOCKS)
+ * Have to be set before including Kokkos header files.
+ */
+
+#define KOKKOS_CUDA_MAX_THREADS 512
+#define KOKKOS_CUDA_MIN_BLOCKS 3
+
+#include <system.h>
+#include <cstdio>
+
+
+/* Simple Lennard Jones Force Kernel using neighborlists
+ * Calculates for every pair of atoms (i,j) with distance smaller r_cut
+ * f_ij = 4*epsilon * ( (sigma/r_ij)^12 - (sigma/r_ij)^6 )
+ * where r_ij is the distance of atoms (i,j).
+ * The force on atom i is the sum over f_ij:
+ * f_i = sum_j (f_ij)
+ * Neighborlists are used in order to pre calculate which atoms j are
+ * close enough to i to be able to contribute. By choosing a larger neighbor
+ * cutoff then the force cutoff, the neighbor list can be reused several times
+ * (typically 10 - 100).
+ */
+
+struct ForceFunctor {
+
+  typedef t_x_array::execution_space execution_space; //Device Type for running the kernel
+  typedef double2 value_type; // When energy calculation is requested return energy, and virial
+
+  t_x_array_randomread x;       //atom positions
+  t_f_array f;                  //atom forces
+  t_int_1d_const numneigh;      //number of neighbors per atom
+  t_neighbors_const neighbors;  //neighborlist
+  double cutforcesq;            //force cutoff
+  double epsilon;               //Potential parameter
+  double sigma6;                //Potential parameter
+
+
+  ForceFunctor(System s) {
+    x = s.d_x;
+    f = s.f;
+    numneigh = s.numneigh;
+    neighbors = s.neighbors;
+    cutforcesq = s.force_cutsq;
+    epsilon = 1.0;
+    sigma6 = 1.0;
+  }
+
+  /* Operator for not calculating energy and virial */
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int &i) const {
+    force<0>(i);
+  }
+
+  /* Operator for calculating energy and virial */
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int &i, double2 &energy_virial) const {
+    double2 ev = force<1>(i);
+    energy_virial.x += ev.x;
+    energy_virial.y += ev.y;
+  }
+
+  template<int EVFLAG>
+  KOKKOS_INLINE_FUNCTION
+  double2 force(const int &i) const
+  {
+    const int numneighs = numneigh[i];
+    const double xtmp = x(i, 0);
+    const double ytmp = x(i, 1);
+    const double ztmp = x(i, 2);
+    double fix = 0;
+    double fiy = 0;
+    double fiz = 0;
+    double energy = 0;
+    double virial = 0;
+
+    //pragma simd forces vectorization (ignoring the performance objections of the compiler)
+    //give hint to compiler that fix, fiy and fiz are used for reduction only
+
+  #ifdef USE_SIMD
+    #pragma simd reduction (+: fix,fiy,fiz,energy,virial)
+  #endif
+    for(int k = 0; k < numneighs; k++) {
+      const int j = neighbors(i, k);
+      const double delx = xtmp - x(j, 0);
+      const double dely = ytmp - x(j, 1);
+      const double delz = ztmp - x(j, 2);
+      const double rsq = delx * delx + dely * dely + delz * delz;
+
+      //if(i==0) printf("%i %i %lf %lf\n",i,j,rsq,cutforcesq);
+      if(rsq < cutforcesq) {
+        const double sr2 = 1.0 / rsq;
+        const double sr6 = sr2 * sr2 * sr2  * sigma6;
+        const double force = 48.0 * sr6 * (sr6 - 0.5) * sr2 * epsilon;
+        fix += delx * force;
+        fiy += dely * force;
+        fiz += delz * force;
+
+        if(EVFLAG) {
+          energy += sr6 * (sr6 - 1.0) * epsilon;
+          virial += delx * delx * force + dely * dely * force + delz * delz * force;
+        }
+      }
+    }
+
+    f(i, 0) += fix;
+    f(i, 1) += fiy;
+    f(i, 2) += fiz;
+
+    double2 energy_virial ;
+    energy_virial.x = 4.0 * energy ;
+    energy_virial.y = 0.5 * virial ;
+    return energy_virial;
+  }
+
+  /* init and join functions when doing the reduction to obtain energy and virial */
+
+  KOKKOS_FUNCTION
+  static void init(volatile value_type &update) {
+    update.x = update.y = 0;
+  }
+  KOKKOS_FUNCTION
+  static void join(volatile value_type &update ,
+                   const volatile value_type &source) {
+    update.x += source.x ;
+    update.y += source.y ;
+  }
+
+};
+
+
+/* Calling function */
+
+double2 force(System &s,int evflag) {
+
+  ForceFunctor f(s);
+
+  double2 ev ; ev.x = 0 ; ev.y = 0 ;
+  if(!evflag)
+    Kokkos::parallel_for(s.nlocal,f);
+  else
+    Kokkos::parallel_reduce(s.nlocal,f,ev);
+
+  execution_space::fence();
+  return ev;
+}
+
diff --git a/lib/kokkos/example/md_skeleton/main.cpp b/lib/kokkos/example/md_skeleton/main.cpp
new file mode 100644
index 0000000000..58cf76cab0
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/main.cpp
@@ -0,0 +1,205 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <cstdio>
+#include <cstring>
+#include <cstdlib>
+#include "system.h"
+
+int create_system(System &system, int nx, int ny, int nz, double rho);
+int neigh_setup(System &system);
+int neigh_build(System &system);
+double2 force(System &system,int evflag);
+
+/* simple MD Skeleton which
+ *   - constructs a simple FCC lattice,
+ *   - computes a neighborlist
+ *   - compute LJ-Force kernel a number of times
+ */
+
+int main(int argc, char** argv) {
+
+  printf("Running MD Skeleton\n");
+  /* Thread numbers for Host */
+
+  int num_threads = 1;
+  int teams = 1;
+  int device = 0; // Default device for GPU runs
+
+  /* avoid unused variable warnings */
+  (void)num_threads;
+  (void)teams;
+  (void)device;
+
+  /* Default value for number of force calculations */
+
+  int iter = 100;
+
+  /* Default value for system size (4*nx*ny*nz atoms)
+   * nx, ny and nz are set to system_size if not specified on commandline */
+
+  int system_size = 20;
+  int nx = -1;
+  int ny = -1;
+  int nz = -1;
+
+  int neighbor_size = 1; // Default bin size for neighbor list construction
+
+  double rho = 0.8442; // Number density of the system
+  double delta = 0; // Scaling factor for random offsets of atom positions
+
+
+  /* read in command-line arguments */
+
+  for(int i = 0; i < argc; i++) {
+    if((strcmp(argv[i], "-t") == 0) || (strcmp(argv[i], "--num_threads") == 0)) {
+      num_threads = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "--teams") == 0)) {
+      teams = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "-d") == 0) || (strcmp(argv[i], "--device") == 0))  {
+      device = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "--delta") == 0)) {
+      delta = atof(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "-i") == 0) || (strcmp(argv[i], "--iter") == 0))  {
+      iter = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "-rho") == 0)) {
+      rho = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "--size") == 0)) {
+      system_size = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "-nx") == 0)) {
+      nx = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "-ny") == 0)) {
+      ny = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "-nz") == 0)) {
+      nz = atoi(argv[++i]);
+      continue;
+    }
+
+    if((strcmp(argv[i], "-b") == 0) || (strcmp(argv[i], "--neigh_bins") == 0))  {
+      neighbor_size = atoi(argv[++i]);
+      continue;
+    }
+  }
+
+  if( nx < 0 ) nx = system_size;
+  if( ny < 0 ) ny = system_size;
+  if( nz < 0 ) nz = system_size;
+
+  printf("-> Init Device\n");
+
+#if defined( KOKKOS_HAVE_CUDA )
+  Kokkos::HostSpace::execution_space::initialize(teams*num_threads);
+  Kokkos::Cuda::SelectDevice select_device(device);
+  Kokkos::Cuda::initialize(select_device);
+#elif defined( KOKKOS_HAVE_OPENMP )
+  Kokkos::OpenMP::initialize(teams*num_threads);
+#elif defined( KOKKOS_HAVE_PTHREAD )
+  Kokkos::Threads::initialize(teams*num_threads);
+#endif
+
+  System system;
+  system.neigh_cut = 2.8;
+  system.force_cut = 2.5;
+  system.force_cutsq = system.force_cut*system.force_cut;
+  system.delta = delta;
+
+  printf("-> Build system\n");
+  create_system(system,nx,ny,nz,rho);
+
+  printf("-> Created %i atoms and %i ghost atoms\n",system.nlocal,system.nghost);
+
+  system.nbinx = system.box.xprd/neighbor_size+1;
+  system.nbiny = system.box.yprd/neighbor_size+1;
+  system.nbinz = system.box.zprd/neighbor_size+1;
+
+
+  printf("-> Building Neighborlist\n");
+
+  neigh_setup(system);
+  neigh_build(system);
+
+  double2 ev = force(system,1);
+
+  printf("-> Calculate Energy: %f Virial: %f\n",ev.x,ev.y);
+
+  printf("-> Running %i force calculations\n",iter);
+
+  Kokkos::Timer timer;
+
+  for(int i=0;i<iter;i++) {
+    force(system,0);
+  }
+
+
+  double time = timer.seconds();
+  printf("Time: %e s for %i iterations with %i atoms\n",time,iter,system.nlocal);
+
+  execution_space::finalize();
+}
diff --git a/lib/kokkos/example/md_skeleton/neighbor.cpp b/lib/kokkos/example/md_skeleton/neighbor.cpp
new file mode 100644
index 0000000000..2a77932946
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/neighbor.cpp
@@ -0,0 +1,430 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <system.h>
+#include <cstdio>
+#include <Kokkos_Core.hpp>
+
+#define SMALL 1.0e-6
+#define FACTOR 0.999
+
+/* BinningFunctor puts atoms into bins of the simulation box
+ * Neighborlists are then created by checking only distances of atoms
+ * in adjacent bins. That makes neighborlist construction a O(N) operation.
+ */
+
+struct BinningFunctor {
+  typedef t_int_2d::execution_space execution_space;
+
+  System s;
+
+  int atoms_per_bin;
+
+  BinningFunctor(System _s): s(_s) {
+    atoms_per_bin = s.bins.dimension_1();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int &i) const
+  {
+    const int ibin = coord2bin(s.d_x(i, 0), s.d_x(i, 1), s.d_x(i, 2));
+
+    const int ac = Kokkos::atomic_fetch_add(&s.bincount[ibin], 1);
+
+    if(ac < atoms_per_bin) {
+      s.bins(ibin, ac) = i;
+    } else if(s.d_resize(0) < ac) {
+      s.d_resize(0) = ac;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  int coord2bin(double x, double y, double z) const
+  {
+    int ix, iy, iz;
+
+    if(x >= s.box.xprd)
+      ix = (int)((x - s.box.xprd) * s.bininvx) + s.nbinx - s.mbinxlo;
+    else if(x >= 0.0)
+      ix = (int)(x * s.bininvx) - s.mbinxlo;
+    else
+      ix = (int)(x * s.bininvx) - s.mbinxlo - 1;
+
+    if(y >= s.box.yprd)
+      iy = (int)((y - s.box.yprd) * s.bininvy) + s.nbiny - s.mbinylo;
+    else if(y >= 0.0)
+      iy = (int)(y * s.bininvy) - s.mbinylo;
+    else
+      iy = (int)(y * s.bininvy) - s.mbinylo - 1;
+
+    if(z >= s.box.zprd)
+      iz = (int)((z - s.box.zprd) * s.bininvz) + s.nbinz - s.mbinzlo;
+    else if(z >= 0.0)
+      iz = (int)(z * s.bininvz) - s.mbinzlo;
+    else
+      iz = (int)(z * s.bininvz) - s.mbinzlo - 1;
+
+    return (iz * s.mbiny * s.mbinx + iy * s.mbinx + ix + 1);
+  }
+};
+
+/* Build the actual neighborlist*/
+
+struct BuildFunctor {
+
+  typedef t_int_2d::execution_space execution_space;
+
+  System s;
+
+  int maxneighs;
+  BuildFunctor(System _s): s(_s) {
+    maxneighs = s.neighbors.dimension_1();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int &i) const
+  {
+    int n = 0;
+
+    const t_int_1d_const_um bincount_c = s.bincount;
+
+    const double xtmp = s.d_x(i, 0);
+    const double ytmp = s.d_x(i, 1);
+    const double ztmp = s.d_x(i, 2);
+
+    const int ibin = coord2bin(xtmp, ytmp, ztmp);
+
+    // loop over all bins in neighborhood (includes ibin)
+    for(int k = 0; k < s.nstencil; k++) {
+      const int jbin = ibin + s.d_stencil[k];
+
+      // get subview of jbin
+      const t_int_1d_const_um loc_bin =
+          Kokkos::subview(s.bins,jbin,Kokkos::ALL());
+
+      if(ibin == jbin)
+        for(int m = 0; m < bincount_c[jbin]; m++) {
+          const int j = loc_bin[m];
+
+          //for same bin as atom i skip j if i==j
+          if (j == i) continue;
+
+          const double delx = xtmp - s.d_x(j, 0);
+          const double dely = ytmp - s.d_x(j, 1);
+          const double delz = ztmp - s.d_x(j, 2);
+          const double rsq = delx * delx + dely * dely + delz * delz;
+
+          if(rsq <= s.neigh_cutsq && n<maxneighs) s.neighbors(i,n++) = j;
+        }
+      else {
+        for(int m = 0; m < bincount_c[jbin]; m++) {
+          const int j = loc_bin[m];
+
+          const double delx = xtmp - s.d_x(j, 0);
+          const double dely = ytmp - s.d_x(j, 1);
+          const double delz = ztmp - s.d_x(j, 2);
+          const double rsq = delx * delx + dely * dely + delz * delz;
+
+          if(rsq <= s.neigh_cutsq && n<maxneighs) s.neighbors(i,n++) = j;
+        }
+      }
+    }
+
+    s.numneigh[i] = n;
+
+    if(n >= maxneighs) {
+      if(n >= s.d_resize(0)) s.d_resize(0) = n;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  int coord2bin(double x, double y, double z) const
+  {
+    int ix, iy, iz;
+
+    if(x >= s.box.xprd)
+      ix = (int)((x - s.box.xprd) * s.bininvx) + s.nbinx - s.mbinxlo;
+    else if(x >= 0.0)
+      ix = (int)(x * s.bininvx) - s.mbinxlo;
+    else
+      ix = (int)(x * s.bininvx) - s.mbinxlo - 1;
+
+    if(y >= s.box.yprd)
+      iy = (int)((y - s.box.yprd) * s.bininvy) + s.nbiny - s.mbinylo;
+    else if(y >= 0.0)
+      iy = (int)(y * s.bininvy) - s.mbinylo;
+    else
+      iy = (int)(y * s.bininvy) - s.mbinylo - 1;
+
+    if(z >= s.box.zprd)
+      iz = (int)((z - s.box.zprd) * s.bininvz) + s.nbinz - s.mbinzlo;
+    else if(z >= 0.0)
+      iz = (int)(z * s.bininvz) - s.mbinzlo;
+    else
+      iz = (int)(z * s.bininvz) - s.mbinzlo - 1;
+
+    return (iz * s.mbiny * s.mbinx + iy * s.mbinx + ix + 1);
+  }
+};
+
+/* Reset an array to zero */
+
+struct MemsetZeroFunctor {
+  typedef t_x_array::execution_space  execution_space ;
+  void* ptr;
+  KOKKOS_INLINE_FUNCTION void operator()(const int i) const {
+    ((int*)ptr)[i] = 0;
+  }
+};
+
+/* Calculate distance of two bins */
+
+double bindist(System &s, int i, int j, int k)
+{
+  double delx, dely, delz;
+
+  if(i > 0)
+    delx = (i - 1) * s.binsizex;
+  else if(i == 0)
+    delx = 0.0;
+  else
+    delx = (i + 1) * s.binsizex;
+
+  if(j > 0)
+    dely = (j - 1) * s.binsizey;
+  else if(j == 0)
+    dely = 0.0;
+  else
+    dely = (j + 1) * s.binsizey;
+
+  if(k > 0)
+    delz = (k - 1) * s.binsizez;
+  else if(k == 0)
+    delz = 0.0;
+  else
+    delz = (k + 1) * s.binsizez;
+
+  return (delx * delx + dely * dely + delz * delz);
+}
+
+/* Setup the neighborlist construction
+ * Determine binsizes, a stencil for defining adjacency, etc.
+ */
+
+void neigh_setup(System &s) {
+
+  s.neigh_cutsq = s.neigh_cut * s.neigh_cut;
+
+  /*
+  c bins must evenly divide into box size,
+  c   becoming larger than cutneigh if necessary
+  c binsize = 1/2 of cutoff is near optimal
+
+  if (flag == 0) {
+    nbinx = 2.0 * xprd / cutneigh;
+    nbiny = 2.0 * yprd / cutneigh;
+    nbinz = 2.0 * zprd / cutneigh;
+    if (nbinx == 0) nbinx = 1;
+    if (nbiny == 0) nbiny = 1;
+    if (nbinz == 0) nbinz = 1;
+  }
+  */
+
+  s.binsizex = s.box.xprd / s.nbinx;
+  s.binsizey = s.box.yprd / s.nbiny;
+  s.binsizez = s.box.zprd / s.nbinz;
+  s.bininvx = 1.0 / s.binsizex;
+  s.bininvy = 1.0 / s.binsizey;
+  s.bininvz = 1.0 / s.binsizez;
+
+  double coord = s.box.xlo - s.neigh_cut - SMALL * s.box.xprd;
+  s.mbinxlo = static_cast<int>(coord * s.bininvx);
+
+  if(coord < 0.0) s.mbinxlo = s.mbinxlo - 1;
+
+  coord = s.box.xhi + s.neigh_cut + SMALL * s.box.xprd;
+  int mbinxhi = static_cast<int>(coord * s.bininvx);
+
+  coord = s.box.ylo - s.neigh_cut - SMALL * s.box.yprd;
+  s.mbinylo = static_cast<int>(coord * s.bininvy);
+
+  if(coord < 0.0) s.mbinylo = s.mbinylo - 1;
+
+  coord = s.box.yhi + s.neigh_cut + SMALL * s.box.yprd;
+  int mbinyhi = static_cast<int>(coord * s.bininvy);
+
+  coord = s.box.zlo - s.neigh_cut - SMALL * s.box.zprd;
+  s.mbinzlo = static_cast<int>(coord * s.bininvz);
+
+  if(coord < 0.0) s.mbinzlo = s.mbinzlo - 1;
+
+  coord = s.box.zhi + s.neigh_cut + SMALL * s.box.zprd;
+  int mbinzhi = static_cast<int>(coord * s.bininvz);
+
+  /* extend bins by 1 in each direction to insure stencil coverage */
+
+  s.mbinxlo = s.mbinxlo - 1;
+  mbinxhi = mbinxhi + 1;
+  s.mbinx = mbinxhi - s.mbinxlo + 1;
+
+  s.mbinylo = s.mbinylo - 1;
+  mbinyhi = mbinyhi + 1;
+  s.mbiny = mbinyhi - s.mbinylo + 1;
+
+  s.mbinzlo = s.mbinzlo - 1;
+  mbinzhi = mbinzhi + 1;
+  s.mbinz = mbinzhi - s.mbinzlo + 1;
+
+  /*
+  compute bin stencil of all bins whose closest corner to central bin
+  is within neighbor cutoff
+  for partial Newton (newton = 0),
+  stencil is all surrounding bins including self
+  for full Newton (newton = 1),
+  stencil is bins to the "upper right" of central bin, does NOT include self
+  next(xyz) = how far the stencil could possibly extend
+  factor < 1.0 for special case of LJ benchmark so code will create
+  correct-size stencil when there are 3 bins for every 5 lattice spacings
+  */
+
+  int nextx = static_cast<int>(s.neigh_cut * s.bininvx);
+
+  if(nextx * s.binsizex < FACTOR * s.neigh_cut) nextx++;
+
+  int nexty = static_cast<int>(s.neigh_cut * s.bininvy);
+
+  if(nexty * s.binsizey < FACTOR * s.neigh_cut) nexty++;
+
+  int nextz = static_cast<int>(s.neigh_cut * s.bininvz);
+
+  if(nextz * s.binsizez < FACTOR * s.neigh_cut) nextz++;
+
+  int nmax = (2 * nextz + 1) * (2 * nexty + 1) * (2 * nextx + 1);
+  s.d_stencil = t_int_1d("stencil", nmax);
+  s.h_stencil = Kokkos::create_mirror_view(s.d_stencil);
+  s.nstencil = 0;
+  int kstart = -nextz;
+
+  for(int k = kstart; k <= nextz; k++) {
+    for(int j = -nexty; j <= nexty; j++) {
+      for(int i = -nextx; i <= nextx; i++) {
+        if(bindist(s,i, j, k) < s.neigh_cutsq) {
+          s.h_stencil(s.nstencil++) = k * s.mbiny * s.mbinx + j * s.mbinx + i;
+        }
+      }
+    }
+  }
+
+  /* Allocate neighbor arrays */
+
+  Kokkos::deep_copy(s.d_stencil, s.h_stencil);
+  s.mbins = s.mbinx * s.mbiny * s.mbinz;
+  s.bincount = t_int_1d("bincount", s.mbins);
+  s.bins = t_int_2d("bins", s.mbins, 8);
+
+  s.neighbors = t_neighbors("neighbors",s.natoms,80);
+  s.numneigh = t_int_1d("numneigh",s.natoms);
+  s.d_resize = t_int_scalar("resize");
+  s.h_resize = Kokkos::create_mirror_view(s.d_resize);
+}
+
+
+/* Build the neighborlist
+ * This is a try and rerun algorithm for handling the case where the bins array
+ * and the neighbors array are not big enough. So if one is too small, it will
+ * reallocate and rerun the binnind algorithm or the neighborlist construction.
+ */
+
+void neigh_build(System &s) {
+
+  /* Binning of atoms */
+
+  s.h_resize(0) = 1;
+
+  while(s.h_resize(0) > 0) {
+    s.h_resize(0) = 0;
+    Kokkos::deep_copy(s.d_resize, s.h_resize);
+
+    MemsetZeroFunctor f_zero;
+    f_zero.ptr = (void*) s.bincount.ptr_on_device();
+    Kokkos::parallel_for(s.mbins, f_zero);
+    execution_space::fence();
+
+    BinningFunctor f(s);
+    Kokkos::parallel_for(s.natoms, f);
+    execution_space::fence();
+
+    /* Check if bins was large enough, if nor reallocated and rerun */
+
+    deep_copy(s.h_resize, s.d_resize);
+
+    if(s.h_resize(0)) {
+      int atoms_per_bin = s.h_resize(0)+2;
+      s.bins = t_int_2d("bins", s.mbins, atoms_per_bin);
+    }
+  }
+
+  /* Neighborlist construction */
+
+  s.h_resize(0) = 1;
+
+  while(s.h_resize(0)) {
+    s.h_resize(0) = 0;
+
+    Kokkos::deep_copy(s.d_resize, s.h_resize);
+
+    BuildFunctor f(s);
+    Kokkos::parallel_for(s.nlocal, f);
+
+    execution_space::fence();
+
+    /* Check if neighbors was large enough, if nor reallocated and rerun */
+
+    deep_copy(s.h_resize, s.d_resize);
+
+    if(s.h_resize(0)) {
+      int maxneighs = s.h_resize(0) * 1.2;
+      s.neighbors = t_neighbors("neighbors", s.natoms, maxneighs);
+    }
+  }
+}
diff --git a/lib/kokkos/example/md_skeleton/setup.cpp b/lib/kokkos/example/md_skeleton/setup.cpp
new file mode 100644
index 0000000000..7815a89101
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/setup.cpp
@@ -0,0 +1,271 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <system.h>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+/* initialize atoms on fcc lattice in parallel fashion */
+
+#define MAX(a,b) (a>b?a:b)
+#define MIN(a,b) (a<b?a:b)
+
+
+int create_system(System &system, int nx, int ny, int nz, double rho)
+{
+  /* Box Setup */
+
+  double lattice = pow((4.0 / rho), (1.0 / 3.0));
+  system.box.xprd = nx * lattice;
+  system.box.yprd = ny * lattice;
+  system.box.zprd = nz * lattice;
+  system.box.xlo = 0;
+  system.box.ylo = 0;
+  system.box.zlo = 0;
+  system.box.xhi = system.box.xprd;
+  system.box.yhi = system.box.yprd;
+  system.box.zhi = system.box.zprd;
+
+
+  int ghost_dist = int(system.neigh_cut/lattice) + 1;
+
+  /* total # of atoms */
+
+  system.nlocal = 4 * nx * ny * nz;
+  system.nghost = 4 * (nx + 2 * ghost_dist) *
+                      (ny + 2 * ghost_dist) *
+                      (nz + 2 * ghost_dist) -
+                      system.nlocal;
+  system.natoms = system.nlocal + system.nghost;
+
+  system.d_x = t_x_array("X",system.natoms);
+  system.h_x = Kokkos::create_mirror_view(system.d_x);
+  system.f = t_f_array("F",system.natoms);
+
+  /* determine loop bounds of lattice subsection that overlaps my sub-box
+     insure loop bounds do not exceed nx,ny,nz */
+
+  double alat = pow((4.0 / rho), (1.0 / 3.0));
+  int ilo = static_cast<int>(system.box.xlo / (0.5 * alat) - 1);
+  int ihi = static_cast<int>(system.box.xhi / (0.5 * alat) + 1);
+  int jlo = static_cast<int>(system.box.ylo / (0.5 * alat) - 1);
+  int jhi = static_cast<int>(system.box.yhi / (0.5 * alat) + 1);
+  int klo = static_cast<int>(system.box.zlo / (0.5 * alat) - 1);
+  int khi = static_cast<int>(system.box.zhi / (0.5 * alat) + 1);
+
+  ilo = MAX(ilo, 0);
+  ihi = MIN(ihi, 2 * nx - 1);
+  jlo = MAX(jlo, 0);
+  jhi = MIN(jhi, 2 * ny - 1);
+  klo = MAX(klo, 0);
+  khi = MIN(khi, 2 * nz - 1);
+
+
+
+  /* generates positions of atoms on fcc sublattice*/
+
+  srand(3718273);
+  /* create non-ghost atoms */
+  {
+    double xtmp, ytmp, ztmp;
+    int sx = 0;
+    int sy = 0;
+    int sz = 0;
+    int ox = 0;
+    int oy = 0;
+    int oz = 0;
+    int subboxdim = 8;
+
+    int n = 0;
+    int iflag = 0;
+
+    while(oz * subboxdim <= khi) {
+      const int k = oz * subboxdim + sz;
+      const int j = oy * subboxdim + sy;
+      const int i = ox * subboxdim + sx;
+
+      if(iflag) continue;
+
+      if(((i + j + k) % 2 == 0) &&
+          (i >= ilo) && (i <= ihi) &&
+          (j >= jlo) && (j <= jhi) &&
+          (k >= klo) && (k <= khi)) {
+
+        const int nold = n;
+        while(nold == n) {
+          xtmp = 0.5 * alat * i + system.delta/1000*(rand()%1000-500);
+          ytmp = 0.5 * alat * j + system.delta/1000*(rand()%1000-500);
+          ztmp = 0.5 * alat * k + system.delta/1000*(rand()%1000-500);
+
+          if(xtmp >= system.box.xlo && xtmp < system.box.xhi &&
+              ytmp >= system.box.ylo && ytmp < system.box.yhi &&
+              ztmp >= system.box.zlo && ztmp < system.box.zhi) {
+            system.h_x(n,0) = xtmp;
+            system.h_x(n,1) = ytmp;
+            system.h_x(n,2) = ztmp;
+            n++;
+          }
+        }
+      }
+
+      sx++;
+
+      if(sx == subboxdim) {
+        sx = 0;
+        sy++;
+      }
+
+      if(sy == subboxdim) {
+        sy = 0;
+        sz++;
+      }
+
+      if(sz == subboxdim) {
+        sz = 0;
+        ox++;
+      }
+
+      if(ox * subboxdim > ihi) {
+        ox = 0;
+        oy++;
+      }
+
+      if(oy * subboxdim > jhi) {
+        oy = 0;
+        oz++;
+      }
+    }
+
+    /* check that correct # of atoms were created */
+
+    if(system.nlocal != n) {
+      printf("Created incorrect # of atoms\n");
+
+      return 1;
+    }
+  }
+
+  /* create ghost atoms */
+
+  {
+    double xtmp, ytmp, ztmp;
+
+    int ilo_g = ilo - 2 * ghost_dist;
+    int jlo_g = jlo - 2 * ghost_dist;
+    int klo_g = klo - 2 * ghost_dist;
+    int ihi_g = ihi + 2 * ghost_dist;
+    int jhi_g = jhi + 2 * ghost_dist;
+    int khi_g = khi + 2 * ghost_dist;
+
+    int subboxdim = 8;
+    int sx = 0;
+    int sy = 0;
+    int sz = 0;
+    int ox = subboxdim * ilo_g;
+    int oy = subboxdim * jlo_g;
+    int oz = subboxdim * klo_g;
+
+    int n = system.nlocal;
+    int iflag = 0;
+
+
+    while(oz * subboxdim <= khi_g) {
+      const int k = oz * subboxdim + sz;
+      const int j = oy * subboxdim + sy;
+      const int i = ox * subboxdim + sx;
+
+      if(iflag) continue;
+
+      if(((i + j + k) % 2 == 0) &&
+          (i >= ilo_g) && (i <= ihi_g) &&
+          (j >= jlo_g) && (j <= jhi_g) &&
+          (k >= klo_g) && (k <= khi_g) &&
+          ((i < ilo) || (i > ihi) ||
+           (j < jlo) || (j > jhi) ||
+           (k < klo) || (k > khi))
+          ) {
+
+        xtmp = 0.5 * alat * i;
+        ytmp = 0.5 * alat * j;
+        ztmp = 0.5 * alat * k;
+
+        system.h_x(n,0) = xtmp + system.delta/1000*(rand()%1000-500);;
+        system.h_x(n,1) = ytmp + system.delta/1000*(rand()%1000-500);;
+        system.h_x(n,2) = ztmp + system.delta/1000*(rand()%1000-500);;
+        n++;
+      }
+
+      sx++;
+
+      if(sx == subboxdim) {
+        sx = 0;
+        sy++;
+      }
+
+      if(sy == subboxdim) {
+        sy = 0;
+        sz++;
+      }
+
+      if(sz == subboxdim) {
+        sz = 0;
+        ox++;
+        //printf("%i %i %i // %i %i %i\n",ox,oy,oz,i,j,k);
+      }
+
+      if(ox * subboxdim > ihi_g) {
+        ox = subboxdim * ilo_g;
+        oy++;
+      }
+
+      if(oy * subboxdim > jhi_g) {
+        oy = subboxdim * jlo_g;
+        oz++;
+      }
+    }
+  }
+
+  Kokkos::deep_copy(system.d_x,system.h_x);
+  return 0;
+}
+
diff --git a/lib/kokkos/example/md_skeleton/system.h b/lib/kokkos/example/md_skeleton/system.h
new file mode 100644
index 0000000000..0184a119ff
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/system.h
@@ -0,0 +1,92 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef SYSTEM_H_
+#define SYSTEM_H_
+
+#include <types.h>
+
+struct Box {
+  double xprd, yprd, zprd;
+  double xlo, xhi;
+  double ylo, yhi;
+  double zlo, zhi;
+};
+
+struct System {
+  Box box;
+
+  int natoms;
+  int nlocal;
+  int nghost;
+
+  t_x_array d_x;
+  t_x_array_host h_x;
+
+  t_f_array f;
+
+  t_neighbors neighbors;
+  t_int_1d numneigh;
+
+  double delta;
+
+  double neigh_cut,neigh_cutsq;
+
+  int mbins;
+  int nbinx,nbiny,nbinz;
+  int mbinx,mbiny,mbinz;
+  int mbinxlo,mbinylo,mbinzlo;
+  double binsizex,binsizey,binsizez;
+  double bininvx,bininvy,bininvz;
+
+  t_int_1d bincount;
+  t_int_2d bins;
+  t_int_scalar d_resize;
+  t_int_scalar_host h_resize;
+  t_int_1d d_stencil;
+  t_int_1d_host h_stencil;
+  int nstencil;
+
+  double force_cut,force_cutsq;
+};
+#endif
diff --git a/lib/kokkos/example/md_skeleton/types.h b/lib/kokkos/example/md_skeleton/types.h
new file mode 100644
index 0000000000..7f92b7cd0f
--- /dev/null
+++ b/lib/kokkos/example/md_skeleton/types.h
@@ -0,0 +1,118 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef TYPES_H_
+#define TYPES_H_
+
+/* Determine default device type and necessary includes */
+
+#include <Kokkos_Core.hpp>
+
+typedef Kokkos::DefaultExecutionSpace execution_space ;
+
+#if ! defined( KOKKOS_HAVE_CUDA )
+  struct double2 {
+    double x, y;
+    KOKKOS_INLINE_FUNCTION
+    double2(double xinit, double yinit) {
+      x = xinit;
+      y = yinit;
+    }
+    KOKKOS_INLINE_FUNCTION
+    double2() {
+      x = 0.0;
+      y = 0.0;
+    }
+    KOKKOS_INLINE_FUNCTION
+    double2& operator += (const double2& src) {
+      x+=src.x;
+      y+=src.y;
+      return *this;
+    }
+
+    KOKKOS_INLINE_FUNCTION
+    volatile double2& operator += (const volatile double2& src) volatile {
+      x+=src.x;
+      y+=src.y;
+      return *this;
+    }
+
+  };
+#endif
+
+#include <impl/Kokkos_Timer.hpp>
+
+/* Define types used throughout the code */
+
+//Position arrays
+typedef Kokkos::View<double*[3], Kokkos::LayoutRight, execution_space>                                   t_x_array ;
+typedef t_x_array::HostMirror                                                                        t_x_array_host ;
+typedef Kokkos::View<const double*[3], Kokkos::LayoutRight, execution_space>                             t_x_array_const ;
+typedef Kokkos::View<const double*[3], Kokkos::LayoutRight, execution_space, Kokkos::MemoryRandomAccess >  t_x_array_randomread ;
+
+//Force array
+typedef Kokkos::View<double*[3],  execution_space>                                                       t_f_array ;
+
+
+//Neighborlist
+typedef Kokkos::View<int**, execution_space >                                                            t_neighbors ;
+typedef Kokkos::View<const int**, execution_space >                                                      t_neighbors_const ;
+typedef Kokkos::View<int*, execution_space, Kokkos::MemoryUnmanaged >                                    t_neighbors_sub ;
+typedef Kokkos::View<const int*, execution_space, Kokkos::MemoryUnmanaged >                              t_neighbors_const_sub ;
+
+//1d int array
+typedef Kokkos::View<int*, execution_space >                                                             t_int_1d ;
+typedef t_int_1d::HostMirror                                                                         t_int_1d_host ;
+typedef Kokkos::View<const int*, execution_space >                                                       t_int_1d_const ;
+typedef Kokkos::View<int*, execution_space , Kokkos::MemoryUnmanaged>                                    t_int_1d_um ;
+typedef Kokkos::View<const int* , execution_space , Kokkos::MemoryUnmanaged>                             t_int_1d_const_um ;
+
+//2d int array
+typedef Kokkos::View<int**, Kokkos::LayoutRight, execution_space >                                       t_int_2d ;
+typedef t_int_2d::HostMirror                                                                         t_int_2d_host ;
+
+//Scalar ints
+typedef Kokkos::View<int[1], Kokkos::LayoutLeft, execution_space>                                        t_int_scalar ;
+typedef t_int_scalar::HostMirror                                                                     t_int_scalar_host ;
+
+#endif /* TYPES_H_ */
diff --git a/lib/kokkos/example/multi_fem/BoxMeshFixture.hpp b/lib/kokkos/example/multi_fem/BoxMeshFixture.hpp
new file mode 100644
index 0000000000..195bb4a6ae
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/BoxMeshFixture.hpp
@@ -0,0 +1,610 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_BOXMESHFIXTURE_HPP
+#define KOKKOS_BOXMESHFIXTURE_HPP
+
+#include <cmath>
+#include <stdexcept>
+#include <sstream>
+
+#include <Kokkos_Core.hpp>
+#include <BoxMeshPartition.hpp>
+#include <FEMesh.hpp>
+#include <HexElement.hpp>
+
+//----------------------------------------------------------------------------
+
+struct FixtureElementHex8 {
+
+  static const unsigned element_node_count = 8 ;
+
+  HybridFEM::HexElement_TensorData< element_node_count > elem_data ;
+  BoxBoundsLinear box_bounds ;
+
+  FixtureElementHex8() : elem_data(), box_bounds() {}
+
+  static void create_node_boxes_from_vertex_boxes(
+    const BoxType                & vertex_box_global ,
+    const std::vector< BoxType > & vertex_box_parts ,
+          BoxType                & node_box_global ,
+          std::vector< BoxType > & node_box_parts )
+  {
+    node_box_global = vertex_box_global ;
+    node_box_parts  = vertex_box_parts  ;
+  }
+
+  void elem_to_node( const unsigned node_local , unsigned coord[] ) const
+  {
+    coord[0] += elem_data.eval_map[ node_local ][0] ;
+    coord[1] += elem_data.eval_map[ node_local ][1] ;
+    coord[2] += elem_data.eval_map[ node_local ][2] ;
+  }
+};
+
+struct FixtureElementHex27 {
+  static const unsigned element_node_count = 27 ;
+
+  HybridFEM::HexElement_TensorData< element_node_count > elem_data ;
+  BoxBoundsQuadratic box_bounds ;
+
+  FixtureElementHex27() : elem_data(), box_bounds() {}
+
+  static void create_node_boxes_from_vertex_boxes(
+    const BoxType                & vertex_box_global ,
+    const std::vector< BoxType > & vertex_box_parts ,
+          BoxType                & node_box_global ,
+          std::vector< BoxType > & node_box_parts )
+  {
+    node_box_global = vertex_box_global ;
+    node_box_parts  = vertex_box_parts  ;
+
+    node_box_global[0][1] = 2 * node_box_global[0][1] - 1 ;
+    node_box_global[1][1] = 2 * node_box_global[1][1] - 1 ;
+    node_box_global[2][1] = 2 * node_box_global[2][1] - 1 ;
+
+    for ( unsigned i = 0 ; i < vertex_box_parts.size() ; ++i ) {
+      node_box_parts[i][0][0] = 2 * node_box_parts[i][0][0] ;
+      node_box_parts[i][1][0] = 2 * node_box_parts[i][1][0] ;
+      node_box_parts[i][2][0] = 2 * node_box_parts[i][2][0] ;
+
+      node_box_parts[i][0][1] =
+        std::min( node_box_global[0][1] , 2 * node_box_parts[i][0][1] );
+      node_box_parts[i][1][1] =
+        std::min( node_box_global[1][1] , 2 * node_box_parts[i][1][1] );
+      node_box_parts[i][2][1] =
+        std::min( node_box_global[2][1] , 2 * node_box_parts[i][2][1] );
+    }
+  }
+
+  void elem_to_node( const unsigned node_local , unsigned coord[] ) const
+  {
+    coord[0] = 2 * coord[0] + elem_data.eval_map[ node_local ][0] ;
+    coord[1] = 2 * coord[1] + elem_data.eval_map[ node_local ][1] ;
+    coord[2] = 2 * coord[2] + elem_data.eval_map[ node_local ][2] ;
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class Device , class ElementSpec >
+struct BoxMeshFixture {
+
+  typedef Scalar  coordinate_scalar_type ;
+  typedef Device  execution_space ;
+
+  static const unsigned element_node_count = ElementSpec::element_node_count ;
+
+  typedef HybridFEM::FEMesh< coordinate_scalar_type ,
+                             element_node_count ,
+                             execution_space > FEMeshType ;
+
+  typedef typename FEMeshType::node_coords_type    node_coords_type ;
+  typedef typename FEMeshType::elem_node_ids_type  elem_node_ids_type ;
+  typedef typename FEMeshType::node_elem_ids_type  node_elem_ids_type ;
+
+
+  static void verify(
+    const typename FEMeshType::node_coords_type::HostMirror   & node_coords ,
+    const typename FEMeshType::elem_node_ids_type::HostMirror & elem_node_ids ,
+    const typename FEMeshType::node_elem_ids_type::HostMirror & node_elem_ids )
+  {
+    typedef typename FEMeshType::size_type         size_type ;
+    //typedef typename node_coords_type::value_type  coords_type ; // unused
+
+    const size_type node_count_total = node_coords.dimension_0();
+    const size_type elem_count_total = elem_node_ids.dimension_0();
+
+    const ElementSpec element ;
+
+    for ( size_type node_index = 0 ;
+                    node_index < node_count_total ; ++node_index ) {
+
+      for ( size_type
+              j = node_elem_ids.row_map[ node_index ] ;
+              j < node_elem_ids.row_map[ node_index + 1 ] ; ++j ) {
+
+        const size_type elem_index = node_elem_ids.entries(j,0);
+        const size_type node_local = node_elem_ids.entries(j,1);
+        const size_type en_id      = elem_node_ids(elem_index,node_local);
+
+        if ( node_index != en_id ) {
+          std::ostringstream msg ;
+          msg << "BoxMeshFixture node_elem_ids error"
+              << " : node_index(" << node_index
+              << ") entry(" << j
+              << ") elem_index(" << elem_index
+              << ") node_local(" << node_local
+              << ") elem_node_id(" << en_id
+              << ")" ;
+          throw std::runtime_error( msg.str() );
+        }
+      }
+    }
+
+    for ( size_type elem_index = 0 ;
+                    elem_index < elem_count_total; ++elem_index ) {
+
+      coordinate_scalar_type elem_node_coord[ element_node_count ][3] ;
+
+      for ( size_type nn = 0 ; nn < element_node_count ; ++nn ) {
+        const size_type node_index = elem_node_ids( elem_index , nn );
+
+        for ( size_type nc = 0 ; nc < 3 ; ++nc ) {
+          elem_node_coord[nn][nc] = node_coords( node_index , nc );
+        }
+      }
+
+
+      for ( size_type nn = 0 ; nn < element_node_count ; ++nn ) {
+
+        const unsigned ix = element.elem_data.eval_map[nn][0] ;
+        const unsigned iy = element.elem_data.eval_map[nn][1] ;
+        const unsigned iz = element.elem_data.eval_map[nn][2] ;
+
+        if ( elem_node_coord[nn][0] != elem_node_coord[0][0] + ix ||
+             elem_node_coord[nn][1] != elem_node_coord[0][1] + iy ||
+             elem_node_coord[nn][2] != elem_node_coord[0][2] + iz ) {
+
+          std::ostringstream msg ;
+          msg << "BoxMeshFixture elem_node_coord mapping failure { "
+              << elem_node_coord[nn][0] << " "
+              << elem_node_coord[nn][1] << " "
+              << elem_node_coord[nn][2] << " } != { "
+              << elem_node_coord[ 0][0] + ix << " "
+              << elem_node_coord[ 0][1] + iy << " "
+              << elem_node_coord[ 0][2] + iz
+              << " }" ;
+          throw std::runtime_error( msg.str() );
+        }
+      }
+    }
+  }
+
+  //------------------------------------
+  // Initialize element-node connectivity:
+  // Order elements that only depend on owned nodes first.
+  // These elements could be computed while waiting for
+  // received node data.
+
+  static void layout_elements_interior_exterior(
+    const BoxType                vertex_box_local_used ,
+    const BoxType                vertex_box_local_owned ,
+    const BoxType                node_box_local_used ,
+    const std::vector<size_t> &  node_used_id_map ,
+    const ElementSpec            element_fixture ,
+    const size_t                 elem_count_interior ,
+    const typename elem_node_ids_type::HostMirror elem_node_ids )
+  {
+    size_t elem_index_interior = 0 ;
+    size_t elem_index_boundary = elem_count_interior ;
+
+    for ( size_t iz = vertex_box_local_used[2][0] ;
+                 iz < vertex_box_local_used[2][1] - 1 ; ++iz ) {
+    for ( size_t iy = vertex_box_local_used[1][0] ;
+                 iy < vertex_box_local_used[1][1] - 1 ; ++iy ) {
+    for ( size_t ix = vertex_box_local_used[0][0] ;
+                 ix < vertex_box_local_used[0][1] - 1 ; ++ix ) {
+
+      size_t elem_index ;
+
+      // If lower and upper vertices are owned then element is interior
+      if ( contain( vertex_box_local_owned, ix,   iy,   iz ) &&
+           contain( vertex_box_local_owned, ix+1, iy+1, iz+1 ) ) {
+        elem_index = elem_index_interior++ ;
+      }
+      else {
+        elem_index = elem_index_boundary++ ;
+      }
+
+      for ( size_t nn = 0 ; nn < element_node_count ; ++nn ) {
+        unsigned coord[3] = { static_cast<unsigned>(ix) , static_cast<unsigned>(iy) , static_cast<unsigned>(iz) };
+
+        element_fixture.elem_to_node( nn , coord );
+
+        const size_t node_local_id =
+          box_map_id( node_box_local_used ,
+                      node_used_id_map ,
+                      coord[0] , coord[1] , coord[2] );
+
+        elem_node_ids( elem_index , nn ) = node_local_id ;
+      }
+    }}}
+  }
+
+  //------------------------------------
+  // Nested partitioning of elements by number of thread 'gangs'
+
+  static void layout_elements_partitioned(
+    const BoxType                vertex_box_local_used ,
+    const BoxType                /*vertex_box_local_owned*/ ,
+    const BoxType                node_box_local_used ,
+    const std::vector<size_t> &  node_used_id_map ,
+    const ElementSpec            element_fixture ,
+    const size_t                 thread_gang_count ,
+    const typename elem_node_ids_type::HostMirror elem_node_ids )
+  {
+    std::vector< BoxType > element_box_gangs( thread_gang_count );
+
+    BoxType element_box_local_used = vertex_box_local_used ;
+
+    element_box_local_used[0][1] -= 1 ;
+    element_box_local_used[1][1] -= 1 ;
+    element_box_local_used[2][1] -= 1 ;
+
+    box_partition_rcb( element_box_local_used , element_box_gangs );
+
+    size_t elem_index = 0 ;
+
+    for ( size_t ig = 0 ; ig < thread_gang_count ; ++ig ) {
+
+      const BoxType box = element_box_gangs[ig] ;
+
+      for ( size_t iz = box[2][0] ; iz < box[2][1] ; ++iz ) {
+      for ( size_t iy = box[1][0] ; iy < box[1][1] ; ++iy ) {
+      for ( size_t ix = box[0][0] ; ix < box[0][1] ; ++ix , ++elem_index ) {
+
+        for ( size_t nn = 0 ; nn < element_node_count ; ++nn ) {
+          unsigned coord[3] = { static_cast<unsigned>(ix) , static_cast<unsigned>(iy) , static_cast<unsigned>(iz) };
+
+          element_fixture.elem_to_node( nn , coord );
+
+          const size_t node_local_id =
+            box_map_id( node_box_local_used ,
+                        node_used_id_map ,
+                        coord[0] , coord[1] , coord[2] );
+
+          elem_node_ids( elem_index , nn ) = node_local_id ;
+        }
+      }}}
+    }
+  }
+
+  //------------------------------------
+
+  static FEMeshType create( const size_t proc_count ,
+                            const size_t proc_local ,
+                            const size_t gang_count ,
+                            const size_t elems_x ,
+                            const size_t elems_y ,
+                            const size_t elems_z ,
+                            const double x_coord_curve = 1 ,
+                            const double y_coord_curve = 1 ,
+                            const double z_coord_curve = 1 )
+  {
+    const size_t vertices_x = elems_x + 1 ;
+    const size_t vertices_y = elems_y + 1 ;
+    const size_t vertices_z = elems_z + 1 ;
+
+    const BoxBoundsLinear vertex_box_bounds ;
+    const ElementSpec element ;
+
+    // Partition based upon vertices:
+
+    BoxType vertex_box_global ;
+    std::vector< BoxType > vertex_box_parts( proc_count );
+
+    vertex_box_global[0][0] = 0 ; vertex_box_global[0][1] = vertices_x ;
+    vertex_box_global[1][0] = 0 ; vertex_box_global[1][1] = vertices_y ;
+    vertex_box_global[2][0] = 0 ; vertex_box_global[2][1] = vertices_z ;
+
+    box_partition_rcb( vertex_box_global , vertex_box_parts );
+
+    const BoxType vertex_box_local_owned = vertex_box_parts[ proc_local ];
+
+    // Determine interior and used vertices:
+
+    BoxType vertex_box_local_interior ;
+    BoxType vertex_box_local_used ;
+
+    vertex_box_bounds.apply( vertex_box_global ,
+                             vertex_box_local_owned ,
+                             vertex_box_local_interior ,
+                             vertex_box_local_used );
+
+    // Element counts:
+
+    const long local_elems_x =
+      ( vertex_box_local_used[0][1] - vertex_box_local_used[0][0] ) - 1 ;
+    const long local_elems_y =
+      ( vertex_box_local_used[1][1] - vertex_box_local_used[1][0] ) - 1 ;
+    const long local_elems_z =
+      ( vertex_box_local_used[2][1] - vertex_box_local_used[2][0] ) - 1 ;
+
+    const size_t elem_count_total = std::max( long(0) , local_elems_x ) *
+                                    std::max( long(0) , local_elems_y ) *
+                                    std::max( long(0) , local_elems_z );
+
+    const long interior_elems_x =
+      ( vertex_box_local_owned[0][1] - vertex_box_local_owned[0][0] ) - 1 ;
+    const long interior_elems_y =
+      ( vertex_box_local_owned[1][1] - vertex_box_local_owned[1][0] ) - 1 ;
+    const long interior_elems_z =
+      ( vertex_box_local_owned[2][1] - vertex_box_local_owned[2][0] ) - 1 ;
+
+    const size_t elem_count_interior = std::max( long(0) , interior_elems_x ) *
+                                       std::max( long(0) , interior_elems_y ) *
+                                       std::max( long(0) , interior_elems_z );
+
+    // Expand vertex boxes to node boxes:
+
+    BoxType node_box_global ;
+    BoxType node_box_local_used ;
+    std::vector< BoxType > node_box_parts ;
+
+    element.create_node_boxes_from_vertex_boxes(
+      vertex_box_global , vertex_box_parts ,
+      node_box_global , node_box_parts );
+
+    // Node communication maps:
+
+    size_t node_count_interior = 0 ;
+    size_t node_count_owned    = 0 ;
+    size_t node_count_total    = 0 ;
+    std::vector<size_t>                 node_used_id_map ;
+    std::vector<size_t>                 node_part_counts ;
+    std::vector< std::vector<size_t> >  node_send_map ;
+
+    box_partition_maps( node_box_global ,
+                        node_box_parts ,
+                        element.box_bounds ,
+                        proc_local ,
+                        node_box_local_used ,
+                        node_used_id_map ,
+                        node_count_interior ,
+                        node_count_owned ,
+                        node_count_total ,
+                        node_part_counts ,
+                        node_send_map );
+
+    size_t node_count_send = 0 ;
+    for ( size_t i = 0 ; i < node_send_map.size() ; ++i ) {
+      node_count_send += node_send_map[i].size();
+    }
+
+    size_t recv_msg_count = 0 ;
+    size_t send_msg_count = 0 ;
+    size_t send_count = 0 ;
+
+    for ( size_t i = 1 ; i < proc_count ; ++i ) {
+      if ( node_part_counts[i] ) ++recv_msg_count ;
+      if ( node_send_map[i].size() ) {
+        ++send_msg_count ;
+        send_count += node_send_map[i].size();
+      }
+    }
+
+    // Finite element mesh:
+
+    FEMeshType mesh ;
+
+    if ( node_count_total ) {
+      mesh.node_coords = node_coords_type( "node_coords", node_count_total );
+    }
+
+    if ( elem_count_total ) {
+      mesh.elem_node_ids =
+        elem_node_ids_type( "elem_node_ids", elem_count_total );
+    }
+
+    mesh.parallel_data_map.assign( node_count_interior ,
+                                   node_count_owned ,
+                                   node_count_total ,
+                                   recv_msg_count ,
+                                   send_msg_count ,
+                                   send_count );
+
+    typename node_coords_type::HostMirror node_coords =
+      Kokkos::create_mirror( mesh.node_coords );
+
+    typename elem_node_ids_type::HostMirror elem_node_ids =
+      Kokkos::create_mirror( mesh.elem_node_ids );
+
+    //------------------------------------
+    // set node coordinates to grid location for subsequent verification
+
+    for ( size_t iz = node_box_local_used[2][0] ;
+                 iz < node_box_local_used[2][1] ; ++iz ) {
+
+    for ( size_t iy = node_box_local_used[1][0] ;
+                 iy < node_box_local_used[1][1] ; ++iy ) {
+
+    for ( size_t ix = node_box_local_used[0][0] ;
+                 ix < node_box_local_used[0][1] ; ++ix ) {
+
+      const size_t node_local_id =
+        box_map_id( node_box_local_used , node_used_id_map , ix , iy , iz );
+
+      node_coords( node_local_id , 0 ) = ix ;
+      node_coords( node_local_id , 1 ) = iy ;
+      node_coords( node_local_id , 2 ) = iz ;
+    }}}
+
+    //------------------------------------
+    // Initialize element-node connectivity:
+
+    if ( 1 < gang_count ) {
+      layout_elements_partitioned( vertex_box_local_used ,
+                                   vertex_box_local_owned ,
+                                   node_box_local_used ,
+                                   node_used_id_map ,
+                                   element ,
+                                   gang_count ,
+                                   elem_node_ids );
+    }
+    else {
+      layout_elements_interior_exterior( vertex_box_local_used ,
+                                         vertex_box_local_owned ,
+                                         node_box_local_used ,
+                                         node_used_id_map ,
+                                         element ,
+                                         elem_count_interior ,
+                                         elem_node_ids );
+    }
+
+    //------------------------------------
+    // Populate node->element connectivity:
+
+    std::vector<size_t> node_elem_work( node_count_total , (size_t) 0 );
+
+    for ( size_t i = 0 ; i < elem_count_total ; ++i ) {
+      for ( size_t n = 0 ; n < element_node_count  ; ++n ) {
+        ++node_elem_work[ elem_node_ids(i,n) ];
+      }
+    }
+
+    mesh.node_elem_ids =
+      Kokkos::create_staticcrsgraph< node_elem_ids_type >( "node_elem_ids" , node_elem_work );
+
+    typename node_elem_ids_type::HostMirror
+      node_elem_ids = Kokkos::create_mirror( mesh.node_elem_ids );
+
+    for ( size_t i = 0 ; i < node_count_total ; ++i ) {
+      node_elem_work[i] = node_elem_ids.row_map[i];
+    }
+
+    // Looping in element order insures the list of elements
+    // is sorted by element index.
+
+    for ( size_t i = 0 ; i < elem_count_total ; ++i ) {
+      for ( size_t n = 0 ; n < element_node_count ; ++n ) {
+        const unsigned nid = elem_node_ids(i, n);
+        const unsigned j = node_elem_work[nid] ; ++node_elem_work[nid] ;
+
+        node_elem_ids.entries( j , 0 ) = i ;
+        node_elem_ids.entries( j , 1 ) = n ;
+      }
+    }
+    //------------------------------------
+    // Verify setup with node coordinates matching grid indices.
+    verify( node_coords , elem_node_ids , node_elem_ids );
+
+    //------------------------------------
+    // Scale node coordinates to problem extent with
+    // nonlinear mapping.
+    {
+      const double problem_extent[3] =
+        { static_cast<double>( vertex_box_global[0][1] - 1 ) ,
+          static_cast<double>( vertex_box_global[1][1] - 1 ) ,
+          static_cast<double>( vertex_box_global[2][1] - 1 ) };
+
+      const double grid_extent[3] =
+        { static_cast<double>( node_box_global[0][1] - 1 ) ,
+          static_cast<double>( node_box_global[1][1] - 1 ) ,
+          static_cast<double>( node_box_global[2][1] - 1 ) };
+
+      for ( size_t i = 0 ; i < node_count_total ; ++i ) {
+        const double x_unit = node_coords(i,0) / grid_extent[0] ;
+        const double y_unit = node_coords(i,1) / grid_extent[1] ;
+        const double z_unit = node_coords(i,2) / grid_extent[2] ;
+
+        node_coords(i,0) = coordinate_scalar_type( problem_extent[0] * std::pow( x_unit , x_coord_curve ) );
+        node_coords(i,1) = coordinate_scalar_type( problem_extent[1] * std::pow( y_unit , y_coord_curve ) );
+        node_coords(i,2) = coordinate_scalar_type( problem_extent[2] * std::pow( z_unit , z_coord_curve ) );
+      }
+    }
+
+    Kokkos::deep_copy( mesh.node_coords ,   node_coords );
+    Kokkos::deep_copy( mesh.elem_node_ids , elem_node_ids );
+    Kokkos::deep_copy( mesh.node_elem_ids.entries , node_elem_ids.entries );
+
+    //------------------------------------
+    // Communication lists:
+    {
+      recv_msg_count = 0 ;
+      send_msg_count = 0 ;
+      send_count = 0 ;
+
+      for ( size_t i = 1 ; i < proc_count ; ++i ) {
+
+        // Order sending starting with the local processor rank
+        // to try to smooth out the amount of messages simultaneously
+        // send to a particular processor.
+
+        const int proc = ( proc_local + i ) % proc_count ;
+        if ( node_part_counts[i] ) {
+          mesh.parallel_data_map.host_recv(recv_msg_count,0) = proc ;
+          mesh.parallel_data_map.host_recv(recv_msg_count,1) = node_part_counts[i] ;
+          ++recv_msg_count ;
+        }
+        if ( node_send_map[i].size() ) {
+          mesh.parallel_data_map.host_send(send_msg_count,0) = proc ;
+          mesh.parallel_data_map.host_send(send_msg_count,1) = node_send_map[i].size() ;
+          for ( size_t j = 0 ; j < node_send_map[i].size() ; ++j , ++send_count ) {
+            mesh.parallel_data_map.host_send_item(send_count) = node_send_map[i][j] - node_count_interior ;
+          }
+          ++send_msg_count ;
+        }
+      }
+    }
+
+    return mesh ;
+  }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_BOXMESHFIXTURE_HPP */
+
+
diff --git a/lib/kokkos/example/multi_fem/BoxMeshPartition.cpp b/lib/kokkos/example/multi_fem/BoxMeshPartition.cpp
new file mode 100644
index 0000000000..17a6696fb9
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/BoxMeshPartition.cpp
@@ -0,0 +1,381 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+#include <limits>
+#include <BoxMeshPartition.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace {
+
+void box_partition( size_t ip , size_t up ,
+                    const BoxType & box ,
+                    BoxType * const p_box )
+{
+  const size_t np = up - ip ;
+
+  if ( 1 == np ) {
+    p_box[ip] = box ;
+  }
+  else {
+    // Choose axis with largest count:
+
+    const size_t n0 = box[0][1] - box[0][0] ;
+    const size_t n1 = box[1][1] - box[1][0] ;
+    const size_t n2 = box[2][1] - box[2][0] ;
+
+    const size_t axis = n2 > n1 ? ( n2 > n0 ? 2 : ( n1 > n0 ? 1 : 0 ) ) :
+                                  ( n1 > n0 ? 1 : 0 );
+
+    const size_t n = box[ axis ][1] - box[ axis ][0] ;
+
+    if ( 0 == np % 3 ) {
+      const size_t np_part = np / 3 ; // exact
+
+      const size_t nbox_low = (size_t)(( (double) n ) * ( 1.0 / 3.0 ));
+      const size_t nbox_mid = (size_t)(( (double) n ) * ( 2.0 / 3.0 ));
+
+      BoxType dbox_low = box ; // P = [ip,ip+np/3) 
+      BoxType dbox_mid = box ; // P = [ip+np/3,ip+2*np/3) 
+      BoxType dbox_upp = box ; // P = [ip+2*np/3,ip+np) 
+
+      dbox_low[ axis ][1] = box[ axis ][0] + nbox_low ;
+      dbox_mid[ axis ][1] = box[ axis ][0] + nbox_mid ;
+
+      dbox_mid[ axis ][0] = dbox_low[ axis ][1];
+      dbox_upp[ axis ][0] = dbox_mid[ axis ][1];
+
+      box_partition( ip,           ip +   np_part, dbox_low , p_box );
+      box_partition( ip+  np_part, ip + 2*np_part, dbox_mid , p_box );
+      box_partition( ip+2*np_part, up,             dbox_upp , p_box );
+    }
+    else {
+      const size_t np_low = np / 2 ; /* Rounded down */
+      const size_t nbox_low = (size_t)
+        (((double)n) * ( ((double) np_low ) / ((double) np ) ));
+
+      BoxType dbox_low = box ;
+      BoxType dbox_upp = box ;
+
+      dbox_low[ axis ][1] = dbox_low[ axis ][0] + nbox_low ; 
+      dbox_upp[ axis ][0] = dbox_low[ axis ][1];
+
+      box_partition( ip, ip + np_low, dbox_low , p_box );
+      box_partition( ip + np_low, up, dbox_upp , p_box );
+    }
+  }
+}
+
+size_t box_map_offset( const BoxType & local_use ,
+                       const size_t global_i ,
+                       const size_t global_j ,
+                       const size_t global_k )
+
+{
+  const size_t max = std::numeric_limits<size_t>::max();
+
+  const size_t n[3] =
+    { local_use[0][1] - local_use[0][0] ,
+      local_use[1][1] - local_use[1][0] ,
+      local_use[2][1] - local_use[2][0] };
+
+  const size_t use[3] = {
+    ( global_i >= local_use[0][0] ? global_i - local_use[0][0] : max ) ,
+    ( global_j >= local_use[1][0] ? global_j - local_use[1][0] : max ) ,
+    ( global_k >= local_use[2][0] ? global_k - local_use[2][0] : max ) };
+
+  const size_t offset =
+    ( use[0] < n[0] && use[1] < n[1] && use[2] < n[2] ) ?
+    ( use[0] + n[0] * ( use[1] + n[1] * use[2] ) ) : max ;
+
+  if ( offset == max ) {
+    std::ostringstream msg ;
+    msg << "box_map_offset ERROR: "
+        << " use " << local_use
+        << " ( " << global_i
+        << " , " << global_j
+        << " , " << global_k
+        << " )" ;
+    throw std::runtime_error( msg.str() );
+  }
+
+  return offset ;
+}
+
+} // namespace
+
+//----------------------------------------------------------------------------
+
+void BoxBoundsLinear::apply(  const BoxType & box_global ,
+                              const BoxType & box_part ,
+                                    BoxType & box_interior ,
+                                    BoxType & box_use ) const
+{
+  const unsigned ghost = 1 ;
+
+  if ( 0 == count( box_part ) ) {
+    box_interior = box_part ;
+    box_use      = box_part ;
+  }
+  else {
+    for ( size_t i = 0 ; i < 3 ; ++i ) {
+
+      box_interior[i][0] =
+        ( box_part[i][0] == box_global[i][0] )      ? box_part[i][0] : (
+        ( box_part[i][0] + ghost < box_part[i][1] ) ? box_part[i][0] + ghost : 
+                                                      box_part[i][1] );
+
+      box_interior[i][1] =
+        ( box_part[i][1] == box_global[i][1] )      ? box_part[i][1] : (
+        ( box_part[i][0] + ghost < box_part[i][1] ) ? box_part[i][1] - ghost :
+                                                      box_part[i][0] );
+
+      box_use[i][0] = 
+        ( box_part[i][0] > ghost + box_global[i][0] ) ? box_part[i][0] - ghost :
+                                                        box_global[i][0] ;
+      box_use[i][1] = 
+        ( box_part[i][1] + ghost < box_global[i][1] ) ? box_part[i][1] + ghost :
+                                                        box_global[i][1] ;
+    }
+  }
+}
+
+void BoxBoundsQuadratic::apply( const BoxType & box_global ,
+                                const BoxType & box_part ,
+                                      BoxType & box_interior ,
+                                      BoxType & box_use ) const
+{
+  if ( 0 == count( box_part ) ) {
+    box_interior = box_part ;
+    box_use      = box_part ;
+  }
+  else {
+    for ( size_t i = 0 ; i < 3 ; ++i ) {
+      const bool odd = ( box_part[i][0] - box_global[i][0] ) & 01 ;
+
+      const unsigned ghost = odd ? 1 : 2 ;
+
+      box_interior[i][0] =
+        ( box_part[i][0] == box_global[i][0] )      ? box_part[i][0] : (
+        ( box_part[i][0] + ghost < box_part[i][1] ) ? box_part[i][0] + ghost : 
+                                                      box_part[i][1] );
+
+      box_interior[i][1] =
+        ( box_part[i][1] == box_global[i][1] )      ? box_part[i][1] : (
+        ( box_part[i][0] + ghost < box_part[i][1] ) ? box_part[i][1] - ghost :
+                                                      box_part[i][0] );
+
+      box_use[i][0] = 
+        ( box_part[i][0] > ghost + box_global[i][0] ) ? box_part[i][0] - ghost :
+                                                        box_global[i][0] ;
+      box_use[i][1] = 
+        ( box_part[i][1] + ghost < box_global[i][1] ) ? box_part[i][1] + ghost :
+                                                        box_global[i][1] ;
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+
+void box_partition_rcb( const BoxType        & root_box ,
+                        std::vector<BoxType> & part_boxes )
+{
+  const BoxBoundsLinear use_boxes ;
+
+  const size_t part_count = part_boxes.size();
+
+  box_partition( 0 , part_count , root_box , & part_boxes[0] );
+
+  // Verify partitioning
+
+  size_t total_cell = 0 ;
+
+  for ( size_t i = 0 ; i < part_count ; ++i ) {
+
+    total_cell += count( part_boxes[i] );
+
+    BoxType box_interior , box_use ;
+
+    use_boxes.apply( root_box , part_boxes[i] , box_interior , box_use );
+
+    if ( count( box_use ) < count( part_boxes[i] ) ||
+         count( part_boxes[i] ) < count( box_interior ) ||
+         part_boxes[i] != intersect( part_boxes[i] , box_use ) ||
+         box_interior  != intersect( part_boxes[i] , box_interior )) {
+
+      std::ostringstream msg ;
+
+      msg << "box_partition_rcb ERROR : "
+          << "part_boxes[" << i << "] = "
+          << part_boxes[i]
+          << " use " << box_use
+          << " interior " << box_interior
+          << std::endl 
+          << "  part ^ use " << intersect( part_boxes[i] , box_use )
+          << "  part ^ interior " << intersect( part_boxes[i] , box_interior );
+
+      throw std::runtime_error( msg.str() );
+    }
+
+    for ( size_t j = i + 1 ; j < part_count ; ++j ) {
+      const BoxType tmp = intersect( part_boxes[i] , part_boxes[j] );
+
+      if ( count( tmp ) ) {
+        throw std::runtime_error( std::string("box partition intersection") );
+      }
+    }
+  }
+
+  if ( total_cell != count( root_box ) ) {
+    throw std::runtime_error( std::string("box partition count") );
+  }
+}
+
+//----------------------------------------------------------------------------
+         
+size_t box_map_id( const BoxType & local_use ,
+                   const std::vector<size_t> & local_use_id_map ,
+                   const size_t global_i ,
+                   const size_t global_j ,
+                   const size_t global_k )
+
+{
+  const size_t offset =
+    box_map_offset( local_use , global_i , global_j , global_k );
+  return local_use_id_map[ offset ];
+}
+         
+//----------------------------------------------------------------------------
+
+void box_partition_maps( const BoxType              & root_box ,
+                         const std::vector<BoxType> & part_boxes ,
+                         const BoxBounds            & use_boxes ,
+                         const size_t          my_part ,
+                         BoxType             & my_use_box ,
+                         std::vector<size_t> & my_use_id_map ,
+                         size_t              & my_count_interior ,
+                         size_t              & my_count_owned ,
+                         size_t              & my_count_uses ,
+                         std::vector<size_t> & my_part_counts ,
+                         std::vector<std::vector<size_t> > & my_send_map )
+{
+  const size_t np = part_boxes.size();
+
+  if ( np <= my_part ) {
+    std::ostringstream msg ;
+    msg << "box_partition_maps ERROR : "
+        << " np(" << np << ") <= my_part(" << my_part << ")" ;
+    throw std::runtime_error( msg.str() );
+  }
+
+  const BoxType my_owned_box = part_boxes[my_part];
+  BoxType my_interior_box ;
+
+
+  use_boxes.apply( root_box, my_owned_box, my_interior_box, my_use_box );
+
+  my_count_interior = count( my_interior_box );
+  my_count_owned    = count( my_owned_box );
+  my_count_uses     = count( my_use_box );
+
+  my_use_id_map.assign( my_count_uses , std::numeric_limits<size_t>::max() );
+
+  // Order ids as { owned-interior , owned-parallel , received_{(p+i)%np} }
+
+  size_t offset_interior = 0 ;
+  size_t offset_parallel = my_count_interior ;
+
+  for ( size_t iz = my_owned_box[2][0] ; iz < my_owned_box[2][1] ; ++iz ) {
+  for ( size_t iy = my_owned_box[1][0] ; iy < my_owned_box[1][1] ; ++iy ) {
+  for ( size_t ix = my_owned_box[0][0] ; ix < my_owned_box[0][1] ; ++ix ) {
+    const size_t offset = box_map_offset( my_use_box , ix , iy , iz );
+    if ( contain( my_interior_box , ix , iy , iz ) ) {
+      my_use_id_map[ offset ] = offset_interior++ ;
+    }
+    else {
+      my_use_id_map[ offset ] = offset_parallel++ ;
+    }
+  }}}
+
+
+  my_part_counts.assign( np , (size_t) 0 );
+  my_send_map.assign( np , std::vector<size_t>() );
+
+  my_part_counts[0] = my_count_owned ;
+
+  for ( size_t i = 1 ; i < np ; ++i ) {
+
+    const size_t ip = ( my_part + i ) % np ;
+
+    const BoxType p_owned_box = part_boxes[ip];
+    BoxType p_use_box , p_interior_box ;
+    use_boxes.apply( root_box, p_owned_box, p_interior_box, p_use_box );
+
+    const BoxType recv_box = intersect( my_use_box , p_owned_box );
+    const BoxType send_box = intersect( my_owned_box , p_use_box );
+
+    if ( 0 != ( my_part_counts[i] = count( recv_box ) ) ) {
+      for ( size_t iz = recv_box[2][0] ; iz < recv_box[2][1] ; ++iz ) {
+      for ( size_t iy = recv_box[1][0] ; iy < recv_box[1][1] ; ++iy ) {
+      for ( size_t ix = recv_box[0][0] ; ix < recv_box[0][1] ; ++ix ) {
+        const size_t offset = box_map_offset( my_use_box , ix , iy , iz );
+        my_use_id_map[ offset ] = offset_parallel++ ;
+      }}}
+    }
+
+    if ( 0 != count( send_box ) ) {
+      for ( size_t iz = send_box[2][0] ; iz < send_box[2][1] ; ++iz ) {
+      for ( size_t iy = send_box[1][0] ; iy < send_box[1][1] ; ++iy ) {
+      for ( size_t ix = send_box[0][0] ; ix < send_box[0][1] ; ++ix ) {
+        const size_t offset = box_map_offset( my_use_box , ix , iy , iz );
+
+        my_send_map[ i ].push_back( my_use_id_map[ offset ] );
+      }}}
+    }
+  }
+}
+
+
diff --git a/lib/kokkos/example/multi_fem/BoxMeshPartition.hpp b/lib/kokkos/example/multi_fem/BoxMeshPartition.hpp
new file mode 100644
index 0000000000..f2aa6f57cc
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/BoxMeshPartition.hpp
@@ -0,0 +1,210 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef BOXMESHPARTITION_HPP
+#define BOXMESHPARTITION_HPP
+
+#include <cstddef>
+#include <utility>
+#include <vector>
+#include <iostream>
+
+//----------------------------------------------------------------------------
+
+struct BoxType {
+  size_t data[3][2] ;
+
+  typedef size_t range_type[2] ;
+
+  inline
+  const range_type & operator[]( size_t i ) const { return data[i]; }
+
+  inline
+  range_type & operator[]( size_t i ) { return data[i]; }
+
+  inline
+  bool operator == ( const BoxType & rhs ) const
+  {
+    return data[0][0] == rhs.data[0][0] && data[0][1] == rhs.data[0][1] &&
+           data[1][0] == rhs.data[1][0] && data[1][1] == rhs.data[2][1] &&
+           data[2][0] == rhs.data[2][0] && data[2][1] == rhs.data[2][1] ;
+  }
+
+  inline
+  bool operator != ( const BoxType & rhs ) const
+  {
+    return data[0][0] != rhs.data[0][0] || data[0][1] != rhs.data[0][1] ||
+           data[1][0] != rhs.data[1][0] || data[1][1] != rhs.data[1][1] ||
+           data[2][0] != rhs.data[2][0] || data[2][1] != rhs.data[2][1] ;
+  }
+};
+
+inline
+size_t count( const BoxType & b )
+{
+  size_t n = 1 ;
+  for ( size_t i = 0 ; i < 3 ; ++i ) {
+    n *= b[i][1] > b[i][0] ? b[i][1] - b[i][0] : 0 ;
+  }
+  return n ;
+}
+
+inline
+bool contain( const BoxType & b , size_t i , size_t j , size_t k )
+{
+  return b[0][0] <= i && i < b[0][1] &&
+         b[1][0] <= j && j < b[1][1] &&
+         b[2][0] <= k && k < b[2][1] ;
+}
+
+inline
+BoxType intersect( const BoxType & x , const BoxType & y )
+{
+  BoxType z ;
+  for ( size_t i = 0 ; i < 3 ; ++i ) {
+    z[i][0] = std::max( x[i][0] , y[i][0] );    
+    z[i][1] = std::min( x[i][1] , y[i][1] );    
+  }
+
+  return z ;
+}
+
+inline
+std::ostream & operator << ( std::ostream & s , const BoxType & box )
+{
+  s << "{ "
+    << box[0][0] << " " << box[0][1] << " , "
+    << box[1][0] << " " << box[1][1] << " , "
+    << box[2][0] << " " << box[2][1] << " }" ;
+  return s ;
+}
+
+//----------------------------------------------------------------------------
+
+class BoxBounds {
+public:
+  /** \brief  Default bounds to one layer of ghosting */
+  virtual
+  void apply( const BoxType & box_global ,
+              const BoxType & box_part ,
+                    BoxType & box_interior ,
+                    BoxType & box_use ) const = 0 ;
+
+  virtual ~BoxBounds() {}
+  BoxBounds() {}
+};
+
+class BoxBoundsLinear : public BoxBounds
+{
+public:
+  /** \brief  Default bounds to one layer of ghosting */
+  virtual
+  void apply( const BoxType & box_global ,
+              const BoxType & box_part ,
+                    BoxType & box_interior ,
+                    BoxType & box_use ) const ;
+
+  virtual ~BoxBoundsLinear() {}
+  BoxBoundsLinear() {}
+};
+
+class BoxBoundsQuadratic : public BoxBounds {
+public:
+  /** \brief  Quadratic mesh: even ordinates have two layers,
+   *          odd ordinates have one layer.
+   */
+  virtual
+  void apply( const BoxType & box_global ,
+              const BoxType & box_part ,
+                    BoxType & box_interior ,
+                    BoxType & box_use ) const ;
+
+  virtual ~BoxBoundsQuadratic() {}
+  BoxBoundsQuadratic() {}
+};
+
+//----------------------------------------------------------------------------
+/* Partition box into part_boxes.size() sub-boxes */
+
+void box_partition_rcb( const BoxType        & root_box ,
+                        std::vector<BoxType> & part_boxes );
+
+//----------------------------------------------------------------------------
+/* Determine local id layout and communication maps for partitioned boxes.
+ *
+ *  Local ids are layed out as follows:
+ *    { [ owned-interior ids not sent ] ,
+ *      [ owned-boundary ids to be sent to other processes ] ,
+ *      [ received ids from processor ( my_part + 1 ) % part_count ]
+ *      [ received ids from processor ( my_part + 2 ) % part_count ]
+ *      [ received ids from processor ( my_part + 3 ) % part_count ]
+ *      ... };
+ *
+ *  This layout allows
+ *  (1) received data to be copied into a contiguous block of memory
+ *  (2) send data to be extracted from a contiguous block of memory.
+ */
+void box_partition_maps(
+  const BoxType              & root_box ,   // [in] Global box
+  const std::vector<BoxType> & part_boxes , // [in] Partitioned boxes
+  const BoxBounds            & use_boxes ,  // [in] Ghost boundaries
+  const size_t          my_part ,           // [in] My local part
+  BoxType             & my_use_box ,        // [out] My used box with ghost
+  std::vector<size_t> & my_use_id_map ,     // [out] Local ordering map
+  size_t              & my_count_interior , // [out] How many interior
+  size_t              & my_count_owned ,    // [out] How many owned
+  size_t              & my_count_uses ,     // [out] How may used
+  std::vector<size_t> & my_part_counts ,    // [out] Partitioning of my_use_id_map
+  std::vector<std::vector<size_t> > & my_send_map ); // [out] Send id map
+
+/*  Mapping of cartesian coordinate to local id */
+size_t box_map_id( const BoxType             & my_use_box ,
+                   const std::vector<size_t> & my_use_id_map ,
+                   const size_t global_i ,
+                   const size_t global_j ,
+                   const size_t global_k );
+
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef BOXMESHPARTITION_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/CMakeLists.txt b/lib/kokkos/example/multi_fem/CMakeLists.txt
new file mode 100644
index 0000000000..e3a40bc26f
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/CMakeLists.txt
@@ -0,0 +1,16 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(SOURCES "")
+
+FILE(GLOB SOURCES *.cpp)
+
+SET(LIBRARIES kokkoscore)
+
+TRIBITS_ADD_EXECUTABLE(
+  multi_fem
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  )
+
diff --git a/lib/kokkos/example/multi_fem/Explicit.hpp b/lib/kokkos/example/multi_fem/Explicit.hpp
new file mode 100644
index 0000000000..cef1a37a1a
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/Explicit.hpp
@@ -0,0 +1,452 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef EXPLICIT_DRIVER_HPP
+#define EXPLICIT_DRIVER_HPP
+
+#include <sys/time.h>
+#include <iostream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+
+#include <impl/Kokkos_Timer.hpp>
+
+#include <ExplicitFunctors.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace Explicit {
+
+struct PerformanceData {
+  double mesh_time ;
+  double init_time ;
+  double internal_force_time ;
+  double central_diff ;
+  double comm_time ;
+  size_t number_of_steps ;
+
+  PerformanceData()
+  : mesh_time(0)
+  , init_time(0)
+  , internal_force_time(0)
+  , central_diff(0)
+  , comm_time(0)
+  , number_of_steps(0)
+  {}
+
+  void best( const PerformanceData & rhs )
+  {
+    if ( rhs.mesh_time < mesh_time ) mesh_time = rhs.mesh_time ;
+    if ( rhs.init_time < init_time ) init_time = rhs.init_time ;
+    if ( rhs.internal_force_time < internal_force_time ) internal_force_time = rhs.internal_force_time ;
+    if ( rhs.central_diff < central_diff ) central_diff = rhs.central_diff ;
+    if ( rhs.comm_time < comm_time ) comm_time = rhs.comm_time ;
+  }
+};
+
+template< typename Scalar , class FixtureType >
+PerformanceData run( const typename FixtureType::FEMeshType & mesh ,
+                     const int global_max_x ,
+                     const int global_max_y ,
+                     const int global_max_z ,
+                     const int steps ,
+                     const int print_sample )
+{
+  typedef Scalar                              scalar_type ;
+  typedef FixtureType                         fixture_type ;
+  typedef typename fixture_type::execution_space  execution_space ;
+  //typedef typename fixture_type::FEMeshType   mesh_type ; // unused
+
+  enum { ElementNodeCount = fixture_type::element_node_count };
+
+  const int NumStates = 2;
+
+  const int total_num_steps = steps ;
+
+  const Scalar user_dt = 5.0e-6;
+  //const Scalar  end_time = 0.0050;
+
+  // element block parameters
+  const Scalar  lin_bulk_visc = 0.0;
+  const Scalar  quad_bulk_visc = 0.0;
+
+  // const Scalar  lin_bulk_visc = 0.06;
+  // const Scalar  quad_bulk_visc = 1.2;
+  // const Scalar  hg_stiffness = 0.0;
+  // const Scalar  hg_viscosity = 0.0;
+  // const Scalar  hg_stiffness = 0.03;
+  // const Scalar  hg_viscosity = 0.001;
+
+  // material properties
+  const Scalar youngs_modulus=1.0e6;
+  const Scalar poissons_ratio=0.0;
+  const Scalar  density = 8.0e-4;
+
+  const comm::Machine machine = mesh.parallel_data_map.machine ;
+
+  PerformanceData perf_data ;
+
+  Kokkos::Timer wall_clock ;
+
+  //------------------------------------
+  // Generate fields
+
+  typedef Fields< scalar_type , execution_space > fields_type ;
+
+  fields_type mesh_fields( mesh ,
+                           lin_bulk_visc ,
+                           quad_bulk_visc ,
+                           youngs_modulus ,
+                           poissons_ratio ,
+                           density );
+
+  typename fields_type::node_coords_type::HostMirror
+    model_coords_h = Kokkos::create_mirror( mesh_fields.model_coords );
+
+  typename fields_type::geom_state_array_type::HostMirror
+    displacement_h = Kokkos::create_mirror( mesh_fields.displacement );
+
+  typename fields_type::geom_state_array_type::HostMirror
+    velocity_h = Kokkos::create_mirror( mesh_fields.velocity );
+
+  Kokkos::deep_copy( model_coords_h , mesh_fields.model_coords );
+
+  //------------------------------------
+  // Initialization
+
+  initialize_element<Scalar,execution_space>::apply( mesh_fields );
+  initialize_node<   Scalar,execution_space>::apply( mesh_fields );
+
+  const Scalar x_bc = global_max_x ;
+
+  // Initial condition on velocity to initiate a pulse along the X axis
+  {
+    const unsigned X = 0;
+    for (int inode = 0; inode< mesh_fields.num_nodes; ++inode) {
+      if ( model_coords_h(inode,X) == 0) {
+        velocity_h(inode,X,0) = 1.0e3;
+        velocity_h(inode,X,1) = 1.0e3;
+      }
+    }
+  }
+
+  Kokkos::deep_copy( mesh_fields.velocity , velocity_h );
+
+  //--------------------------------------------------------------------------
+  // We will call a sequence of functions.  These functions have been
+  // grouped into several functors to balance the number of global memory
+  // accesses versus requiring too many registers or too much L1 cache.
+  // Global memory accees have read/write cost and memory subsystem contention cost.
+  //--------------------------------------------------------------------------
+
+  perf_data.init_time = comm::max( machine , wall_clock.seconds() );
+
+  // Parameters required for the internal force computations.
+
+  int current_state = 0;
+  int previous_state = 0;
+  int next_state = 0;
+
+  perf_data.number_of_steps = total_num_steps ;
+
+#if defined( KOKKOS_HAVE_MPI )
+
+  typedef typename
+    fields_type::geom_state_array_type::value_type  comm_value_type ;
+
+  const unsigned comm_value_count = 6 ;
+
+  Kokkos::AsyncExchange< comm_value_type , execution_space ,
+                              Kokkos::ParallelDataMap >
+    comm_exchange( mesh.parallel_data_map , comm_value_count );
+
+#endif
+
+  for (int step = 0; step < total_num_steps; ++step) {
+
+    wall_clock.reset();
+
+    //------------------------------------------------------------------------
+#if defined( KOKKOS_HAVE_MPI )
+    {
+      // Communicate "send" nodes' displacement and velocity next_state
+      // to the ghosted nodes.
+      // buffer packages: { { dx , dy , dz , vx , vy , vz }_node }
+
+      pack_state< Scalar , execution_space >
+        ::apply( comm_exchange.buffer() ,
+                 mesh.parallel_data_map.count_interior ,
+                 mesh.parallel_data_map.count_send ,
+                 mesh_fields , next_state );
+
+      comm_exchange.setup();
+
+      comm_exchange.send_receive();
+
+      unpack_state< Scalar , execution_space >
+        ::apply( mesh_fields , next_state ,
+                 comm_exchange.buffer() ,
+                 mesh.parallel_data_map.count_owned ,
+                 mesh.parallel_data_map.count_receive );
+
+      execution_space::fence();
+    }
+#endif
+
+    perf_data.comm_time += comm::max( machine , wall_clock.seconds() );
+
+    //------------------------------------------------------------------------
+    // rotate the states
+
+    previous_state = current_state;
+    current_state = next_state;
+    ++next_state;
+    next_state %= NumStates;
+
+    wall_clock.reset();
+
+    // First kernel 'grad_hgop' combines two functions:
+    // gradient, velocity gradient
+    grad< Scalar , execution_space >::apply( mesh_fields ,
+                                         current_state ,
+                                         previous_state );
+
+    // Combine tensor decomposition and rotation functions.
+    decomp_rotate< Scalar , execution_space >::apply( mesh_fields ,
+                                                  current_state ,
+                                                  previous_state );
+
+    internal_force< Scalar , execution_space >::apply( mesh_fields ,
+                                                   user_dt ,
+                                                   current_state );
+
+    execution_space::fence();
+
+    perf_data.internal_force_time +=
+      comm::max( machine , wall_clock.seconds() );
+
+    wall_clock.reset();
+
+    // Assembly of elements' contributions to nodal force into
+    // a nodal force vector.  Update the accelerations, velocities,
+    // displacements.
+    // The same pattern can be used for matrix-free residual computations.
+    nodal_step< Scalar , execution_space >::apply( mesh_fields ,
+                                               x_bc ,
+                                               current_state,
+                                               next_state );
+    execution_space::fence();
+
+    perf_data.central_diff +=
+      comm::max( machine , wall_clock.seconds() );
+
+    if ( print_sample && 0 == step % 100 ) {
+      Kokkos::deep_copy( displacement_h , mesh_fields.displacement );
+      Kokkos::deep_copy( velocity_h ,     mesh_fields.velocity );
+
+      if ( 1 == print_sample ) {
+
+        std::cout << "step " << step
+                  << " : displacement(*,0,0) =" ;
+        for ( int i = 0 ; i < mesh_fields.num_nodes_owned ; ++i ) {
+          if ( model_coords_h(i,1) == 0 && model_coords_h(i,2) == 0 ) {
+            std::cout << " " << displacement_h(i,0,next_state);
+          }
+        }
+        std::cout << std::endl ;
+
+        const float tol = 1.0e-6 ;
+        const int yb = global_max_y ;
+        const int zb = global_max_z ;
+        std::cout << "step " << step
+                  << " : displacement(*," << yb << "," << zb << ") =" ;
+        for ( int i = 0 ; i < mesh_fields.num_nodes_owned ; ++i ) {
+          if ( fabs( model_coords_h(i,1) - yb ) < tol &&
+               fabs( model_coords_h(i,2) - zb ) < tol ) {
+            std::cout << " " << displacement_h(i,0,next_state);
+          }
+        }
+        std::cout << std::endl ;
+      }
+      else if ( 2 == print_sample ) {
+
+        const float tol = 1.0e-6 ;
+        const int xb = global_max_x / 2 ;
+        const int yb = global_max_y / 2 ;
+        const int zb = global_max_z / 2 ;
+
+        for ( int i = 0 ; i < mesh_fields.num_nodes_owned ; ++i ) {
+          if ( fabs( model_coords_h(i,0) - xb ) < tol &&
+               fabs( model_coords_h(i,1) - yb ) < tol &&
+               fabs( model_coords_h(i,2) - zb ) < tol ) {
+            std::cout << "step " << step
+                      << " : displacement("
+                      << xb << "," << yb << "," << zb << ") = {"
+                      << std::setprecision(6)
+                      << " " << displacement_h(i,0,next_state)
+                      << std::setprecision(2)
+                      << " " << displacement_h(i,1,next_state)
+                      << std::setprecision(2)
+                      << " " << displacement_h(i,2,next_state)
+                      << " }" << std::endl ;
+          }
+        }
+      }
+    }
+  }
+
+  return perf_data ;
+}
+
+
+template <typename Scalar, typename Device>
+static void driver( const char * const label ,
+                    comm::Machine machine ,
+                    const int gang_count ,
+                    const int elem_count_beg ,
+                    const int elem_count_end ,
+                    const int runs )
+{
+  typedef Scalar              scalar_type ;
+  typedef Device              execution_space ;
+  typedef double              coordinate_scalar_type ;
+  typedef FixtureElementHex8  fixture_element_type ;
+
+  typedef BoxMeshFixture< coordinate_scalar_type ,
+                          execution_space ,
+                          fixture_element_type > fixture_type ;
+
+  typedef typename fixture_type::FEMeshType mesh_type ;
+
+  const size_t proc_count = comm::size( machine );
+  const size_t proc_rank  = comm::rank( machine );
+
+  const int space = 15 ;
+  const int steps = 1000 ;
+  const int print_sample = 0 ;
+
+  if ( comm::rank( machine ) == 0 ) {
+
+    std::cout << std::endl ;
+    std::cout << "\"MiniExplicitDynamics with Kokkos " << label
+              << " time_steps(" << steps << ")"
+              << "\"" << std::endl;
+    std::cout << std::left << std::setw(space) << "\"Element\" , ";
+    std::cout << std::left << std::setw(space) << "\"Node\" , ";
+    std::cout << std::left << std::setw(space) << "\"Initialize\" , ";
+    std::cout << std::left << std::setw(space) << "\"ElemForce\" , ";
+    std::cout << std::left << std::setw(space) << "\"NodeUpdate\" , ";
+    std::cout << std::left << std::setw(space) << "\"NodeComm\" , ";
+    std::cout << std::left << std::setw(space) << "\"Time/Elem\" , ";
+    std::cout << std::left << std::setw(space) << "\"Time/Node\"";
+
+    std::cout << std::endl;
+
+    std::cout << std::left << std::setw(space) << "\"count\" , ";
+    std::cout << std::left << std::setw(space) << "\"count\" , ";
+    std::cout << std::left << std::setw(space) << "\"microsec\" , ";
+    std::cout << std::left << std::setw(space) << "\"microsec\" , ";
+    std::cout << std::left << std::setw(space) << "\"microsec\" , ";
+    std::cout << std::left << std::setw(space) << "\"microsec\" , ";
+    std::cout << std::left << std::setw(space) << "\"microsec\" , ";
+    std::cout << std::left << std::setw(space) << "\"microsec\"";
+
+    std::cout << std::endl;
+  }
+
+  for(int i = elem_count_beg ; i < elem_count_end ; i *= 2 )
+  {
+    const int iz = std::max( 1 , (int) cbrt( ((double) i) / 2.0 ) );
+    const int iy = iz + 1 ;
+    const int ix = 2 * iy ;
+    const int nelem = ix * iy * iz ;
+    const int nnode = ( ix + 1 ) * ( iy + 1 ) * ( iz + 1 );
+
+    mesh_type mesh =
+      fixture_type::create( proc_count , proc_rank , gang_count ,
+                            ix , iy , iz );
+
+    mesh.parallel_data_map.machine = machine ;
+
+    PerformanceData perf , best ;
+
+    for(int j = 0; j < runs; j++){
+
+     perf = run<scalar_type,fixture_type>(mesh,ix,iy,iz,steps,print_sample);
+
+     if( j == 0 ) {
+       best = perf ;
+     }
+     else {
+       best.best( perf );
+     }
+   }
+
+   if ( comm::rank( machine ) == 0 ) {
+     double time_per_element =
+       ( best.internal_force_time ) / ( nelem * perf.number_of_steps );
+     double time_per_node =
+       ( best.comm_time + best.central_diff ) / ( nnode * perf.number_of_steps );
+
+   std::cout << std::setw(space-3) << nelem << " , "
+             << std::setw(space-3) << nnode << " , "
+             << std::setw(space-3) << best.number_of_steps << " , "
+             << std::setw(space-3) << best.init_time * 1000000 << " , "
+             << std::setw(space-3)
+             << ( best.internal_force_time * 1000000 ) / best.number_of_steps << " , "
+             << std::setw(space-3)
+             << ( best.central_diff * 1000000 ) / best.number_of_steps << " , "
+             << std::setw(space-3)
+             << ( best.comm_time * 1000000 ) / best.number_of_steps << " , "
+             << std::setw(space-3) << time_per_element * 1000000 << " , "
+             << std::setw(space-3) << time_per_node * 1000000
+             << std::endl ;
+    }
+  }
+}
+
+
+} // namespace Explicit
+
+#endif /* #ifndef EXPLICIT_DRIVER_HPP */
diff --git a/lib/kokkos/example/multi_fem/ExplicitFunctors.hpp b/lib/kokkos/example/multi_fem/ExplicitFunctors.hpp
new file mode 100644
index 0000000000..feea82244f
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/ExplicitFunctors.hpp
@@ -0,0 +1,1471 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_EXPLICITFUNCTORS_HPP
+#define KOKKOS_EXPLICITFUNCTORS_HPP
+
+#include <math.h>
+#include <Kokkos_Core.hpp>
+#include <FEMesh.hpp>
+
+namespace Explicit {
+
+template<typename Scalar , class Device >
+struct Fields {
+
+  static const int NumStates     = 2 ;
+  static const int SpatialDim    = 3 ;
+  static const int ElemNodeCount = 8 ;
+
+  // Indices for full 3x3 tensor:
+
+  static const int K_F_XX = 0 ;
+  static const int K_F_YY = 1 ;
+  static const int K_F_ZZ = 2 ;
+  static const int K_F_XY = 3 ;
+  static const int K_F_YZ = 4 ;
+  static const int K_F_ZX = 5 ;
+  static const int K_F_YX = 6 ;
+  static const int K_F_ZY = 7 ;
+  static const int K_F_XZ = 8 ;
+
+  //  Indexes into a 3 by 3 symmetric tensor stored as a length 6 vector
+
+  static const int K_S_XX = 0 ;
+  static const int K_S_YY = 1 ;
+  static const int K_S_ZZ = 2 ;
+  static const int K_S_XY = 3 ;
+  static const int K_S_YZ = 4 ;
+  static const int K_S_ZX = 5 ;
+  static const int K_S_YX = 3 ;
+  static const int K_S_ZY = 4 ;
+  static const int K_S_XZ = 5 ;
+
+  //  Indexes into a 3 by 3 skew symmetric tensor stored as a length 3 vector
+
+  static const int K_V_XY = 0 ;
+  static const int K_V_YZ = 1 ;
+  static const int K_V_ZX = 2 ;
+
+
+  typedef Device                           execution_space ;
+  typedef typename execution_space::size_type  size_type ;
+
+  typedef HybridFEM::FEMesh<double,ElemNodeCount,execution_space>  FEMesh ;
+
+  typedef typename FEMesh::node_coords_type    node_coords_type ;
+  typedef typename FEMesh::elem_node_ids_type  elem_node_ids_type ;
+  typedef typename FEMesh::node_elem_ids_type  node_elem_ids_type ;
+  typedef typename Kokkos::ParallelDataMap   parallel_data_map ;
+
+  typedef Kokkos::View< double[][ SpatialDim ][ NumStates ] , execution_space > geom_state_array_type ;
+  typedef Kokkos::View< Scalar[][ SpatialDim ] , execution_space > geom_array_type ;
+  typedef Kokkos::View< Scalar[] ,               execution_space > array_type ;
+  typedef Kokkos::View< Scalar ,                 execution_space >  scalar_type ;
+
+  typedef Kokkos::View< Scalar[][  6 ] ,    execution_space >  elem_sym_tensor_type ;
+  typedef Kokkos::View< Scalar[][  9 ] ,    execution_space >  elem_tensor_type ;
+  typedef Kokkos::View< Scalar[][  9 ][ NumStates ] , execution_space >  elem_tensor_state_type ;
+  typedef Kokkos::View< Scalar[][ SpatialDim ][ ElemNodeCount ] , execution_space > elem_node_geom_type ;
+
+  // Parameters:
+  const int num_nodes ;
+  const int num_nodes_owned ;
+  const int num_elements ;
+
+  const Scalar  lin_bulk_visc;
+  const Scalar  quad_bulk_visc;
+  const Scalar  two_mu;
+  const Scalar  bulk_modulus;
+  const Scalar  density;
+
+  // Mesh:
+  const elem_node_ids_type  elem_node_connectivity ;
+  const node_elem_ids_type  node_elem_connectivity ;
+  const node_coords_type    model_coords ;
+
+  // Compute:
+  const scalar_type                dt ;
+  const scalar_type                prev_dt ;
+  const geom_state_array_type      displacement ;
+  const geom_state_array_type      velocity ;
+  const geom_array_type            acceleration ;
+  const geom_array_type            internal_force ;
+  const array_type                 nodal_mass ;
+  const array_type                 elem_mass ;
+  const array_type                 internal_energy ;
+  const elem_sym_tensor_type       stress_new ;
+  const elem_tensor_state_type     rotation ;
+  const elem_node_geom_type        element_force ;
+  const elem_tensor_type           vel_grad ;
+  const elem_sym_tensor_type       stretch ;
+  const elem_sym_tensor_type       rot_stretch ;
+
+  Fields(
+      const FEMesh & mesh,
+      Scalar arg_lin_bulk_visc,
+      Scalar arg_quad_bulk_visc,
+      Scalar youngs_modulus,
+      Scalar poissons_ratio,
+      Scalar arg_density )
+    : num_nodes(       mesh.parallel_data_map.count_owned +
+                       mesh.parallel_data_map.count_receive )
+    , num_nodes_owned( mesh.parallel_data_map.count_owned )
+    , num_elements(    mesh.elem_node_ids.dimension_0() )
+    , lin_bulk_visc(  arg_lin_bulk_visc )
+    , quad_bulk_visc( arg_quad_bulk_visc )
+    , two_mu(youngs_modulus/(1.0+poissons_ratio))
+    , bulk_modulus(youngs_modulus/(3*(1.0-2.0*poissons_ratio)))
+    , density(arg_density)
+
+    // mesh
+
+    , elem_node_connectivity( mesh.elem_node_ids ) // ( num_elements , ElemNodeCount )
+    , node_elem_connectivity( mesh.node_elem_ids ) // ( num_nodes , ... )
+    , model_coords(  mesh.node_coords )            // ( num_nodes , 3 )
+
+    // compute with input/output
+
+    , dt(              "dt" )
+    , prev_dt(         "prev_dt" )
+    , displacement(    "displacement" ,   num_nodes )
+    , velocity(        "velocity" ,       num_nodes )
+    , acceleration(    "acceleration" ,   num_nodes_owned )
+    , internal_force(  "internal_force" , num_nodes_owned )
+    , nodal_mass(      "nodal_mass" ,     num_nodes_owned )
+    , elem_mass(       "elem_mass" ,       num_elements )
+    , internal_energy( "internal_energy" , num_elements )
+    , stress_new(      "stress_new" ,      num_elements )
+
+    // temporary arrays
+
+    , rotation(      "rotation" ,  num_elements )
+    , element_force( "element_force" ,  num_elements )
+    , vel_grad(      "vel_grad" , num_elements )
+    , stretch(       "stretch" , num_elements )
+    , rot_stretch(   "rot_stretch" , num_elements )
+  { }
+};
+
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class DeviceType >
+KOKKOS_INLINE_FUNCTION
+Scalar dot8( const Scalar * a , const Scalar * b )
+{ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] +
+         a[4] * b[4] + a[5] * b[5] + a[6] * b[6] + a[7] * b[7] ; }
+
+template< typename Scalar , class DeviceType >
+KOKKOS_INLINE_FUNCTION
+void comp_grad( const Scalar * const x ,
+                const Scalar * const y ,
+                const Scalar * const z,
+                Scalar * const grad_x ,
+                Scalar * const grad_y ,
+                Scalar * const grad_z )
+{
+  //  calc X difference vectors
+
+  Scalar R42=(x[3] - x[1]);
+  Scalar R52=(x[4] - x[1]);
+  Scalar R54=(x[4] - x[3]);
+
+  Scalar R63=(x[5] - x[2]);
+  Scalar R83=(x[7] - x[2]);
+  Scalar R86=(x[7] - x[5]);
+
+  Scalar R31=(x[2] - x[0]);
+  Scalar R61=(x[5] - x[0]);
+  Scalar R74=(x[6] - x[3]);
+
+  Scalar R72=(x[6] - x[1]);
+  Scalar R75=(x[6] - x[4]);
+  Scalar R81=(x[7] - x[0]);
+
+  Scalar t1=(R63 + R54);
+  Scalar t2=(R61 + R74);
+  Scalar t3=(R72 + R81);
+
+  Scalar t4 =(R86 + R42);
+  Scalar t5 =(R83 + R52);
+  Scalar t6 =(R75 + R31);
+
+  //  Calculate Y gradient from X and Z data
+
+  grad_y[0] = (z[1] *  t1) - (z[2] * R42) - (z[3] *  t5)  + (z[4] *  t4) + (z[5] * R52) - (z[7] * R54);
+  grad_y[1] = (z[2] *  t2) + (z[3] * R31) - (z[0] *  t1)  - (z[5] *  t6) + (z[6] * R63) - (z[4] * R61);
+  grad_y[2] = (z[3] *  t3) + (z[0] * R42) - (z[1] *  t2)  - (z[6] *  t4) + (z[7] * R74) - (z[5] * R72);
+  grad_y[3] = (z[0] *  t5) - (z[1] * R31) - (z[2] *  t3)  + (z[7] *  t6) + (z[4] * R81) - (z[6] * R83);
+  grad_y[4] = (z[5] *  t3) + (z[6] * R86) - (z[7] *  t2)  - (z[0] *  t4) - (z[3] * R81) + (z[1] * R61);
+  grad_y[5] = (z[6] *  t5) - (z[4] *  t3)  - (z[7] * R75) + (z[1] *  t6) - (z[0] * R52) + (z[2] * R72);
+  grad_y[6] = (z[7] *  t1) - (z[5] *  t5)  - (z[4] * R86) + (z[2] *  t4) - (z[1] * R63) + (z[3] * R83);
+  grad_y[7] = (z[4] *  t2) - (z[6] *  t1)  + (z[5] * R75) - (z[3] *  t6) - (z[2] * R74) + (z[0] * R54);
+
+  //   calc Z difference vectors
+
+  R42=(z[3] - z[1]);
+  R52=(z[4] - z[1]);
+  R54=(z[4] - z[3]);
+
+  R63=(z[5] - z[2]);
+  R83=(z[7] - z[2]);
+  R86=(z[7] - z[5]);
+
+  R31=(z[2] - z[0]);
+  R61=(z[5] - z[0]);
+  R74=(z[6] - z[3]);
+
+  R72=(z[6] - z[1]);
+  R75=(z[6] - z[4]);
+  R81=(z[7] - z[0]);
+
+  t1=(R63 + R54);
+  t2=(R61 + R74);
+  t3=(R72 + R81);
+
+  t4 =(R86 + R42);
+  t5 =(R83 + R52);
+  t6 =(R75 + R31);
+
+  //  Calculate X gradient from Y and Z data
+
+  grad_x[0] = (y[1] *  t1) - (y[2] * R42) - (y[3] *  t5) + (y[4] *  t4) + (y[5] * R52) - (y[7] * R54);
+  grad_x[1] = (y[2] *  t2) + (y[3] * R31) - (y[0] *  t1) - (y[5] *  t6) + (y[6] * R63) - (y[4] * R61);
+  grad_x[2] = (y[3] *  t3) + (y[0] * R42) - (y[1] *  t2) - (y[6] *  t4) + (y[7] * R74) - (y[5] * R72);
+  grad_x[3] = (y[0] *  t5) - (y[1] * R31) - (y[2] *  t3) + (y[7] *  t6) + (y[4] * R81) - (y[6] * R83);
+  grad_x[4] = (y[5] *  t3) + (y[6] * R86) - (y[7] *  t2) - (y[0] *  t4) - (y[3] * R81) + (y[1] * R61);
+  grad_x[5] = (y[6] *  t5) - (y[4] *  t3) - (y[7] * R75) + (y[1] *  t6) - (y[0] * R52) + (y[2] * R72);
+  grad_x[6] = (y[7] *  t1) - (y[5] *  t5) - (y[4] * R86) + (y[2] *  t4) - (y[1] * R63) + (y[3] * R83);
+  grad_x[7] = (y[4] *  t2) - (y[6] *  t1) + (y[5] * R75) - (y[3] *  t6) - (y[2] * R74) + (y[0] * R54);
+
+  //  calc Y difference vectors
+
+  R42=(y[3] - y[1]);
+  R52=(y[4] - y[1]);
+  R54=(y[4] - y[3]);
+
+  R63=(y[5] - y[2]);
+  R83=(y[7] - y[2]);
+  R86=(y[7] - y[5]);
+
+  R31=(y[2] - y[0]);
+  R61=(y[5] - y[0]);
+  R74=(y[6] - y[3]);
+
+  R72=(y[6] - y[1]);
+  R75=(y[6] - y[4]);
+  R81=(y[7] - y[0]);
+
+  t1=(R63 + R54);
+  t2=(R61 + R74);
+  t3=(R72 + R81);
+
+  t4 =(R86 + R42);
+  t5 =(R83 + R52);
+  t6 =(R75 + R31);
+
+  //  Calculate Z gradient from X and Y data
+
+  grad_z[0] = (x[1] *  t1) - (x[2] * R42) - (x[3] *  t5)  + (x[4] *  t4) + (x[5] * R52) - (x[7] * R54);
+  grad_z[1] = (x[2] *  t2) + (x[3] * R31) - (x[0] *  t1)  - (x[5] *  t6) + (x[6] * R63) - (x[4] * R61);
+  grad_z[2] = (x[3] *  t3) + (x[0] * R42) - (x[1] *  t2)  - (x[6] *  t4) + (x[7] * R74) - (x[5] * R72);
+  grad_z[3] = (x[0] *  t5) - (x[1] * R31) - (x[2] *  t3)  + (x[7] *  t6) + (x[4] * R81) - (x[6] * R83);
+  grad_z[4] = (x[5] *  t3) + (x[6] * R86) - (x[7] *  t2)  - (x[0] *  t4) - (x[3] * R81) + (x[1] * R61);
+  grad_z[5] = (x[6] *  t5) - (x[4] *  t3)  - (x[7] * R75) + (x[1] *  t6) - (x[0] * R52) + (x[2] * R72);
+  grad_z[6] = (x[7] *  t1) - (x[5] *  t5)  - (x[4] * R86) + (x[2] *  t4) - (x[1] * R63) + (x[3] * R83);
+  grad_z[7] = (x[4] *  t2) - (x[6] *  t1)  + (x[5] * R75) - (x[3] *  t6) - (x[2] * R74) + (x[0] * R54);
+}
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class DeviceType >
+struct initialize_element
+{
+  typedef DeviceType     execution_space ;
+
+  typedef Explicit::Fields< Scalar , execution_space > Fields ;
+
+  typename Fields::elem_node_ids_type      elem_node_connectivity ;
+  typename Fields::node_coords_type        model_coords ;
+  typename Fields::elem_sym_tensor_type    stretch ;
+  typename Fields::elem_tensor_state_type  rotation ;
+  typename Fields::array_type              elem_mass ;
+
+  const Scalar density ;
+
+  initialize_element( const Fields & mesh_fields )
+    : elem_node_connectivity( mesh_fields.elem_node_connectivity )
+    , model_coords(           mesh_fields.model_coords )
+    , stretch(                mesh_fields.stretch )
+    , rotation(               mesh_fields.rotation )
+    , elem_mass(              mesh_fields.elem_mass )
+    , density(                mesh_fields.density )
+    {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int ielem )const
+  {
+    const int K_XX = 0 ;
+    const int K_YY = 1 ;
+    const int K_ZZ = 2 ;
+    const Scalar ONE12TH = 1.0 / 12.0 ;
+
+    Scalar x[ Fields::ElemNodeCount ];
+    Scalar y[ Fields::ElemNodeCount ];
+    Scalar z[ Fields::ElemNodeCount ];
+    Scalar grad_x[ Fields::ElemNodeCount ];
+    Scalar grad_y[ Fields::ElemNodeCount ];
+    Scalar grad_z[ Fields::ElemNodeCount ];
+
+    for ( int i = 0 ; i < Fields::ElemNodeCount ; ++i ) {
+      const int n = elem_node_connectivity( ielem , i );
+
+      x[i]  = model_coords( n , 0 );
+      y[i]  = model_coords( n , 1 );
+      z[i]  = model_coords( n , 2 );
+    }
+
+    comp_grad<Scalar,execution_space>( x, y, z, grad_x, grad_y, grad_z);
+
+    stretch(ielem,K_XX) = 1 ;
+    stretch(ielem,K_YY) = 1 ;
+    stretch(ielem,K_ZZ) = 1 ;
+
+    rotation(ielem,K_XX,0) = 1 ;
+    rotation(ielem,K_YY,0) = 1 ;
+    rotation(ielem,K_ZZ,0) = 1 ;
+
+    rotation(ielem,K_XX,1) = 1 ;
+    rotation(ielem,K_YY,1) = 1 ;
+    rotation(ielem,K_ZZ,1) = 1 ;
+
+    elem_mass(ielem) = ONE12TH * density *
+                                 dot8<Scalar,execution_space>( x , grad_x );
+  }
+
+  static void apply( const Fields & mesh_fields )
+  {
+    initialize_element op( mesh_fields );
+    Kokkos::parallel_for( mesh_fields.num_elements , op );
+  }
+};
+
+
+template<typename Scalar , class DeviceType >
+struct initialize_node
+{
+  typedef DeviceType     execution_space ;
+
+  typedef Explicit::Fields< Scalar , execution_space > Fields ;
+
+  typename Fields::node_elem_ids_type      node_elem_connectivity ;
+  typename Fields::array_type              nodal_mass ;
+  typename Fields::array_type              elem_mass ;
+
+  static const int ElemNodeCount = Fields::ElemNodeCount ;
+
+  initialize_node( const Fields & mesh_fields )
+    : node_elem_connectivity( mesh_fields.node_elem_connectivity )
+    , nodal_mass(             mesh_fields.nodal_mass )
+    , elem_mass(              mesh_fields.elem_mass )
+    {}
+
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int inode )const
+  {
+    const int begin = node_elem_connectivity.row_map[inode];
+    const int end   = node_elem_connectivity.row_map[inode+1];
+
+    Scalar node_mass = 0;
+
+    for(int i = begin; i != end; ++i) {
+      const int elem_id = node_elem_connectivity.entries( i , 0 );
+      node_mass += elem_mass(elem_id);
+    }
+
+    nodal_mass(inode) = node_mass / ElemNodeCount ;
+  }
+
+  static void apply( const Fields & mesh_fields )
+  {
+    initialize_node op( mesh_fields );
+    Kokkos::parallel_for( mesh_fields.num_nodes_owned , op );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+
+template<typename Scalar, class DeviceType >
+struct grad
+{
+  typedef DeviceType execution_space ;
+
+  typedef Explicit::Fields< Scalar , execution_space >  Fields ;
+
+  static const int ElemNodeCount = Fields::ElemNodeCount ;
+
+  static const int K_F_XX = Fields::K_F_XX ;
+  static const int K_F_YY = Fields::K_F_YY ;
+  static const int K_F_ZZ = Fields::K_F_ZZ ;
+  static const int K_F_XY = Fields::K_F_XY ;
+  static const int K_F_YZ = Fields::K_F_YZ ;
+  static const int K_F_ZX = Fields::K_F_ZX ;
+  static const int K_F_YX = Fields::K_F_YX ;
+  static const int K_F_ZY = Fields::K_F_ZY ;
+  static const int K_F_XZ = Fields::K_F_XZ ;
+
+  // Global arrays used by this functor.
+
+  const typename Fields::elem_node_ids_type     elem_node_connectivity ;
+  const typename Fields::node_coords_type       model_coords ;
+  const typename Fields::geom_state_array_type  displacement ; 
+  const typename Fields::geom_state_array_type  velocity ; 
+  const typename Fields::elem_tensor_type       vel_grad ;
+  const typename Fields::scalar_type            dt ;
+
+  const int  current_state;
+  const int  previous_state;
+
+  // Constructor on the Host to populate this device functor.
+  // All array view copies are shallow.
+  grad( const Fields &  fields,
+        const int arg_current_state,
+        const int arg_previous_state)
+    : elem_node_connectivity( fields.elem_node_connectivity)
+    , model_coords( fields.model_coords)
+    , displacement( fields.displacement)
+    , velocity( fields.velocity)
+    , vel_grad( fields.vel_grad)
+    , dt(  fields.dt)
+    , current_state(arg_current_state)
+    , previous_state(arg_previous_state)
+    { }
+
+  //--------------------------------------------------------------------------
+
+    //   Calculate Velocity Gradients
+    KOKKOS_INLINE_FUNCTION
+    void v_grad(  int ielem,
+      Scalar * vx,       Scalar * vy,       Scalar * vz,
+      Scalar * grad_x,     Scalar * grad_y,     Scalar * grad_z,
+      Scalar inv_vol) const
+    {
+      const int K_F_XX = Fields::K_F_XX ;
+      const int K_F_YY = Fields::K_F_YY ;
+      const int K_F_ZZ = Fields::K_F_ZZ ;
+      const int K_F_XY = Fields::K_F_XY ;
+      const int K_F_YZ = Fields::K_F_YZ ;
+      const int K_F_ZX = Fields::K_F_ZX ;
+      const int K_F_YX = Fields::K_F_YX ;
+      const int K_F_ZY = Fields::K_F_ZY ;
+      const int K_F_XZ = Fields::K_F_XZ ;
+
+      vel_grad(ielem, K_F_XX) = inv_vol * dot8<Scalar,execution_space>( vx , grad_x );
+      vel_grad(ielem, K_F_YX) = inv_vol * dot8<Scalar,execution_space>( vy , grad_x );
+      vel_grad(ielem, K_F_ZX) = inv_vol * dot8<Scalar,execution_space>( vz , grad_x );
+
+      vel_grad(ielem, K_F_XY) = inv_vol * dot8<Scalar,execution_space>( vx , grad_y );
+      vel_grad(ielem, K_F_YY) = inv_vol * dot8<Scalar,execution_space>( vy , grad_y );
+      vel_grad(ielem, K_F_ZY) = inv_vol * dot8<Scalar,execution_space>( vz , grad_y );
+
+      vel_grad(ielem, K_F_XZ) = inv_vol * dot8<Scalar,execution_space>( vx , grad_z );
+      vel_grad(ielem, K_F_YZ) = inv_vol * dot8<Scalar,execution_space>( vy , grad_z );
+      vel_grad(ielem, K_F_ZZ) = inv_vol * dot8<Scalar,execution_space>( vz , grad_z );
+    }
+
+  //--------------------------------------------------------------------------
+  // Functor operator() which calls the three member functions.
+
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int ielem )const
+  {
+    const int X = 0 ;
+    const int Y = 1 ;
+    const int Z = 2 ;
+    const Scalar dt_scale = -0.5 * *dt;
+
+    //  declare and reuse local data for frequently accessed data to
+    //  reduce global memory reads and writes.
+
+    Scalar      x[8],      y[8],      z[8];
+    Scalar     vx[8],     vy[8],     vz[8];
+    Scalar grad_x[8], grad_y[8], grad_z[8];
+
+    // Read global velocity once and use many times
+    // via local registers / L1 cache.
+    //  store the velocity information in local memory before using,
+    //  so it can be returned for other functions to use
+
+    // Read global coordinates and velocity once and use many times
+    // via local registers / L1 cache.
+    // load X coordinate information and move by half time step
+
+    for ( int i = 0 ; i < ElemNodeCount ; ++i ) {
+      const int n = elem_node_connectivity( ielem , i );
+
+      vx[i] = velocity( n , X , current_state );
+      vy[i] = velocity( n , Y , current_state );
+      vz[i] = velocity( n , Z , current_state );
+
+      x[i]  = model_coords( n , X ) +
+              displacement( n , X , current_state ) +
+              dt_scale * vx[i];
+
+      y[i]  = model_coords( n , Y ) +
+              displacement( n , Y , current_state ) +
+              dt_scale * vy[i];
+
+      z[i]  = model_coords( n , Z ) +
+              displacement( n , Z , current_state ) +
+              dt_scale * vz[i];
+    }
+
+    comp_grad<Scalar,execution_space>( x, y, z, grad_x, grad_y, grad_z);
+
+    //  Calculate hexahedral volume from x model_coords and gradient information
+
+    const Scalar inv_vol = 1.0 / dot8<Scalar,execution_space>( x , grad_x );
+
+    v_grad(ielem, vx, vy, vz, grad_x, grad_y, grad_z, inv_vol);
+  }
+
+  static void apply( const Fields & fields ,
+                     const int arg_current_state ,
+                     const int arg_previous_state )
+  {
+    grad op( fields, arg_current_state , arg_previous_state );
+    Kokkos::parallel_for( fields.num_elements , op );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template<typename Scalar, class DeviceType >
+struct decomp_rotate
+{
+  typedef DeviceType execution_space ;
+
+  typedef Explicit::Fields< Scalar , execution_space >  Fields ;
+
+  static const int ElemNodeCount = Fields::ElemNodeCount ;
+
+  static const int K_F_XX = Fields::K_F_XX ;
+  static const int K_F_YY = Fields::K_F_YY ;
+  static const int K_F_ZZ = Fields::K_F_ZZ ;
+  static const int K_F_XY = Fields::K_F_XY ;
+  static const int K_F_YZ = Fields::K_F_YZ ;
+  static const int K_F_ZX = Fields::K_F_ZX ;
+  static const int K_F_YX = Fields::K_F_YX ;
+  static const int K_F_ZY = Fields::K_F_ZY ;
+  static const int K_F_XZ = Fields::K_F_XZ ;
+
+  static const int K_S_XX = Fields::K_S_XX ;
+  static const int K_S_YY = Fields::K_S_YY ;
+  static const int K_S_ZZ = Fields::K_S_ZZ ;
+  static const int K_S_XY = Fields::K_S_XY ;
+  static const int K_S_YZ = Fields::K_S_YZ ;
+  static const int K_S_ZX = Fields::K_S_ZX ;
+  static const int K_S_YX = Fields::K_S_YX ;
+  static const int K_S_ZY = Fields::K_S_ZY ;
+  static const int K_S_XZ = Fields::K_S_XZ ;
+
+  static const int K_V_XY = Fields::K_V_XY ;
+  static const int K_V_YZ = Fields::K_V_YZ ;
+  static const int K_V_ZX = Fields::K_V_ZX ;
+
+  // Global arrays used by this functor.
+
+  const typename Fields::elem_tensor_state_type     rotation ;
+  const typename Fields::elem_tensor_type           vel_grad ;
+  const typename Fields::elem_sym_tensor_type       stretch ;
+  const typename Fields::elem_sym_tensor_type       rot_stretch ;
+  const typename Fields::scalar_type                dt_value ;
+
+  const int  current_state;
+  const int  previous_state;
+
+  decomp_rotate( const Fields & mesh_fields ,
+                 const int arg_current_state,
+                 const int arg_previous_state)
+    : rotation(    mesh_fields.rotation )
+    , vel_grad(    mesh_fields.vel_grad )
+    , stretch(     mesh_fields.stretch )
+    , rot_stretch( mesh_fields.rot_stretch )
+    , dt_value(    mesh_fields.dt)
+    , current_state( arg_current_state)
+    , previous_state(arg_previous_state)
+    {}
+
+  static void apply( const Fields & mesh_fields ,
+                     const int arg_current_state ,
+                     const int arg_previous_state )
+  {
+    decomp_rotate op( mesh_fields , arg_current_state , arg_previous_state );
+    Kokkos::parallel_for( mesh_fields.num_elements , op );
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void additive_decomp(int ielem, Scalar * v_gr, Scalar * str_ten) const
+  {
+    //  In addition to calculating stretching_tensor,
+    //  use this as an opportunity to load global
+    //  variables into a local space
+
+    for ( int i = 0 ; i < 9 ; ++i ) {
+      v_gr[i] = vel_grad( ielem , i );
+    }
+
+    //
+    //  Symmetric part
+    //
+    str_ten[K_S_XX] = v_gr[K_F_XX];
+    str_ten[K_S_YY] = v_gr[K_F_YY];
+    str_ten[K_S_ZZ] = v_gr[K_F_ZZ];
+    str_ten[K_S_XY] = 0.5*(v_gr[K_F_XY] + v_gr[K_F_YX]);
+    str_ten[K_S_YZ] = 0.5*(v_gr[K_F_YZ] + v_gr[K_F_ZY]);
+    str_ten[K_S_ZX] = 0.5*(v_gr[K_F_ZX] + v_gr[K_F_XZ]);
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void polar_decomp(int ielem, Scalar * v_gr, Scalar * str_ten, Scalar * str, Scalar * vort, Scalar * rot_old, Scalar * rot_new)const
+  {
+    const Scalar dt = *dt_value;
+    const Scalar dt_half = 0.5 * dt;
+
+    //  Skew Symmetric part
+    vort[K_V_XY] = 0.5*(v_gr[K_F_XY] - v_gr[K_F_YX]);
+    vort[K_V_YZ] = 0.5*(v_gr[K_F_YZ] - v_gr[K_F_ZY]);
+    vort[K_V_ZX] = 0.5*(v_gr[K_F_ZX] - v_gr[K_F_XZ]);
+
+    //   calculate the rates of rotation via gauss elimination.
+    for ( int i = 0 ; i < 6 ; ++i ) {
+      str[i] = stretch(ielem, i);
+    }
+
+    Scalar z1 = str_ten[K_S_XY] * str[K_S_ZX] -
+                str_ten[K_S_ZX] * str[K_S_XY] +
+                str_ten[K_S_YY] * str[K_S_YZ] -
+                str_ten[K_S_YZ] * str[K_S_YY] +
+                str_ten[K_S_YZ] * str[K_S_ZZ] -
+                str_ten[K_S_ZZ] * str[K_S_YZ];
+
+    Scalar z2 = str_ten[K_S_ZX] * str[K_S_XX] -
+                str_ten[K_S_XX] * str[K_S_ZX] +
+                str_ten[K_S_YZ] * str[K_S_XY] -
+                str_ten[K_S_XY] * str[K_S_YZ] +
+                str_ten[K_S_ZZ] * str[K_S_ZX] -
+                str_ten[K_S_ZX] * str[K_S_ZZ];
+
+    Scalar z3 = str_ten[K_S_XX] * str[K_S_XY] -
+                str_ten[K_S_XY] * str[K_S_XX] +
+                str_ten[K_S_XY] * str[K_S_YY] -
+                str_ten[K_S_YY] * str[K_S_XY] +
+                str_ten[K_S_ZX] * str[K_S_YZ] -
+                str_ten[K_S_YZ] * str[K_S_ZX];
+
+  //   forward elimination
+    const Scalar a1inv = 1.0 / (str[K_S_YY] + str[K_S_ZZ]);
+
+    const Scalar a4BYa1 = -1 * str[K_S_XY] * a1inv;
+
+    const Scalar a2inv = 1.0 / (str[K_S_ZZ] + str[K_S_XX] + str[K_S_XY] * a4BYa1);
+
+    const Scalar a5 =  -str[K_S_YZ] + str[K_S_ZX] * a4BYa1;
+
+    z2 -= z1 * a4BYa1;
+    Scalar a6BYa1 = -1 * str[K_S_ZX] * a1inv;
+    const Scalar a5BYa2 = a5 * a2inv;
+    z3 -= z1 * a6BYa1 - z2 * a5BYa2;
+
+  //   backward substitution -
+    z3 /= (str[K_S_XX] + str[K_S_YY] + str[K_S_ZX] * a6BYa1 + a5 * a5BYa2);
+    z2 = (z2 - a5 * z3) * a2inv;
+    z1 = (z1*a1inv - a6BYa1 * z3 -a4BYa1 * z2);
+
+  //   calculate rotation rates - recall that spin_rate is an asymmetric tensor,
+  //   so compute spin rate vector as dual of spin rate tensor,
+  //   i.e   w_i = e_ijk * spin_rate_jk
+    z1 += vort[K_V_YZ];
+    z2 += vort[K_V_ZX];
+    z3 += vort[K_V_XY];
+
+  //   update rotation tensor:
+  //  1) premultiply old rotation tensor to get right-hand side.
+
+    for ( int i = 0 ; i < 9 ; ++i ) {
+      rot_old[i] = rotation(ielem, i, previous_state);
+    }
+
+    Scalar r_XX = rot_old[K_F_XX] + dt_half*( z3 * rot_old[K_F_YX] - z2 * rot_old[K_F_ZX] );
+    Scalar r_YX = rot_old[K_F_YX] + dt_half*( z1 * rot_old[K_F_ZX] - z3 * rot_old[K_F_XX] );
+    Scalar r_ZX = rot_old[K_F_ZX] + dt_half*( z2 * rot_old[K_F_XX] - z1 * rot_old[K_F_YX] );
+    Scalar r_XY = rot_old[K_F_XY] + dt_half*( z3 * rot_old[K_F_YY] - z2 * rot_old[K_F_ZY] );
+    Scalar r_YY = rot_old[K_F_YY] + dt_half*( z1 * rot_old[K_F_ZY] - z3 * rot_old[K_F_XY] );
+    Scalar r_ZY = rot_old[K_F_ZY] + dt_half*( z2 * rot_old[K_F_XY] - z1 * rot_old[K_F_YY] );
+    Scalar r_XZ = rot_old[K_F_XZ] + dt_half*( z3 * rot_old[K_F_YZ] - z2 * rot_old[K_F_ZZ] );
+    Scalar r_YZ = rot_old[K_F_YZ] + dt_half*( z1 * rot_old[K_F_ZZ] - z3 * rot_old[K_F_XZ] );
+    Scalar r_ZZ = rot_old[K_F_ZZ] + dt_half*( z2 * rot_old[K_F_XZ] - z1 * rot_old[K_F_YZ] );
+
+
+  //  2) solve for new rotation tensor via gauss elimination.
+  //   forward elimination -
+    Scalar a12 = - dt_half * z3;
+    Scalar a13 =   dt_half * z2;
+    Scalar b32 = - dt_half * z1;
+    Scalar a22inv = 1.0 / (1.0 + a12 * a12);
+
+    Scalar a13a12 = a13*a12;
+    Scalar a23 = b32 + a13a12;
+    r_YX += r_XX * a12;
+    r_YY += r_XY * a12;
+    r_YZ += r_XZ * a12;
+
+
+    b32 = (b32 - a13a12) * a22inv;
+    r_ZX += r_XX * a13 + r_YX * b32;
+    r_ZY += r_XY * a13 + r_YY * b32;
+    r_ZZ += r_XZ * a13 + r_YZ * b32;
+
+
+  //   backward substitution -
+    const Scalar a33inv = 1.0 / (1.0 + a13 * a13 + a23 * b32);
+
+    rot_new[K_F_ZX] = r_ZX * a33inv;
+    rot_new[K_F_ZY] = r_ZY * a33inv;
+    rot_new[K_F_ZZ] = r_ZZ * a33inv;
+    rot_new[K_F_YX] = ( r_YX - rot_new[K_F_ZX] * a23 ) * a22inv;
+    rot_new[K_F_YY] = ( r_YY - rot_new[K_F_ZY] * a23 ) * a22inv;
+    rot_new[K_F_YZ] = ( r_YZ - rot_new[K_F_ZZ] * a23 ) * a22inv;
+    rot_new[K_F_XX] = r_XX - rot_new[K_F_ZX] * a13 - rot_new[K_F_YX] * a12;
+    rot_new[K_F_XY] = r_XY - rot_new[K_F_ZY] * a13 - rot_new[K_F_YY] * a12;
+    rot_new[K_F_XZ] = r_XZ - rot_new[K_F_ZZ] * a13 - rot_new[K_F_YZ] * a12;
+
+    for ( int i = 0 ; i < 9 ; ++i ) {
+      rotation(ielem, i, current_state) = rot_new[i] ;
+    }
+
+  //   update stretch tensor in the new configuration -
+    const Scalar a1 = str_ten[K_S_XY] + vort[K_V_XY];
+    const Scalar a2 = str_ten[K_S_YZ] + vort[K_V_YZ];
+    const Scalar a3 = str_ten[K_S_ZX] + vort[K_V_ZX];
+    const Scalar b1 = str_ten[K_S_ZX] - vort[K_V_ZX];
+    const Scalar b2 = str_ten[K_S_XY] - vort[K_V_XY];
+    const Scalar b3 = str_ten[K_S_YZ] - vort[K_V_YZ];
+
+    const Scalar s_XX = str[K_S_XX];
+    const Scalar s_YY = str[K_S_YY];
+    const Scalar s_ZZ = str[K_S_ZZ];
+    const Scalar s_XY = str[K_S_XY];
+    const Scalar s_YZ = str[K_S_YZ];
+    const Scalar s_ZX = str[K_S_ZX];
+
+    str[K_S_XX] += dt * (str_ten[K_S_XX] * s_XX + ( a1 + z3 ) * s_XY + ( b1 - z2 ) * s_ZX);
+    str[K_S_YY] += dt * (str_ten[K_S_YY] * s_YY + ( a2 + z1 ) * s_YZ + ( b2 - z3 ) * s_XY);
+    str[K_S_ZZ] += dt * (str_ten[K_S_ZZ] * s_ZZ + ( a3 + z2 ) * s_ZX + ( b3 - z1 ) * s_YZ);
+    str[K_S_XY] += dt * (str_ten[K_S_XX] * s_XY + ( a1 )      * s_YY + ( b1      ) * s_YZ - z3 * s_XX + z1 * s_ZX);
+    str[K_S_YZ] += dt * (str_ten[K_S_YY] * s_YZ + ( a2 )      * s_ZZ + ( b2      ) * s_ZX - z1 * s_YY + z2 * s_XY);
+    str[K_S_ZX] += dt * (str_ten[K_S_ZZ] * s_ZX + ( a3 )      * s_XX + ( b3      ) * s_XY - z2 * s_ZZ + z3 * s_YZ);
+
+  }
+
+
+  KOKKOS_INLINE_FUNCTION
+  void rotate_tensor(int ielem, Scalar * str_ten, Scalar * str, Scalar * rot_new)const {
+
+    Scalar t[9];
+    Scalar rot_str[6]; // Rotated stretch
+
+    t[0] = str_ten[K_S_XX]*rot_new[K_F_XX] +
+           str_ten[K_S_XY]*rot_new[K_F_YX] +
+           str_ten[K_S_XZ]*rot_new[K_F_ZX];
+
+    t[1] = str_ten[K_S_YX]*rot_new[K_F_XX] +
+           str_ten[K_S_YY]*rot_new[K_F_YX] +
+           str_ten[K_S_YZ]*rot_new[K_F_ZX];
+
+    t[2] = str_ten[K_S_ZX]*rot_new[K_F_XX] +
+           str_ten[K_S_ZY]*rot_new[K_F_YX] +
+           str_ten[K_S_ZZ]*rot_new[K_F_ZX];
+
+    t[3] = str_ten[K_S_XX]*rot_new[K_F_XY] +
+           str_ten[K_S_XY]*rot_new[K_F_YY] +
+           str_ten[K_S_XZ]*rot_new[K_F_ZY];
+
+    t[4] = str_ten[K_S_YX]*rot_new[K_F_XY] +
+           str_ten[K_S_YY]*rot_new[K_F_YY] +
+           str_ten[K_S_YZ]*rot_new[K_F_ZY];
+
+    t[5] = str_ten[K_S_ZX]*rot_new[K_F_XY] +
+           str_ten[K_S_ZY]*rot_new[K_F_YY] +
+           str_ten[K_S_ZZ]*rot_new[K_F_ZY];
+
+    t[6] = str_ten[K_S_XX]*rot_new[K_F_XZ] +
+           str_ten[K_S_XY]*rot_new[K_F_YZ] +
+           str_ten[K_S_XZ]*rot_new[K_F_ZZ];
+
+    t[7] = str_ten[K_S_YX]*rot_new[K_F_XZ] +
+           str_ten[K_S_YY]*rot_new[K_F_YZ] +
+           str_ten[K_S_YZ]*rot_new[K_F_ZZ];
+
+    t[8] = str_ten[K_S_ZX]*rot_new[K_F_XZ] +
+           str_ten[K_S_ZY]*rot_new[K_F_YZ] +
+           str_ten[K_S_ZZ]*rot_new[K_F_ZZ];
+
+
+    rot_str[ K_S_XX ] = rot_new[K_F_XX] * t[0] +
+                        rot_new[K_F_YX] * t[1] +
+                        rot_new[K_F_ZX] * t[2];
+    rot_str[ K_S_YY ] = rot_new[K_F_XY] * t[3] +
+                        rot_new[K_F_YY] * t[4] +
+                        rot_new[K_F_ZY] * t[5];
+    rot_str[ K_S_ZZ ] = rot_new[K_F_XZ] * t[6] +
+                        rot_new[K_F_YZ] * t[7] +
+                        rot_new[K_F_ZZ] * t[8];
+
+    rot_str[ K_S_XY ] = rot_new[K_F_XX] * t[3] +
+                        rot_new[K_F_YX] * t[4] +
+                        rot_new[K_F_ZX] * t[5];
+    rot_str[ K_S_YZ ] = rot_new[K_F_XY] * t[6] +
+                        rot_new[K_F_YY] * t[7] +
+                        rot_new[K_F_ZY] * t[8];
+    rot_str[ K_S_ZX ] = rot_new[K_F_XZ] * t[0] +
+                        rot_new[K_F_YZ] * t[1] +
+                        rot_new[K_F_ZZ] * t[2];
+
+    for ( int i = 0 ; i < 6 ; ++i ) {
+      rot_stretch(ielem, i) = rot_str[i] ;
+    }
+
+    for ( int i = 0 ; i < 6 ; ++i ) {
+      stretch(ielem, i) = str[i] ;
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int ielem )const {
+
+    //   Local scratch space to avoid multiple
+    //   accesses to global memory.
+    Scalar str_ten[6]; // Stretching tensor
+    Scalar str[6];     // Stretch
+    Scalar rot_old[9]; // Rotation old
+    Scalar rot_new[9]; // Rotation new
+    Scalar vort[3];    // Vorticity
+    Scalar v_gr[9];    // Velocity gradient
+
+    additive_decomp(ielem, v_gr, str_ten);
+
+    polar_decomp(ielem, v_gr, str_ten, str, vort, rot_old, rot_new);
+
+    rotate_tensor(ielem, str_ten, str, rot_new);
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template<typename Scalar, class DeviceType >
+struct internal_force
+{
+  typedef DeviceType execution_space ;
+
+  typedef Explicit::Fields< Scalar , execution_space >  Fields ;
+
+  static const int ElemNodeCount = Fields::ElemNodeCount ;
+
+  static const int K_F_XX = Fields::K_F_XX ;
+  static const int K_F_YY = Fields::K_F_YY ;
+  static const int K_F_ZZ = Fields::K_F_ZZ ;
+  static const int K_F_XY = Fields::K_F_XY ;
+  static const int K_F_YZ = Fields::K_F_YZ ;
+  static const int K_F_ZX = Fields::K_F_ZX ;
+  static const int K_F_YX = Fields::K_F_YX ;
+  static const int K_F_ZY = Fields::K_F_ZY ;
+  static const int K_F_XZ = Fields::K_F_XZ ;
+
+  static const int K_S_XX = Fields::K_S_XX ;
+  static const int K_S_YY = Fields::K_S_YY ;
+  static const int K_S_ZZ = Fields::K_S_ZZ ;
+  static const int K_S_XY = Fields::K_S_XY ;
+  static const int K_S_YZ = Fields::K_S_YZ ;
+  static const int K_S_ZX = Fields::K_S_ZX ;
+  static const int K_S_YX = Fields::K_S_YX ;
+  static const int K_S_ZY = Fields::K_S_ZY ;
+  static const int K_S_XZ = Fields::K_S_XZ ;
+
+  //--------------------------------------------------------------------------
+  // Reduction:
+
+  typedef Scalar value_type;
+
+  KOKKOS_INLINE_FUNCTION
+  static void init(value_type &update) {
+    update = 1.0e32;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update,
+                    const volatile value_type & source )
+  {
+    update = update < source ? update : source;
+  }
+
+  // Final serial processing of reduction value:
+  KOKKOS_INLINE_FUNCTION
+  void final( value_type & result ) const
+  {
+    *prev_dt = *dt ;
+    *dt = result ;
+  };
+
+  //--------------------------------------------------------------------------
+
+  // Global arrays used by this functor.
+
+  const typename Fields::elem_node_ids_type      elem_node_connectivity ;
+  const typename Fields::node_coords_type        model_coords ;
+  const typename Fields::scalar_type             dt ;
+  const typename Fields::scalar_type             prev_dt ;
+  const typename Fields::geom_state_array_type   displacement ;
+  const typename Fields::geom_state_array_type   velocity ;
+  const typename Fields::array_type              elem_mass ;
+  const typename Fields::array_type              internal_energy ;
+  const typename Fields::elem_sym_tensor_type    stress_new ;
+  const typename Fields::elem_node_geom_type     element_force ;
+  const typename Fields::elem_tensor_state_type  rotation ;
+  const typename Fields::elem_sym_tensor_type    rot_stretch ;
+
+  const Scalar     two_mu;
+  const Scalar     bulk_modulus;
+  const Scalar     lin_bulk_visc;
+  const Scalar     quad_bulk_visc;
+  const Scalar     user_dt;
+  const int        current_state;
+
+  internal_force( const Fields & mesh_fields,
+                  const Scalar arg_user_dt,
+                  const int arg_current_state )
+    : elem_node_connectivity( mesh_fields.elem_node_connectivity )
+    , model_coords(           mesh_fields.model_coords )
+    , dt(                     mesh_fields.dt )
+    , prev_dt(                mesh_fields.prev_dt )
+    , displacement(           mesh_fields.displacement )
+    , velocity(               mesh_fields.velocity )
+    , elem_mass(              mesh_fields.elem_mass )
+    , internal_energy(        mesh_fields.internal_energy )
+    , stress_new(             mesh_fields.stress_new )
+    , element_force(          mesh_fields.element_force )
+    , rotation(               mesh_fields.rotation )
+    , rot_stretch(            mesh_fields.rot_stretch )
+    , two_mu(                 mesh_fields.two_mu )
+    , bulk_modulus(           mesh_fields.bulk_modulus )
+    , lin_bulk_visc(          mesh_fields.lin_bulk_visc )
+    , quad_bulk_visc(         mesh_fields.quad_bulk_visc )
+    , user_dt(       arg_user_dt )
+    , current_state( arg_current_state )
+  {}
+
+  static void apply( const Fields & mesh_fields ,
+                     const Scalar arg_user_dt,
+                     const int arg_current_state )
+  {
+    internal_force  op_force( mesh_fields , arg_user_dt , arg_current_state );
+
+    Kokkos::parallel_reduce( mesh_fields.num_elements, op_force );
+  }
+
+  //--------------------------------------------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void rotate_tensor_backward(int ielem ,
+    const Scalar * const s_n ,
+    Scalar * const rot_stress )const
+  {
+    const int rot_state = current_state ; // 1 ;
+
+    //   t : temporary variables
+    //   s_n : stress_new in local memory space
+    //   r_n : rotation_new in local memory space
+    Scalar t[9], r_n[9];
+
+    r_n[0] = rotation(ielem, 0, rot_state );
+    r_n[1] = rotation(ielem, 1, rot_state );
+    r_n[2] = rotation(ielem, 2, rot_state );
+    r_n[3] = rotation(ielem, 3, rot_state );
+    r_n[4] = rotation(ielem, 4, rot_state );
+    r_n[5] = rotation(ielem, 5, rot_state );
+    r_n[6] = rotation(ielem, 6, rot_state );
+    r_n[7] = rotation(ielem, 7, rot_state );
+    r_n[8] = rotation(ielem, 8, rot_state );
+
+    t[0] = s_n[K_S_XX]*r_n[K_F_XX]+ s_n[K_S_XY]*r_n[K_F_XY]+ s_n[K_S_XZ]*r_n[K_F_XZ];
+    t[1] = s_n[K_S_YX]*r_n[K_F_XX]+ s_n[K_S_YY]*r_n[K_F_XY]+ s_n[K_S_YZ]*r_n[K_F_XZ];
+    t[2] = s_n[K_S_ZX]*r_n[K_F_XX]+ s_n[K_S_ZY]*r_n[K_F_XY]+ s_n[K_S_ZZ]*r_n[K_F_XZ];
+    t[3] = s_n[K_S_XX]*r_n[K_F_YX]+ s_n[K_S_XY]*r_n[K_F_YY]+ s_n[K_S_XZ]*r_n[K_F_YZ];
+    t[4] = s_n[K_S_YX]*r_n[K_F_YX]+ s_n[K_S_YY]*r_n[K_F_YY]+ s_n[K_S_YZ]*r_n[K_F_YZ];
+    t[5] = s_n[K_S_ZX]*r_n[K_F_YX]+ s_n[K_S_ZY]*r_n[K_F_YY]+ s_n[K_S_ZZ]*r_n[K_F_YZ];
+    t[6] = s_n[K_S_XX]*r_n[K_F_ZX]+ s_n[K_S_XY]*r_n[K_F_ZY]+ s_n[K_S_XZ]*r_n[K_F_ZZ];
+    t[7] = s_n[K_S_YX]*r_n[K_F_ZX]+ s_n[K_S_YY]*r_n[K_F_ZY]+ s_n[K_S_YZ]*r_n[K_F_ZZ];
+    t[8] = s_n[K_S_ZX]*r_n[K_F_ZX]+ s_n[K_S_ZY]*r_n[K_F_ZY]+ s_n[K_S_ZZ]*r_n[K_F_ZZ];
+
+    rot_stress[ K_S_XX ] = r_n[K_F_XX]*t[0] + r_n[K_F_XY]*t[1] + r_n[K_F_XZ]*t[2];
+    rot_stress[ K_S_YY ] = r_n[K_F_YX]*t[3] + r_n[K_F_YY]*t[4] + r_n[K_F_YZ]*t[5];
+    rot_stress[ K_S_ZZ ] = r_n[K_F_ZX]*t[6] + r_n[K_F_ZY]*t[7] + r_n[K_F_ZZ]*t[8];
+
+    rot_stress[ K_S_XY ] = r_n[K_F_XX]*t[3] + r_n[K_F_XY]*t[4] + r_n[K_F_XZ]*t[5];
+    rot_stress[ K_S_YZ ] = r_n[K_F_YX]*t[6] + r_n[K_F_YY]*t[7] + r_n[K_F_YZ]*t[8];
+    rot_stress[ K_S_ZX ] = r_n[K_F_ZX]*t[0] + r_n[K_F_ZY]*t[1] + r_n[K_F_ZZ]*t[2];
+  }
+
+  //--------------------------------------------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void comp_force(int ielem,
+     const Scalar * const vx ,
+     const Scalar * const vy ,
+     const Scalar * const vz ,
+     const Scalar * const grad_x ,
+     const Scalar * const grad_y ,
+     const Scalar * const grad_z ,
+     Scalar * total_stress12th ) const
+  {
+    Scalar internal_energy_inc = 0 ;
+
+    for(int inode = 0; inode < 8; ++inode) {
+
+      const Scalar fx =
+        total_stress12th[K_S_XX] * grad_x[inode] +
+        total_stress12th[K_S_XY] * grad_y[inode] +
+        total_stress12th[K_S_XZ] * grad_z[inode] ;
+
+      element_force(ielem, 0, inode) = fx ;
+
+      const Scalar fy =
+        total_stress12th[K_S_YX] * grad_x[inode] +
+        total_stress12th[K_S_YY] * grad_y[inode] +
+        total_stress12th[K_S_YZ] * grad_z[inode] ;
+
+      element_force(ielem, 1, inode) = fy ;
+
+      const Scalar fz =
+        total_stress12th[K_S_ZX] * grad_x[inode] +
+        total_stress12th[K_S_ZY] * grad_y[inode] +
+        total_stress12th[K_S_ZZ] * grad_z[inode] ;
+
+      element_force(ielem, 2, inode) = fz ;
+
+      internal_energy_inc +=
+        fx * vx[inode] +
+        fy * vy[inode] +
+        fz * vz[inode] ;
+    }
+
+    internal_energy(ielem) = internal_energy_inc ;
+  }
+
+  //----------------------------------------------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void get_stress(int ielem , Scalar * const s_n ) const
+    {
+      const int kxx = 0;
+      const int kyy = 1;
+      const int kzz = 2;
+      const int kxy = 3;
+      const int kyz = 4;
+      const int kzx = 5;
+
+      const Scalar e = (rot_stretch(ielem,kxx)+rot_stretch(ielem,kyy)+rot_stretch(ielem,kzz))/3.0;
+
+      s_n[kxx] = stress_new(ielem,kxx) += *dt * (two_mu * (rot_stretch(ielem,kxx)-e)+3*bulk_modulus*e);
+      s_n[kyy] = stress_new(ielem,kyy) += *dt * (two_mu * (rot_stretch(ielem,kyy)-e)+3*bulk_modulus*e);
+      s_n[kzz] = stress_new(ielem,kzz) += *dt * (two_mu * (rot_stretch(ielem,kzz)-e)+3*bulk_modulus*e);
+
+      s_n[kxy] = stress_new(ielem,kxy) += *dt * two_mu * rot_stretch(ielem,kxy);
+      s_n[kyz] = stress_new(ielem,kyz) += *dt * two_mu * rot_stretch(ielem,kyz);
+      s_n[kzx] = stress_new(ielem,kzx) += *dt * two_mu * rot_stretch(ielem,kzx);
+    }
+
+  //----------------------------------------------------------------------------
+
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int ielem, value_type & update )const
+  {
+    const Scalar ONE12TH = 1.0 / 12.0 ;
+
+    Scalar x[8], y[8], z[8] ;
+    Scalar vx[8], vy[8], vz[8];
+    Scalar grad_x[8], grad_y[8], grad_z[8];
+
+    // Position and velocity:
+
+    for ( int i = 0 ; i < ElemNodeCount ; ++i ) {
+      const int n = elem_node_connectivity(ielem,i);
+
+      x[i] = model_coords(n, 0) + displacement(n, 0, current_state) ;
+      y[i] = model_coords(n, 1) + displacement(n, 1, current_state) ;
+      z[i] = model_coords(n, 2) + displacement(n, 2, current_state) ;
+
+      vx[i] = velocity(n, 0, current_state);
+      vy[i] = velocity(n, 1, current_state);
+      vz[i] = velocity(n, 2, current_state);
+    }
+
+    // Gradient:
+
+    comp_grad<Scalar,execution_space>( x , y , z , grad_x , grad_y , grad_z );
+
+
+    const Scalar mid_vol = dot8<Scalar,execution_space>( x , grad_x );
+
+    const Scalar shr = two_mu ;
+    const Scalar dil = bulk_modulus + ((2.0*shr)/3.0);
+
+    const Scalar aspect = 6.0 * mid_vol /
+                          ( dot8<Scalar,execution_space>( grad_x , grad_x ) +
+                            dot8<Scalar,execution_space>( grad_y , grad_y ) +
+                            dot8<Scalar,execution_space>( grad_z , grad_z ) );
+
+    const Scalar dtrial = sqrt(elem_mass(ielem) * aspect / dil);
+    const Scalar traced = (rot_stretch(ielem, 0) + rot_stretch(ielem, 1) + rot_stretch(ielem, 2));
+
+    const Scalar eps = traced < 0 ? (lin_bulk_visc - quad_bulk_visc * traced * dtrial) : lin_bulk_visc ;
+
+    const Scalar bulkq = eps * dil * dtrial * traced;
+
+    Scalar cur_time_step = dtrial * ( sqrt( 1.0 + eps * eps) - eps);
+
+    // force fixed time step if input
+
+    cur_time_step = user_dt > 0 ? user_dt : cur_time_step;
+
+    update = update < cur_time_step ? update : cur_time_step;
+
+
+    Scalar s_n[ 6 ];
+
+    get_stress( ielem, s_n );
+
+    Scalar total_stress12th[6];
+
+    // Get rotated stress:
+
+    rotate_tensor_backward(ielem, s_n , total_stress12th );
+
+    total_stress12th[0] = ONE12TH*( total_stress12th[ 0 ] + bulkq );
+    total_stress12th[1] = ONE12TH*( total_stress12th[ 1 ] + bulkq );
+    total_stress12th[2] = ONE12TH*( total_stress12th[ 2 ] + bulkq );
+    total_stress12th[3] = ONE12TH*( total_stress12th[ 3 ] );
+    total_stress12th[4] = ONE12TH*( total_stress12th[ 4 ] );
+    total_stress12th[5] = ONE12TH*( total_stress12th[ 5 ] );
+
+    comp_force(ielem, vx, vy, vz,
+                      grad_x, grad_y, grad_z, total_stress12th);
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template<typename Scalar, class DeviceType >
+struct nodal_step
+{
+  typedef DeviceType     execution_space ;
+  typedef typename execution_space::size_type  size_type;
+
+  typedef Explicit::Fields< Scalar , execution_space >  Fields ;
+
+  const typename Fields::scalar_type            dt ;
+  const typename Fields::scalar_type            prev_dt ;
+  const typename Fields::node_elem_ids_type     node_elem_connectivity ;
+  const typename Fields::node_coords_type       model_coords ;
+  const typename Fields::array_type             nodal_mass ;
+  const typename Fields::geom_state_array_type  displacement ;
+  const typename Fields::geom_state_array_type  velocity ;
+  const typename Fields::geom_array_type        acceleration ;
+  const typename Fields::geom_array_type        internal_force ;
+  const typename Fields::elem_node_geom_type    element_force ;
+
+  const Scalar   x_bc;
+  const int      current_state;
+  const int      next_state;
+
+
+  nodal_step( const Fields  & mesh_fields ,
+              const Scalar    arg_x_bc,
+              const int       arg_current_state,
+              const int       arg_next_state)
+   : dt(       mesh_fields.dt )
+   , prev_dt(  mesh_fields.prev_dt )
+   , node_elem_connectivity( mesh_fields.node_elem_connectivity )
+   , model_coords(   mesh_fields.model_coords )
+   , nodal_mass(     mesh_fields.nodal_mass )
+   , displacement(   mesh_fields.displacement )
+   , velocity(       mesh_fields.velocity )
+   , acceleration(   mesh_fields.acceleration )
+   , internal_force( mesh_fields.internal_force )
+   , element_force(  mesh_fields.element_force )
+   , x_bc(          arg_x_bc )
+   , current_state( arg_current_state )
+   , next_state(    arg_next_state )
+   {
+        //std::cout << "finish_step dt: " << dt << std::endl;
+        //std::cout << "finish_step prev_dt: " << prev_dt << std::endl;
+   }
+
+  static void apply( const Fields  & mesh_fields ,
+                     const Scalar    arg_x_bc ,
+                     const int       arg_current_state ,
+                     const int       arg_next_state )
+  {
+    nodal_step op( mesh_fields, arg_x_bc, arg_current_state, arg_next_state );
+
+    // Only update the owned nodes:
+
+    Kokkos::parallel_for( mesh_fields.num_nodes_owned , op );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()(int inode) const
+    {
+      // Getting count as per 'CSR-like' data structure
+      const int begin = node_elem_connectivity.row_map[inode];
+      const int end   = node_elem_connectivity.row_map[inode+1];
+
+      double local_force[] = {0.0, 0.0, 0.0};
+
+      // Gather-sum internal force from
+      // each element that a node is attached to.
+
+      for ( int i = begin; i < end ; ++i ){
+
+        //  node_elem_offset is a cumulative structure, so
+        //  node_elem_offset(inode) should be the index where
+        //  a particular row's elem_IDs begin
+        const int nelem = node_elem_connectivity.entries( i, 0);
+
+        //  find the row in an element's stiffness matrix
+        //  that corresponds to inode
+        const int elem_node_index = node_elem_connectivity.entries( i, 1);
+
+        local_force[0] += element_force(nelem, 0, elem_node_index);
+        local_force[1] += element_force(nelem, 1, elem_node_index);
+        local_force[2] += element_force(nelem, 2, elem_node_index);
+      }
+
+      internal_force(inode, 0) = local_force[0];
+      internal_force(inode, 1) = local_force[1];
+      internal_force(inode, 2) = local_force[2];
+
+      // Acceleration:
+
+      Scalar v_new[3];
+      Scalar a_current[3];
+
+      const Scalar tol = 1.0e-7;
+
+      // If not on the boundary then: a = F / m
+      if ( tol < fabs(model_coords(inode,0)-x_bc) ) {
+
+        const Scalar m = nodal_mass( inode );
+
+        acceleration(inode,0) = a_current[0] = -local_force[0] / m ;
+        acceleration(inode,1) = a_current[1] = -local_force[1] / m ;
+        acceleration(inode,2) = a_current[2] = -local_force[2] / m ;
+      }
+      else { //enforce fixed BC
+        acceleration(inode,0) = a_current[0] = 0;
+        acceleration(inode,1) = a_current[1] = 0;
+        acceleration(inode,2) = a_current[2] = 0;
+      }
+
+      // Central difference time integration:
+
+      const Scalar dt_disp = *dt ;
+      const Scalar dt_vel = ( *dt + *prev_dt ) / 2.0 ;
+
+      velocity(inode,0,next_state) = v_new[0] =
+        velocity(inode,0,current_state) + dt_vel * a_current[0];
+
+      velocity(inode,1,next_state) = v_new[1] =
+        velocity(inode,1,current_state) + dt_vel * a_current[1];
+
+      velocity(inode,2,next_state) = v_new[2] =
+        velocity(inode,2,current_state) + dt_vel * a_current[2];
+
+      displacement(inode,0,next_state) =
+        displacement(inode,0,current_state) + dt_disp * v_new[0];
+
+      displacement(inode,1,next_state) =
+        displacement(inode,1,current_state) + dt_disp * v_new[1];
+
+      displacement(inode,2,next_state) =
+        displacement(inode,2,current_state) + dt_disp * v_new[2];
+    }
+};
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class DeviceType >
+struct pack_state
+{
+  typedef DeviceType     execution_space ;
+  typedef typename execution_space::size_type  size_type ;
+
+  typedef Explicit::Fields< Scalar , execution_space >  Fields ;
+
+  typedef typename Fields::geom_state_array_type::value_type  value_type ;
+  typedef Kokkos::View< value_type* , execution_space >     buffer_type ;
+
+  static const unsigned value_count = 6 ;
+
+  const typename Fields::geom_state_array_type  displacement ;
+  const typename Fields::geom_state_array_type  velocity ;
+  const buffer_type  output ;
+  const size_type    inode_base ;
+  const size_type    state_next ;
+
+  pack_state( const buffer_type & arg_output ,
+              const Fields      & mesh_fields ,
+              const size_type     arg_begin ,
+              const size_type     arg_state )
+   : displacement( mesh_fields.displacement )
+   , velocity(     mesh_fields.velocity )
+   , output(       arg_output )
+   , inode_base(   arg_begin )
+   , state_next(   arg_state )
+   {}
+
+  static void apply( const buffer_type & arg_output ,
+                     const size_type     arg_begin ,
+                     const size_type     arg_count ,
+                     const Fields      & mesh_fields ,
+                     const size_type     arg_state )
+  {
+    pack_state op( arg_output , mesh_fields , arg_begin , arg_state );
+
+    Kokkos::parallel_for( arg_count , op );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i ) const
+  {
+    const size_type inode = inode_base + i ;
+
+    size_type j = i * value_count ;
+
+    output[j++] = displacement( inode , 0 , state_next );
+    output[j++] = displacement( inode , 1 , state_next );
+    output[j++] = displacement( inode , 2 , state_next );
+    output[j++] = velocity( inode , 0 , state_next );
+    output[j++] = velocity( inode , 1 , state_next );
+    output[j++] = velocity( inode , 2 , state_next );
+  }
+};
+
+template< typename Scalar , class DeviceType >
+struct unpack_state
+{
+  typedef DeviceType     execution_space ;
+  typedef typename execution_space::size_type  size_type ;
+
+  typedef Explicit::Fields< Scalar , execution_space >  Fields ;
+
+  typedef typename Fields::geom_state_array_type::value_type  value_type ;
+  typedef Kokkos::View< value_type* , execution_space >     buffer_type ;
+
+  static const unsigned value_count = 6 ;
+
+  const typename Fields::geom_state_array_type  displacement ;
+  const typename Fields::geom_state_array_type  velocity ;
+  const buffer_type  input ;
+  const size_type    inode_base ;
+  const size_type    state_next ;
+
+  unpack_state( const buffer_type & arg_input ,
+                const Fields      & mesh_fields ,
+                const size_type     arg_begin ,
+                const size_type     arg_state )
+   : displacement( mesh_fields.displacement )
+   , velocity(     mesh_fields.velocity )
+   , input(        arg_input )
+   , inode_base(   arg_begin )
+   , state_next(   arg_state )
+   {}
+
+  static void apply( const Fields      & mesh_fields ,
+                     const size_type     arg_state ,
+                     const buffer_type & arg_input ,
+                     const size_type     arg_begin ,
+                     const size_type     arg_count )
+  {
+    unpack_state op( arg_input , mesh_fields , arg_begin , arg_state );
+
+    Kokkos::parallel_for( arg_count , op );
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i ) const
+  {
+    const size_type inode = inode_base + i ;
+
+    size_type j = i * value_count ;
+
+    displacement( inode , 0 , state_next ) = input[j++] ;
+    displacement( inode , 1 , state_next ) = input[j++] ;
+    displacement( inode , 2 , state_next ) = input[j++] ;
+    velocity( inode , 0 , state_next ) = input[j++] ;
+    velocity( inode , 1 , state_next ) = input[j++] ;
+    velocity( inode , 2 , state_next ) = input[j++] ;
+  }
+};
+
+} /* namespace Explicit */
+
+#endif /* #ifndef KOKKOS_EXPLICITFUNCTORS_HPP */
+
+
diff --git a/lib/kokkos/example/multi_fem/FEMesh.hpp b/lib/kokkos/example/multi_fem/FEMesh.hpp
new file mode 100644
index 0000000000..33468e2fbd
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/FEMesh.hpp
@@ -0,0 +1,86 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_FEMESH_HPP
+#define KOKKOS_FEMESH_HPP
+
+#include <utility>
+#include <limits>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_StaticCrsGraph.hpp>
+
+#include <ParallelComm.hpp>
+#include <ParallelDataMap.hpp>
+
+namespace HybridFEM {
+
+//----------------------------------------------------------------------------
+/** \brief  Finite element mesh fixture for hybrid parallel performance tests.
+ */
+template< typename CoordScalarType , unsigned ElemNodeCount , class Device >
+struct FEMesh {
+
+  typedef typename Device::size_type size_type ;
+
+  static const size_type element_node_count = ElemNodeCount ;
+
+  typedef Kokkos::View< CoordScalarType*[3] , Device >       node_coords_type ;
+  typedef Kokkos::View< size_type*[ElemNodeCount], Device >  elem_node_ids_type ;
+  typedef Kokkos::StaticCrsGraph< size_type[2] ,  Device >   node_elem_ids_type ;
+
+  node_coords_type         node_coords ;
+  elem_node_ids_type       elem_node_ids ;
+  node_elem_ids_type       node_elem_ids ;
+  Kokkos::ParallelDataMap  parallel_data_map ;
+};
+
+//----------------------------------------------------------------------------
+
+} /* namespace HybridFEM */
+
+#endif /* #ifndef KOKKOS_FEMESH_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/HexElement.hpp b/lib/kokkos/example/multi_fem/HexElement.hpp
new file mode 100644
index 0000000000..7dec087cbd
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/HexElement.hpp
@@ -0,0 +1,268 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef ELEMENTHEX_HPP
+#define ELEMENTHEX_HPP
+
+namespace HybridFEM {
+
+template< unsigned NodeCount >
+class HexElement_TensorData ;
+
+template< unsigned NodeCount , class Device >
+class HexElement_TensorEval ;
+
+//----------------------------------------------------------------------------
+/** \brief  Evaluate Hex element on interval [-1,1]^3 */
+template<>
+class HexElement_TensorData< 8 > {
+public:
+
+  static const unsigned element_node_count    = 8 ;
+  static const unsigned spatial_dimension     = 3 ;
+  static const unsigned integration_count_1d  = 2 ;
+  static const unsigned function_count_1d     = 2 ;
+
+  float values_1d [ function_count_1d ][ integration_count_1d ];
+  float derivs_1d [ function_count_1d ][ integration_count_1d ];
+  float weights_1d[ integration_count_1d ];
+
+  unsigned char eval_map[ element_node_count ][4] ;
+
+  static float eval_value_1d( const unsigned jf , const float x )
+  {
+    return 0 == jf ? 0.5 * ( 1.0 - x ) : (
+           1 == jf ? 0.5 * ( 1.0 + x ) : 0 );
+  }
+
+  static float eval_deriv_1d( const unsigned jf , const float )
+  {
+    return 0 == jf ? -0.5 : (
+           1 == jf ?  0.5 : 0 );
+  }
+
+  HexElement_TensorData()
+  {
+    const unsigned char tmp_map[ element_node_count ][ spatial_dimension ] =
+      { { 0 , 0 , 0 },
+        { 1 , 0 , 0 },
+        { 1 , 1 , 0 },
+        { 0 , 1 , 0 },
+        { 0 , 0 , 1 },
+        { 1 , 0 , 1 },
+        { 1 , 1 , 1 },
+        { 0 , 1 , 1 } };
+
+    weights_1d[0] = 1 ;
+    weights_1d[1] = 1 ;
+
+    const float points_1d[ integration_count_1d ] =
+      { -0.577350269 , 0.577350269 };
+
+    for ( unsigned i = 0 ; i < element_node_count ; ++i ) {
+      eval_map[i][0] = tmp_map[i][0];
+      eval_map[i][1] = tmp_map[i][1];
+      eval_map[i][2] = tmp_map[i][2];
+    }
+
+    for ( unsigned xp = 0 ; xp < integration_count_1d ; ++xp ) {
+    for ( unsigned xf = 0 ; xf < function_count_1d ; ++xf ) {
+      values_1d[xp][xf] = eval_value_1d( xf , points_1d[xp] );
+      derivs_1d[xp][xf] = eval_deriv_1d( xf , points_1d[xp] );
+    }}
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template<>
+class HexElement_TensorData< 27 > {
+public:
+
+  static const unsigned element_node_count    = 27 ;
+  static const unsigned spatial_dimension     = 3 ;
+  static const unsigned integration_count_1d  = 3 ;
+  static const unsigned function_count_1d     = 3 ;
+
+  float values_1d [ function_count_1d ][ integration_count_1d ];
+  float derivs_1d [ function_count_1d ][ integration_count_1d ];
+  float weights_1d[ integration_count_1d ];
+
+  unsigned char eval_map[ element_node_count ][4] ;
+
+  // sizeof(EvaluateElementHex) = 111 bytes =
+  //   sizeof(float) * 9 +
+  //   sizeof(float) * 9 +
+  //   sizeof(float) * 3 +
+  //   sizeof(char) * 27 
+
+  static float eval_value_1d( const unsigned jf , const float p )
+  {
+    return 0 == jf ? 0.5 * p * ( p - 1 ) : (
+           1 == jf ? 1.0 - p * p : (
+           2 == jf ? 0.5 * p * ( p + 1 ) : 0 ));
+  }
+
+  static float eval_deriv_1d( const unsigned jf , const float p )
+  {
+    return 0 == jf ? p - 0.5 : (
+           1 == jf ? -2.0 * p : (
+           2 == jf ? p + 0.5 : 0 ));
+  }
+
+  HexElement_TensorData()
+  {
+    const unsigned char tmp_map[ element_node_count ][ spatial_dimension ] =
+      { { 0 , 0 , 0 },
+        { 2 , 0 , 0 },
+        { 2 , 2 , 0 },
+        { 0 , 2 , 0 },
+        { 0 , 0 , 2 },
+        { 2 , 0 , 2 },
+        { 2 , 2 , 2 },
+        { 0 , 2 , 2 },
+        { 1 , 0 , 0 },
+        { 2 , 1 , 0 },
+        { 1 , 2 , 0 },
+        { 0 , 1 , 0 },
+        { 0 , 0 , 1 },
+        { 2 , 0 , 1 },
+        { 2 , 2 , 1 },
+        { 0 , 2 , 1 },
+        { 1 , 0 , 2 },
+        { 2 , 1 , 2 },
+        { 1 , 2 , 2 },
+        { 0 , 1 , 2 },
+        { 1 , 1 , 1 },
+        { 1 , 1 , 0 },
+        { 1 , 1 , 2 },
+        { 0 , 1 , 1 },
+        { 2 , 1 , 1 },
+        { 1 , 0 , 1 },
+        { 1 , 2 , 1 } };
+
+    // Interval [-1,1]
+
+    weights_1d[0] = 0.555555556 ;
+    weights_1d[1] = 0.888888889 ;
+    weights_1d[2] = 0.555555556 ;
+
+    const float points_1d[3] = { -0.774596669 ,
+                                  0.000000000 ,
+                                  0.774596669 };
+
+    for ( unsigned i = 0 ; i < element_node_count ; ++i ) {
+      eval_map[i][0] = tmp_map[i][0];
+      eval_map[i][1] = tmp_map[i][1];
+      eval_map[i][2] = tmp_map[i][2];
+    }
+
+    for ( unsigned xp = 0 ; xp < integration_count_1d ; ++xp ) {
+    for ( unsigned xf = 0 ; xf < function_count_1d ; ++xf ) {
+      values_1d[xp][xf] = eval_value_1d( xf , points_1d[xp] );
+      derivs_1d[xp][xf] = eval_deriv_1d( xf , points_1d[xp] );
+    }}
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< unsigned NodeCount >
+class HexElement_Data {
+public:
+  static const unsigned spatial_dimension   = 3 ;
+  static const unsigned element_node_count  = NodeCount ;
+  static const unsigned integration_count   = NodeCount ;
+  static const unsigned function_count      = NodeCount ;
+
+  float weights[   integration_count ] ;
+  float values[    integration_count ][ function_count ];
+  float gradients[ integration_count ][ spatial_dimension ][ function_count ];
+
+  HexElement_Data()
+  {
+    HexElement_TensorData< NodeCount > tensor_data ;
+
+    for ( unsigned ip = 0 ; ip < integration_count ; ++ip ) {
+
+      const unsigned ipx = tensor_data.eval_map[ip][0] ;
+      const unsigned ipy = tensor_data.eval_map[ip][1] ;
+      const unsigned ipz = tensor_data.eval_map[ip][2] ;
+
+      weights[ip] = tensor_data.weights_1d[ ipx ] *
+                    tensor_data.weights_1d[ ipy ] *
+                    tensor_data.weights_1d[ ipz ] ;
+
+      for ( unsigned jf = 0 ; jf < function_count ; ++jf ) {
+
+        const unsigned jfx = tensor_data.eval_map[jf][0] ;
+        const unsigned jfy = tensor_data.eval_map[jf][1] ;
+        const unsigned jfz = tensor_data.eval_map[jf][2] ;
+
+        values[ip][jf] = tensor_data.values_1d[ ipx ][ jfx ] *
+                         tensor_data.values_1d[ ipy ][ jfy ] *
+                         tensor_data.values_1d[ ipz ][ jfz ] ;
+
+        gradients[ip][0][jf] = tensor_data.derivs_1d[ ipx ][ jfx ] *
+                               tensor_data.values_1d[ ipy ][ jfy ] *
+                               tensor_data.values_1d[ ipz ][ jfz ] ;
+
+        gradients[ip][1][jf] = tensor_data.values_1d[ ipx ][ jfx ] *
+                               tensor_data.derivs_1d[ ipy ][ jfy ] *
+                               tensor_data.values_1d[ ipz ][ jfz ] ;
+
+        gradients[ip][2][jf] = tensor_data.values_1d[ ipx ][ jfx ] *
+                               tensor_data.values_1d[ ipy ][ jfy ] *
+                               tensor_data.derivs_1d[ ipz ][ jfz ] ;
+      }
+    }
+  }
+};
+
+//----------------------------------------------------------------------------
+
+} /* namespace HybridFEM */
+
+#endif /* #ifndef ELEMENTHEX_HPP */
+
+
diff --git a/lib/kokkos/example/multi_fem/HexExplicitFunctions.hpp b/lib/kokkos/example/multi_fem/HexExplicitFunctions.hpp
new file mode 100644
index 0000000000..3c4ca58224
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/HexExplicitFunctions.hpp
@@ -0,0 +1,443 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_HEXEXPLICITFUNCTIONS_HPP
+#define KOKKOS_HEXEXPLICITFUNCTIONS_HPP
+
+#include <math.h>
+
+namespace Explicit {
+
+struct Hex8Functions
+{
+  static const unsigned SpatialDim    = 3 ;
+  static const unsigned ElemNodeCount = 8 ;
+
+  // Indices for full 3x3 tensor:
+
+  static const unsigned K_F_XX = 0 ;
+  static const unsigned K_F_YY = 1 ;
+  static const unsigned K_F_ZZ = 2 ;
+  static const unsigned K_F_XY = 3 ;
+  static const unsigned K_F_YZ = 4 ;
+  static const unsigned K_F_ZX = 5 ;
+  static const unsigned K_F_YX = 6 ;
+  static const unsigned K_F_ZY = 7 ;
+  static const unsigned K_F_XZ = 8 ;
+  static const unsigned K_F_SIZE = 9 ;
+
+  //  Indexes into a 3 by 3 symmetric tensor stored as a length 6 vector
+
+  static const unsigned K_S_XX = 0 ;
+  static const unsigned K_S_YY = 1 ;
+  static const unsigned K_S_ZZ = 2 ;
+  static const unsigned K_S_XY = 3 ;
+  static const unsigned K_S_YZ = 4 ;
+  static const unsigned K_S_ZX = 5 ;
+  static const unsigned K_S_YX = 3 ;
+  static const unsigned K_S_ZY = 4 ;
+  static const unsigned K_S_XZ = 5 ;
+  static const unsigned K_S_SIZE = 6 ;
+
+  //  Indexes into a 3 by 3 skew symmetric tensor stored as a length 3 vector
+
+  static const unsigned K_V_XY = 0 ;
+  static const unsigned K_V_YZ = 1 ;
+  static const unsigned K_V_ZX = 2 ;
+  static const unsigned K_V_SIZE = 3 ;
+
+  //--------------------------------------------------------------------------
+
+  template< typename ScalarA , typename ScalarB >
+  KOKKOS_INLINE_FUNCTION static
+  double dot8( const ScalarA * const a , const ScalarB * const b )
+  { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3] +
+           a[4] * b[4] + a[5] * b[5] + a[6] * b[6] + a[7] * b[7] ; }
+
+  //--------------------------------------------------------------------------
+
+  template< class ScalarPrecise ,
+            class ScalarCompact >
+  KOKKOS_INLINE_FUNCTION static
+  void grad( const ScalarPrecise x[] ,
+             const ScalarPrecise z[] ,
+                   ScalarCompact grad_y[] )
+  {
+    const ScalarCompact R42=(x[3] - x[1]);
+    const ScalarCompact R52=(x[4] - x[1]);
+    const ScalarCompact R54=(x[4] - x[3]);
+
+    const ScalarCompact R63=(x[5] - x[2]);
+    const ScalarCompact R83=(x[7] - x[2]);
+    const ScalarCompact R86=(x[7] - x[5]);
+
+    const ScalarCompact R31=(x[2] - x[0]);
+    const ScalarCompact R61=(x[5] - x[0]);
+    const ScalarCompact R74=(x[6] - x[3]);
+
+    const ScalarCompact R72=(x[6] - x[1]);
+    const ScalarCompact R75=(x[6] - x[4]);
+    const ScalarCompact R81=(x[7] - x[0]);
+
+    const ScalarCompact t1=(R63 + R54);
+    const ScalarCompact t2=(R61 + R74);
+    const ScalarCompact t3=(R72 + R81);
+
+    const ScalarCompact t4 =(R86 + R42);
+    const ScalarCompact t5 =(R83 + R52);
+    const ScalarCompact t6 =(R75 + R31);
+
+    //  Calculate Y gradient from X and Z data
+
+    grad_y[0] = (z[1] *  t1) - (z[2] * R42) - (z[3] *  t5)  + (z[4] *  t4) + (z[5] * R52) - (z[7] * R54);
+    grad_y[1] = (z[2] *  t2) + (z[3] * R31) - (z[0] *  t1)  - (z[5] *  t6) + (z[6] * R63) - (z[4] * R61);
+    grad_y[2] = (z[3] *  t3) + (z[0] * R42) - (z[1] *  t2)  - (z[6] *  t4) + (z[7] * R74) - (z[5] * R72);
+    grad_y[3] = (z[0] *  t5) - (z[1] * R31) - (z[2] *  t3)  + (z[7] *  t6) + (z[4] * R81) - (z[6] * R83);
+    grad_y[4] = (z[5] *  t3) + (z[6] * R86) - (z[7] *  t2)  - (z[0] *  t4) - (z[3] * R81) + (z[1] * R61);
+    grad_y[5] = (z[6] *  t5) - (z[4] *  t3)  - (z[7] * R75) + (z[1] *  t6) - (z[0] * R52) + (z[2] * R72);
+    grad_y[6] = (z[7] *  t1) - (z[5] *  t5)  - (z[4] * R86) + (z[2] *  t4) - (z[1] * R63) + (z[3] * R83);
+    grad_y[7] = (z[4] *  t2) - (z[6] *  t1)  + (z[5] * R75) - (z[3] *  t6) - (z[2] * R74) + (z[0] * R54);
+  }
+
+  template< class ScalarPrecise ,
+            class ScalarCompact >
+  static KOKKOS_INLINE_FUNCTION
+  void grad( const ScalarPrecise x[] ,
+             const ScalarPrecise y[] ,
+             const ScalarPrecise z[] ,
+                   ScalarCompact grad_x[] ,
+                   ScalarCompact grad_y[] ,
+                   ScalarCompact grad_z[] )
+  {
+    grad( x , z , grad_y );
+    grad( z , y , grad_x );
+    grad( y , x , grad_z );
+  }
+
+  //--------------------------------------------------------------------------
+
+  template< class ScalarPrecise ,
+            class ScalarCompact >
+  KOKKOS_INLINE_FUNCTION static
+  void polar_decomp( const float dt ,
+                     const ScalarCompact v_gr[] ,
+                           ScalarPrecise stretch[] /* INOUT */ ,
+                           ScalarCompact str_ten[] /* OUT */ ,
+                           ScalarCompact rot[]     /* OUT */ )
+  {
+    const float dt_half = 0.5 * dt;
+
+    ScalarCompact vort[ K_V_SIZE ];  // Vorticity
+
+    //  Symmetric part
+    str_ten[K_S_XX] = v_gr[K_F_XX];
+    str_ten[K_S_YY] = v_gr[K_F_YY];
+    str_ten[K_S_ZZ] = v_gr[K_F_ZZ];
+    str_ten[K_S_XY] = 0.5 * ( v_gr[K_F_XY] + v_gr[K_F_YX] );
+    str_ten[K_S_YZ] = 0.5 * ( v_gr[K_F_YZ] + v_gr[K_F_ZY] );
+    str_ten[K_S_ZX] = 0.5 * ( v_gr[K_F_ZX] + v_gr[K_F_XZ] );
+
+    //  Skew Symmetric part
+    vort[K_V_XY] = 0.5 * ( v_gr[K_F_XY] - v_gr[K_F_YX] );
+    vort[K_V_YZ] = 0.5 * ( v_gr[K_F_YZ] - v_gr[K_F_ZY] );
+    vort[K_V_ZX] = 0.5 * ( v_gr[K_F_ZX] - v_gr[K_F_XZ] );
+
+    //   calculate the rates of rotation via gauss elimination.
+
+    ScalarCompact z1 = str_ten[K_S_XY] * stretch[K_S_ZX] -
+                       str_ten[K_S_ZX] * stretch[K_S_XY] +
+                       str_ten[K_S_YY] * stretch[K_S_YZ] -
+                       str_ten[K_S_YZ] * stretch[K_S_YY] +
+                       str_ten[K_S_YZ] * stretch[K_S_ZZ] -
+                       str_ten[K_S_ZZ] * stretch[K_S_YZ];
+
+    ScalarCompact z2 = str_ten[K_S_ZX] * stretch[K_S_XX] -
+                       str_ten[K_S_XX] * stretch[K_S_ZX] +
+                       str_ten[K_S_YZ] * stretch[K_S_XY] -
+                       str_ten[K_S_XY] * stretch[K_S_YZ] +
+                       str_ten[K_S_ZZ] * stretch[K_S_ZX] -
+                       str_ten[K_S_ZX] * stretch[K_S_ZZ];
+
+    ScalarCompact z3 = str_ten[K_S_XX] * stretch[K_S_XY] -
+                       str_ten[K_S_XY] * stretch[K_S_XX] +
+                       str_ten[K_S_XY] * stretch[K_S_YY] -
+                       str_ten[K_S_YY] * stretch[K_S_XY] +
+                       str_ten[K_S_ZX] * stretch[K_S_YZ] -
+                       str_ten[K_S_YZ] * stretch[K_S_ZX];
+
+    {
+      //   forward elimination
+
+      const ScalarCompact a1inv  = 1.0 / (stretch[K_S_YY] + stretch[K_S_ZZ]);
+      const ScalarCompact a4BYa1 = -1 * stretch[K_S_XY] * a1inv;
+      const ScalarCompact a2inv  = 1.0 / (stretch[K_S_ZZ] + stretch[K_S_XX] + stretch[K_S_XY] * a4BYa1);
+
+     const ScalarCompact a5 =  -stretch[K_S_YZ] + stretch[K_S_ZX] * a4BYa1;
+
+      z2 -= z1 * a4BYa1;
+      const ScalarCompact a6BYa1 = -1 * stretch[K_S_ZX] * a1inv;
+      const ScalarCompact a5BYa2 = a5 * a2inv;
+      z3 -= z1 * a6BYa1 - z2 * a5BYa2;
+
+      //   backward substitution -
+
+      z3 /= (stretch[K_S_XX] + stretch[K_S_YY] + stretch[K_S_ZX] * a6BYa1 + a5 * a5BYa2);
+      z2 = (z2 - a5 * z3) * a2inv;
+      z1 = (z1*a1inv - a6BYa1 * z3 -a4BYa1 * z2);
+    }
+
+    //   calculate rotation rates - recall that spin_rate is an asymmetric tensor,
+    //   so compute spin rate vector as dual of spin rate tensor,
+    //   i.e   w_i = e_ijk * spin_rate_jk
+
+    z1 += vort[K_V_YZ];
+    z2 += vort[K_V_ZX];
+    z3 += vort[K_V_XY];
+
+    {
+      //   update rotation tensor:
+      //  1) premultiply old rotation tensor to get right-hand side.
+
+      ScalarCompact r_XX = rot[K_F_XX] + dt_half*( z3 * rot[K_F_YX] - z2 * rot[K_F_ZX] );
+      ScalarCompact r_YX = rot[K_F_YX] + dt_half*( z1 * rot[K_F_ZX] - z3 * rot[K_F_XX] );
+      ScalarCompact r_ZX = rot[K_F_ZX] + dt_half*( z2 * rot[K_F_XX] - z1 * rot[K_F_YX] );
+      ScalarCompact r_XY = rot[K_F_XY] + dt_half*( z3 * rot[K_F_YY] - z2 * rot[K_F_ZY] );
+      ScalarCompact r_YY = rot[K_F_YY] + dt_half*( z1 * rot[K_F_ZY] - z3 * rot[K_F_XY] );
+      ScalarCompact r_ZY = rot[K_F_ZY] + dt_half*( z2 * rot[K_F_XY] - z1 * rot[K_F_YY] );
+      ScalarCompact r_XZ = rot[K_F_XZ] + dt_half*( z3 * rot[K_F_YZ] - z2 * rot[K_F_ZZ] );
+      ScalarCompact r_YZ = rot[K_F_YZ] + dt_half*( z1 * rot[K_F_ZZ] - z3 * rot[K_F_XZ] );
+      ScalarCompact r_ZZ = rot[K_F_ZZ] + dt_half*( z2 * rot[K_F_XZ] - z1 * rot[K_F_YZ] );
+
+
+      //  2) solve for new rotation tensor via gauss elimination.
+      //   forward elimination -
+
+      const ScalarCompact a12 = - dt_half * z3;
+      const ScalarCompact a13 =   dt_half * z2;
+            ScalarCompact b32 = - dt_half * z1;
+      const ScalarCompact a22inv = 1.0 / (1.0 + a12 * a12);
+
+      const ScalarCompact a13a12 = a13*a12;
+      const ScalarCompact a23 = b32 + a13a12;
+
+      r_YX += r_XX * a12;
+      r_YY += r_XY * a12;
+      r_YZ += r_XZ * a12;
+
+      b32 = (b32 - a13a12) * a22inv;
+
+      r_ZX += r_XX * a13 + r_YX * b32;
+      r_ZY += r_XY * a13 + r_YY * b32;
+      r_ZZ += r_XZ * a13 + r_YZ * b32;
+
+      //   backward substitution -
+
+      const ScalarCompact a33inv = 1.0 / (1.0 + a13 * a13 + a23 * b32);
+
+      rot[K_F_ZX] = r_ZX * a33inv;
+      rot[K_F_ZY] = r_ZY * a33inv;
+      rot[K_F_ZZ] = r_ZZ * a33inv;
+      rot[K_F_YX] = ( r_YX - rot[K_F_ZX] * a23 ) * a22inv;
+      rot[K_F_YY] = ( r_YY - rot[K_F_ZY] * a23 ) * a22inv;
+      rot[K_F_YZ] = ( r_YZ - rot[K_F_ZZ] * a23 ) * a22inv;
+      rot[K_F_XX] = r_XX - rot[K_F_ZX] * a13 - rot[K_F_YX] * a12;
+      rot[K_F_XY] = r_XY - rot[K_F_ZY] * a13 - rot[K_F_YY] * a12;
+      rot[K_F_XZ] = r_XZ - rot[K_F_ZZ] * a13 - rot[K_F_YZ] * a12;
+    }
+
+    //   update stretch tensor in the new configuration -
+
+    const ScalarCompact a1 = str_ten[K_S_XY] + vort[K_V_XY];
+    const ScalarCompact a2 = str_ten[K_S_YZ] + vort[K_V_YZ];
+    const ScalarCompact a3 = str_ten[K_S_ZX] + vort[K_V_ZX];
+    const ScalarCompact b1 = str_ten[K_S_ZX] - vort[K_V_ZX];
+    const ScalarCompact b2 = str_ten[K_S_XY] - vort[K_V_XY];
+    const ScalarCompact b3 = str_ten[K_S_YZ] - vort[K_V_YZ];
+
+    const ScalarCompact s_XX = stretch[K_S_XX];
+    const ScalarCompact s_YY = stretch[K_S_YY];
+    const ScalarCompact s_ZZ = stretch[K_S_ZZ];
+    const ScalarCompact s_XY = stretch[K_S_XY];
+    const ScalarCompact s_YZ = stretch[K_S_YZ];
+    const ScalarCompact s_ZX = stretch[K_S_ZX];
+
+    stretch[K_S_XX] += dt * (str_ten[K_S_XX] * s_XX + ( a1 + z3 ) * s_XY + ( b1 - z2 ) * s_ZX);
+    stretch[K_S_YY] += dt * (str_ten[K_S_YY] * s_YY + ( a2 + z1 ) * s_YZ + ( b2 - z3 ) * s_XY);
+    stretch[K_S_ZZ] += dt * (str_ten[K_S_ZZ] * s_ZZ + ( a3 + z2 ) * s_ZX + ( b3 - z1 ) * s_YZ);
+    stretch[K_S_XY] += dt * (str_ten[K_S_XX] * s_XY + ( a1 )      * s_YY + ( b1      ) * s_YZ - z3 * s_XX + z1 * s_ZX);
+    stretch[K_S_YZ] += dt * (str_ten[K_S_YY] * s_YZ + ( a2 )      * s_ZZ + ( b2      ) * s_ZX - z1 * s_YY + z2 * s_XY);
+    stretch[K_S_ZX] += dt * (str_ten[K_S_ZZ] * s_ZX + ( a3 )      * s_XX + ( b3      ) * s_XY - z2 * s_ZZ + z3 * s_YZ);
+  }
+
+  //--------------------------------------------------------------------------
+
+  template< typename ScalarCompact >
+  static KOKKOS_INLINE_FUNCTION
+  void rotate_tensor( const ScalarCompact str_ten[] ,
+                      const ScalarCompact rot[] ,
+                            ScalarCompact rot_str[] )
+  {
+    ScalarCompact t[9];
+
+    t[0] = str_ten[K_S_XX]*rot[K_F_XX] + str_ten[K_S_XY]*rot[K_F_YX] + str_ten[K_S_XZ]*rot[K_F_ZX];
+    t[1] = str_ten[K_S_YX]*rot[K_F_XX] + str_ten[K_S_YY]*rot[K_F_YX] + str_ten[K_S_YZ]*rot[K_F_ZX];
+    t[2] = str_ten[K_S_ZX]*rot[K_F_XX] + str_ten[K_S_ZY]*rot[K_F_YX] + str_ten[K_S_ZZ]*rot[K_F_ZX];
+
+    t[3] = str_ten[K_S_XX]*rot[K_F_XY] + str_ten[K_S_XY]*rot[K_F_YY] + str_ten[K_S_XZ]*rot[K_F_ZY];
+    t[4] = str_ten[K_S_YX]*rot[K_F_XY] + str_ten[K_S_YY]*rot[K_F_YY] + str_ten[K_S_YZ]*rot[K_F_ZY];
+    t[5] = str_ten[K_S_ZX]*rot[K_F_XY] + str_ten[K_S_ZY]*rot[K_F_YY] + str_ten[K_S_ZZ]*rot[K_F_ZY];
+
+    t[6] = str_ten[K_S_XX]*rot[K_F_XZ] + str_ten[K_S_XY]*rot[K_F_YZ] + str_ten[K_S_XZ]*rot[K_F_ZZ];
+    t[7] = str_ten[K_S_YX]*rot[K_F_XZ] + str_ten[K_S_YY]*rot[K_F_YZ] + str_ten[K_S_YZ]*rot[K_F_ZZ];
+    t[8] = str_ten[K_S_ZX]*rot[K_F_XZ] + str_ten[K_S_ZY]*rot[K_F_YZ] + str_ten[K_S_ZZ]*rot[K_F_ZZ];
+
+
+    rot_str[ K_S_XX ] = rot[K_F_XX] * t[0] + rot[K_F_YX] * t[1] + rot[K_F_ZX] * t[2];
+    rot_str[ K_S_YY ] = rot[K_F_XY] * t[3] + rot[K_F_YY] * t[4] + rot[K_F_ZY] * t[5];
+    rot_str[ K_S_ZZ ] = rot[K_F_XZ] * t[6] + rot[K_F_YZ] * t[7] + rot[K_F_ZZ] * t[8];
+
+    rot_str[ K_S_XY ] = rot[K_F_XX] * t[3] + rot[K_F_YX] * t[4] + rot[K_F_ZX] * t[5];
+    rot_str[ K_S_YZ ] = rot[K_F_XY] * t[6] + rot[K_F_YY] * t[7] + rot[K_F_ZY] * t[8];
+    rot_str[ K_S_ZX ] = rot[K_F_XZ] * t[0] + rot[K_F_YZ] * t[1] + rot[K_F_ZZ] * t[2];
+  }
+
+  //--------------------------------------------------------------------------
+
+  template< class ScalarPrecise ,
+            class ScalarCompact >
+  static KOKKOS_INLINE_FUNCTION
+  void rotate_tensor_backward( const ScalarPrecise stress[] ,
+                               const ScalarCompact rot[] ,
+                                     ScalarCompact rot_stress[] )
+  {
+    ScalarCompact t[9] ;
+
+    t[0] = stress[K_S_XX]*rot[K_F_XX]+ stress[K_S_XY]*rot[K_F_XY]+ stress[K_S_XZ]*rot[K_F_XZ];
+    t[1] = stress[K_S_YX]*rot[K_F_XX]+ stress[K_S_YY]*rot[K_F_XY]+ stress[K_S_YZ]*rot[K_F_XZ];
+    t[2] = stress[K_S_ZX]*rot[K_F_XX]+ stress[K_S_ZY]*rot[K_F_XY]+ stress[K_S_ZZ]*rot[K_F_XZ];
+    t[3] = stress[K_S_XX]*rot[K_F_YX]+ stress[K_S_XY]*rot[K_F_YY]+ stress[K_S_XZ]*rot[K_F_YZ];
+    t[4] = stress[K_S_YX]*rot[K_F_YX]+ stress[K_S_YY]*rot[K_F_YY]+ stress[K_S_YZ]*rot[K_F_YZ];
+    t[5] = stress[K_S_ZX]*rot[K_F_YX]+ stress[K_S_ZY]*rot[K_F_YY]+ stress[K_S_ZZ]*rot[K_F_YZ];
+    t[6] = stress[K_S_XX]*rot[K_F_ZX]+ stress[K_S_XY]*rot[K_F_ZY]+ stress[K_S_XZ]*rot[K_F_ZZ];
+    t[7] = stress[K_S_YX]*rot[K_F_ZX]+ stress[K_S_YY]*rot[K_F_ZY]+ stress[K_S_YZ]*rot[K_F_ZZ];
+    t[8] = stress[K_S_ZX]*rot[K_F_ZX]+ stress[K_S_ZY]*rot[K_F_ZY]+ stress[K_S_ZZ]*rot[K_F_ZZ];
+
+    rot_stress[ K_S_XX ] = rot[K_F_XX]*t[0] + rot[K_F_XY]*t[1] + rot[K_F_XZ]*t[2];
+    rot_stress[ K_S_YY ] = rot[K_F_YX]*t[3] + rot[K_F_YY]*t[4] + rot[K_F_YZ]*t[5];
+    rot_stress[ K_S_ZZ ] = rot[K_F_ZX]*t[6] + rot[K_F_ZY]*t[7] + rot[K_F_ZZ]*t[8];
+
+    rot_stress[ K_S_XY ] = rot[K_F_XX]*t[3] + rot[K_F_XY]*t[4] + rot[K_F_XZ]*t[5];
+    rot_stress[ K_S_YZ ] = rot[K_F_YX]*t[6] + rot[K_F_YY]*t[7] + rot[K_F_YZ]*t[8];
+    rot_stress[ K_S_ZX ] = rot[K_F_ZX]*t[0] + rot[K_F_ZY]*t[1] + rot[K_F_ZZ]*t[2];
+  }
+
+  //--------------------------------------------------------------------------
+
+  template< class ScalarPrecise ,
+            class ScalarCompact >
+  KOKKOS_INLINE_FUNCTION static
+  void update_stress( const float dt ,
+                      const float two_mu ,
+                      const float bulk_modulus ,
+                      const ScalarCompact rot_str[] ,
+                            ScalarPrecise stress[] )
+  {
+    const ScalarCompact e = rot_str[ K_S_XX ] + rot_str[ K_S_YY ] + rot_str[ K_S_ZZ ] ;
+    const ScalarCompact eb = e * bulk_modulus ;
+    const ScalarCompact e3 = e / 3.0 ;
+
+    stress[K_S_XX] += dt * ( two_mu * ( rot_str[K_S_XX] - e3 ) + eb );
+    stress[K_S_YY] += dt * ( two_mu * ( rot_str[K_S_YY] - e3 ) + eb );
+    stress[K_S_ZZ] += dt * ( two_mu * ( rot_str[K_S_ZZ] - e3 ) + eb );
+
+    stress[K_S_XY] += dt * two_mu * rot_str[K_S_XY];
+    stress[K_S_YZ] += dt * two_mu * rot_str[K_S_YZ];
+    stress[K_S_ZX] += dt * two_mu * rot_str[K_S_ZX];
+  }
+
+  //--------------------------------------------------------------------------
+
+  template< class ScalarPrecise ,
+            class ScalarCompact >
+  static KOKKOS_INLINE_FUNCTION
+  void comp_force( const ScalarPrecise vx[] ,
+                   const ScalarPrecise vy[] ,
+                   const ScalarPrecise vz[] ,
+                   const ScalarCompact grad_x[] ,
+                   const ScalarCompact grad_y[] ,
+                   const ScalarCompact grad_z[] ,
+                   const ScalarCompact total_stress12th[] ,
+                         ScalarCompact force[][ SpatialDim ] ,
+                         ScalarCompact & energy )
+  {
+    ScalarPrecise internal_energy = 0 ;
+
+    for ( unsigned inode = 0; inode < ElemNodeCount ; ++inode ) {
+
+      force[inode][0] = total_stress12th[K_S_XX] * grad_x[inode] +
+                        total_stress12th[K_S_XY] * grad_y[inode] +
+                        total_stress12th[K_S_XZ] * grad_z[inode] ;
+
+      force[inode][1] = total_stress12th[K_S_YX] * grad_x[inode] +
+                        total_stress12th[K_S_YY] * grad_y[inode] +
+                        total_stress12th[K_S_YZ] * grad_z[inode] ;
+
+      force[inode][2] = total_stress12th[K_S_ZX] * grad_x[inode] +
+                        total_stress12th[K_S_ZY] * grad_y[inode] +
+                        total_stress12th[K_S_ZZ] * grad_z[inode] ;
+
+      internal_energy += force[inode][0] * vx[inode] +
+                         force[inode][1] * vy[inode] +
+                         force[inode][2] * vz[inode] ;
+    }
+
+    energy = internal_energy ;
+  }
+
+  //--------------------------------------------------------------------------
+};
+
+} // namespace Explicit
+
+#endif /* #ifndef KOKKOS_HEXEXPLICITFUNCTIONS_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/Implicit.hpp b/lib/kokkos/example/multi_fem/Implicit.hpp
new file mode 100644
index 0000000000..53f602f11a
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/Implicit.hpp
@@ -0,0 +1,341 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef HYBRIDFEM_IMPLICIT_HPP
+#define HYBRIDFEM_IMPLICIT_HPP
+
+#include <utility>
+#include <iostream>
+#include <iomanip>
+
+#include <Kokkos_Core.hpp>
+#include <SparseLinearSystem.hpp>
+#include <SparseLinearSystemFill.hpp>
+#include <ImplicitFunctors.hpp>
+#include <FEMesh.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace HybridFEM {
+namespace Implicit {
+
+struct PerformanceData {
+  double mesh_time ;
+  double graph_time ;
+  double elem_time ;
+  double matrix_gather_fill_time ;
+  double matrix_boundary_condition_time ;
+  double cg_iteration_time ;
+
+  PerformanceData()
+    : mesh_time(0)
+    , graph_time(0)
+    , elem_time(0)
+    , matrix_gather_fill_time(0)
+    , matrix_boundary_condition_time(0)
+    , cg_iteration_time(0)
+    {}
+
+  void best( const PerformanceData & rhs )
+  {
+    mesh_time = std::min( mesh_time , rhs.mesh_time );
+    graph_time = std::min( graph_time , rhs.graph_time );
+    elem_time = std::min( elem_time , rhs.elem_time );
+    matrix_gather_fill_time = std::min( matrix_gather_fill_time , rhs.matrix_gather_fill_time );
+    matrix_boundary_condition_time = std::min( matrix_boundary_condition_time , rhs.matrix_boundary_condition_time );
+    cg_iteration_time = std::min( cg_iteration_time , rhs.cg_iteration_time );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class FixtureType >
+PerformanceData run( const typename FixtureType::FEMeshType & mesh ,
+                     const int , // global_max_x ,
+                     const int , // global_max_y ,
+                     const int global_max_z ,
+                     const bool print_sample )
+{
+  typedef Scalar                              scalar_type ;
+  typedef FixtureType                         fixture_type ;
+  typedef typename fixture_type::execution_space  execution_space;
+  //typedef typename execution_space::size_type     size_type ; // unused
+
+  typedef typename fixture_type::FEMeshType mesh_type ;
+  typedef typename fixture_type::coordinate_scalar_type coordinate_scalar_type ;
+
+  enum { ElementNodeCount = fixture_type::element_node_count };
+
+  const comm::Machine machine = mesh.parallel_data_map.machine ;
+
+  const size_t element_count = mesh.elem_node_ids.dimension_0();
+
+  const size_t iteration_limit = 200 ;
+  const double residual_tolerance = 1e-14 ;
+
+  size_t iteration_count = 0 ;
+  double residual_norm = 0 ;
+
+  PerformanceData perf_data ;
+
+  //------------------------------------
+  // Sparse linear system types:
+
+  typedef Kokkos::View< scalar_type* , execution_space >   vector_type ;
+  typedef Kokkos::CrsMatrix< scalar_type , execution_space >     matrix_type ;
+  typedef typename matrix_type::graph_type         matrix_graph_type ;
+  typedef typename matrix_type::coefficients_type  matrix_coefficients_type ;
+
+  typedef GraphFactory< matrix_graph_type , mesh_type > graph_factory ;
+
+  //------------------------------------
+  // Problem setup types:
+
+  typedef ElementComputation< scalar_type , scalar_type , execution_space > ElementFunctor ;
+  typedef DirichletBoundary< scalar_type , scalar_type , execution_space > BoundaryFunctor ;
+
+  typedef typename ElementFunctor::elem_matrices_type elem_matrices_type ;
+  typedef typename ElementFunctor::elem_vectors_type  elem_vectors_type ;
+
+  typedef GatherFill< matrix_type ,
+                      mesh_type ,
+                      elem_matrices_type ,
+                      elem_vectors_type > GatherFillFunctor ;
+
+  //------------------------------------
+
+  const scalar_type elem_coeff_K = 2 ;
+  const scalar_type elem_load_Q  = 1 ;
+
+  matrix_type linsys_matrix ;
+  vector_type linsys_rhs ;
+  vector_type linsys_solution ;
+
+  typename graph_factory::element_map_type element_map ;
+
+  Kokkos::Timer wall_clock ;
+
+  //------------------------------------
+  // Generate sparse matrix graph and element->graph map.
+
+  graph_factory::create( mesh , linsys_matrix.graph , element_map );
+
+  execution_space::fence();
+  perf_data.graph_time = comm::max( machine , wall_clock.seconds() );
+
+  //------------------------------------
+  // Allocate linear system coefficients and rhs:
+
+  const size_t local_owned_length =
+    linsys_matrix.graph.row_map.dimension_0() - 1 ;
+
+  linsys_matrix.coefficients =
+    matrix_coefficients_type( "coeff" , linsys_matrix.graph.entries.dimension_0() );
+
+  linsys_rhs      = vector_type( "rhs" , local_owned_length );
+  linsys_solution = vector_type( "solution" , local_owned_length );
+
+  //------------------------------------
+  // Fill linear system
+  {
+    elem_matrices_type elem_matrices ;
+    elem_vectors_type  elem_vectors ;
+
+    if ( element_count ) {
+      elem_matrices = elem_matrices_type( std::string("elem_matrices"), element_count );
+      elem_vectors  = elem_vectors_type ( std::string("elem_vectors"), element_count );
+    }
+
+    //------------------------------------
+    // Compute element matrices and vectors:
+
+    wall_clock.reset();
+
+    ElementFunctor::apply( mesh ,
+                           elem_matrices , elem_vectors ,
+                           elem_coeff_K , elem_load_Q );
+
+    execution_space::fence();
+    perf_data.elem_time = comm::max( machine , wall_clock.seconds() );
+
+    //------------------------------------
+    // Fill linear system coefficients:
+
+    wall_clock.reset();
+
+    GatherFillFunctor::apply( linsys_matrix , linsys_rhs ,
+               mesh , element_map , elem_matrices , elem_vectors );
+
+    execution_space::fence();
+    perf_data.matrix_gather_fill_time = comm::max( machine , wall_clock.seconds() );
+
+    // Apply boundary conditions:
+
+    wall_clock.reset();
+
+    BoundaryFunctor::apply( linsys_matrix , linsys_rhs , mesh ,
+                            0 , global_max_z , 0 , global_max_z );
+
+    execution_space::fence();
+    perf_data.matrix_boundary_condition_time = comm::max( machine , wall_clock.seconds() );
+  }
+
+  //------------------------------------
+  // Solve linear sytem
+
+  cgsolve( mesh.parallel_data_map ,
+           linsys_matrix , linsys_rhs , linsys_solution ,
+           iteration_count , residual_norm ,
+           perf_data.cg_iteration_time ,
+           iteration_limit , residual_tolerance );
+
+  //------------------------------------
+
+  if ( print_sample ) {
+
+    typename mesh_type::node_coords_type::HostMirror coords_h =
+      Kokkos::create_mirror( mesh.node_coords );
+
+    typename vector_type::HostMirror X_h =
+      Kokkos::create_mirror( linsys_solution );
+
+    Kokkos::deep_copy( coords_h , mesh.node_coords );
+    Kokkos::deep_copy( X_h , linsys_solution );
+
+    for ( size_t i = 0 ; i < mesh.parallel_data_map.count_owned ; ++i ) {
+      const coordinate_scalar_type x = coords_h(i,0);
+      const coordinate_scalar_type y = coords_h(i,1);
+      const coordinate_scalar_type z = coords_h(i,2);
+
+      if ( x <= 0 && y <= 0 ) {
+        std::cout << "  node( " << x << " " << y << " " << z << " ) = "
+                  << X_h(i) << std::endl ;
+      }
+    }
+  }
+
+  return perf_data ;
+}
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class Device >
+void driver( const char * const label ,
+             comm::Machine machine ,
+             const int gang_count ,
+             const int elem_count_beg ,
+             const int elem_count_end ,
+             const int runs )
+{
+  typedef Scalar              scalar_type ;
+  typedef Device              execution_space ;
+  typedef double              coordinate_scalar_type ;
+  typedef FixtureElementHex8  fixture_element_type ;
+
+  typedef BoxMeshFixture< coordinate_scalar_type ,
+                          execution_space ,
+                          fixture_element_type > fixture_type ;
+
+  typedef typename fixture_type::FEMeshType mesh_type ;
+
+  const size_t proc_count = comm::size( machine );
+  const size_t proc_rank  = comm::rank( machine );
+
+  if ( elem_count_beg == 0 || elem_count_end == 0 || runs == 0 ) return ;
+
+  if ( comm::rank( machine ) == 0 ) {
+    std::cout << std::endl ;
+    std::cout << "\"Kokkos::HybridFE::Implicit " << label << "\"" << std::endl;
+    std::cout << "\"Size\" ,  \"Graphing\" , \"Element\" , \"Fill\" ,   \"Boundary\" ,  \"CG-Iter\"" << std::endl
+              << "\"elems\" , \"millisec\" , \"millisec\" , \"millisec\" , \"millisec\" , \"millisec\"" << std::endl ;
+  }
+
+  for(int i = elem_count_beg ; i < elem_count_end ; i *= 2 )
+  {
+    const int ix = std::max( 1 , (int) cbrt( ((double) i) / 2.0 ) );
+    const int iy = ix + 1 ;
+    const int iz = 2 * iy ;
+    const int n  = ix * iy * iz ;
+
+    mesh_type mesh =
+      fixture_type::create( proc_count , proc_rank , gang_count ,
+                            ix , iy , iz );
+
+    mesh.parallel_data_map.machine = machine ;
+
+    PerformanceData perf_data , perf_best ;
+
+    for(int j = 0; j < runs; j++){
+
+     perf_data = run<scalar_type,fixture_type>(mesh,ix,iy,iz, false );
+
+     if( j == 0 ) {
+       perf_best = perf_data ;
+     }
+     else {
+       perf_best.best( perf_data );
+     }
+   }
+
+  if ( comm::rank( machine ) == 0 ) {
+
+     std::cout << std::setw(8) << n << " , "
+               << std::setw(10) << perf_best.graph_time * 1000 << " , "
+               << std::setw(10) << perf_best.elem_time * 1000 << " , "
+               << std::setw(10) << perf_best.matrix_gather_fill_time * 1000 << " , "
+               << std::setw(10) << perf_best.matrix_boundary_condition_time * 1000 << " , "
+               << std::setw(10) << perf_best.cg_iteration_time * 1000
+               << std::endl ;
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+
+} /* namespace Implicit */
+} /* namespace HybridFEM */
+
+
+#endif /* #ifndef HYBRIDFEM_IMPLICIT_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/ImplicitFunctors.hpp b/lib/kokkos/example/multi_fem/ImplicitFunctors.hpp
new file mode 100644
index 0000000000..9d9aa77163
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/ImplicitFunctors.hpp
@@ -0,0 +1,585 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+
+namespace HybridFEM {
+namespace Implicit {
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , unsigned Dim , unsigned N >
+struct TensorIntegration ;
+
+template<typename Scalar >
+struct TensorIntegration<Scalar,1,1> {
+  Scalar pts[1] ;
+  Scalar wts[1] ;
+
+  TensorIntegration() { pts[0] = 0 ; wts[0] = 2 ; }
+};
+
+template<typename Scalar >
+struct TensorIntegration<Scalar,1,2>
+{
+  Scalar pts[2] ;
+  Scalar wts[2] ;
+
+  TensorIntegration()
+  {
+    const Scalar x2 = 0.577350269 ;
+    pts[0] = -x2; wts[0] = 1.0;
+    pts[1] =  x2; wts[1] = 1.0;
+  }
+};
+
+template<typename Scalar >
+struct TensorIntegration<Scalar,1,3>
+{
+  Scalar pts[3] ;
+  Scalar wts[3] ;
+
+  TensorIntegration()
+  {
+    const Scalar x3 = 0.774596669 ;
+    const Scalar w1 = 0.555555556 ;
+    const Scalar w2 = 0.888888889 ;
+    pts[0] =  -x3 ;  wts[0] = w1 ;
+    pts[1] =    0 ;  wts[1] = w2 ;
+    pts[2] =   x3 ;  wts[2] = w1 ;
+  }
+};
+
+template< typename Scalar , unsigned Order >
+struct TensorIntegration<Scalar,3,Order>
+{
+  static const unsigned N = Order * Order * Order ;
+
+  Scalar pts[N][3] ;
+  Scalar wts[N];
+
+  TensorIntegration()
+  {
+    TensorIntegration<Scalar,1,Order> oneD ;
+
+    unsigned n = 0 ;
+    for ( unsigned k = 0 ; k < Order ; ++k ) {
+    for ( unsigned j = 0 ; j < Order ; ++j ) {
+    for ( unsigned i = 0 ; i < Order ; ++i , ++n ) {
+      pts[n][0] = oneD.pts[i] ;
+      pts[n][1] = oneD.pts[j] ;
+      pts[n][2] = oneD.pts[k] ;
+      wts[n] = oneD.wts[i] * oneD.wts[j] * oneD.wts[k] ;
+    }}}
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar >
+struct ShapeFunctionEvaluation {
+
+  static const unsigned FunctionCount = 8 ;
+  static const unsigned SpatialDimension = 3 ;
+  static const unsigned IntegrationOrder = 2 ;
+
+  typedef TensorIntegration< Scalar , SpatialDimension , IntegrationOrder > 
+    TensorIntegrationType ;
+
+  static const unsigned PointCount = TensorIntegrationType::N ;
+
+  Scalar value   [ PointCount ][ FunctionCount ] ;
+  Scalar gradient[ PointCount ][ FunctionCount * SpatialDimension ];
+  Scalar weight  [ PointCount ];
+
+  ShapeFunctionEvaluation()
+  {
+    const TensorIntegration< Scalar , SpatialDimension , IntegrationOrder > 
+      integration ;
+
+    const Scalar ONE8TH = 0.125 ;
+
+    for ( unsigned i = 0 ; i < PointCount ; ++i ) {
+
+      const Scalar u = 1.0 - integration.pts[i][0];
+      const Scalar v = 1.0 - integration.pts[i][1];
+      const Scalar w = 1.0 - integration.pts[i][2];
+
+      const Scalar up1 = 1.0 + integration.pts[i][0];
+      const Scalar vp1 = 1.0 + integration.pts[i][1];
+      const Scalar wp1 = 1.0 + integration.pts[i][2];
+
+      weight[i] = integration.wts[i] ;
+
+      // Vaues:
+      value[i][0] = ONE8TH *   u *   v *  w ;
+      value[i][1] = ONE8TH * up1 *   v *  w ;
+      value[i][2] = ONE8TH * up1 * vp1 *  w ;
+      value[i][3] = ONE8TH *   u * vp1 *  w ;
+
+      value[i][4] = ONE8TH *   u *   v *  wp1 ;
+      value[i][5] = ONE8TH * up1 *   v *  wp1 ;
+      value[i][6] = ONE8TH * up1 * vp1 *  wp1 ;
+      value[i][7] = ONE8TH *   u * vp1 *  wp1 ;
+
+      //fn 0 = u * v * w
+      gradient[i][ 0] = ONE8TH * -1  *  v  *  w  ;
+      gradient[i][ 1] = ONE8TH *  u  * -1  *  w  ;
+      gradient[i][ 2] = ONE8TH *  u  *  v  * -1  ;
+
+      //fn 1 = up1 * v * w
+      gradient[i][ 3] = ONE8TH *  1  *  v  *  w  ;
+      gradient[i][ 4] = ONE8TH * up1 * -1  *  w  ;
+      gradient[i][ 5] = ONE8TH * up1 *  v  * -1  ;
+
+      //fn 2 = up1 * vp1 * w
+      gradient[i][ 6] = ONE8TH *  1  * vp1 *  w ;
+      gradient[i][ 7] = ONE8TH * up1 *  1  *  w ;
+      gradient[i][ 8] = ONE8TH * up1 * vp1 * -1 ;
+
+      //fn 3 = u * vp1 * w
+      gradient[i][ 9] = ONE8TH * -1 * vp1 *  w ;
+      gradient[i][10] = ONE8TH *  u *  1  *  w ;
+      gradient[i][11] = ONE8TH *  u * vp1 * -1 ;
+
+      //fn 4 = u * v * wp1
+      gradient[i][12] = ONE8TH * -1  *  v  * wp1 ;
+      gradient[i][13] = ONE8TH *  u  * -1  * wp1 ;
+      gradient[i][14] = ONE8TH *  u  *  v  *  1  ;
+
+      //fn 5 = up1 * v * wp1
+      gradient[i][15] = ONE8TH *  1  *  v  * wp1 ;
+      gradient[i][16] = ONE8TH * up1 * -1  * wp1 ;
+      gradient[i][17] = ONE8TH * up1 *  v  *  1  ;
+
+      //fn 6 = up1 * vp1 * wp1
+      gradient[i][18] = ONE8TH *  1  * vp1 * wp1 ;
+      gradient[i][19] = ONE8TH * up1 *  1  * wp1 ;
+      gradient[i][20] = ONE8TH * up1 * vp1 *  1 ;
+
+      //fn 7 = u * vp1 * wp1
+      gradient[i][21] = ONE8TH * -1 * vp1 * wp1 ;
+      gradient[i][22] = ONE8TH *  u *  1  * wp1 ;
+      gradient[i][23] = ONE8TH *  u * vp1 *  1 ;
+    }
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< typename ScalarType , typename ScalarCoordType , class DeviceType >
+struct ElementComputation
+{
+  typedef DeviceType     execution_space;
+  typedef ScalarType              scalar_type ;
+  typedef typename execution_space::size_type  size_type ;
+
+  static const size_type ElementNodeCount = 8 ;
+
+  typedef FEMesh< ScalarCoordType , ElementNodeCount , execution_space > mesh_type ;
+  typedef Kokkos::View< scalar_type[][ElementNodeCount][ElementNodeCount] , execution_space > elem_matrices_type ;
+  typedef Kokkos::View< scalar_type[][ElementNodeCount] , execution_space > elem_vectors_type ;
+
+  typedef ShapeFunctionEvaluation< scalar_type > shape_function_data ;
+
+  static const unsigned SpatialDim    = shape_function_data::SpatialDimension ;
+  static const unsigned FunctionCount = shape_function_data::FunctionCount ;
+
+private:
+
+  const shape_function_data               shape_eval ;
+  typename mesh_type::elem_node_ids_type  elem_node_ids ;
+  typename mesh_type::node_coords_type    node_coords ;
+  elem_matrices_type                      element_matrices ;
+  elem_vectors_type                       element_vectors ;
+  scalar_type                             coeff_K ;
+  scalar_type                             coeff_Q ;
+
+  ElementComputation( const mesh_type   & arg_mesh ,
+                      const elem_matrices_type  & arg_element_matrices , 
+                      const elem_vectors_type   & arg_element_vectors ,
+                      const scalar_type   arg_coeff_K ,
+                      const scalar_type   arg_coeff_Q )
+  : shape_eval()
+  , elem_node_ids( arg_mesh.elem_node_ids )
+  , node_coords(   arg_mesh.node_coords )
+  , element_matrices( arg_element_matrices )
+  , element_vectors( arg_element_vectors )
+  , coeff_K( arg_coeff_K )
+  , coeff_Q( arg_coeff_Q )
+  {}
+
+public:
+
+  static void apply( const mesh_type  & mesh ,
+                     const elem_matrices_type & elem_matrices ,
+                     const elem_vectors_type  & elem_vectors ,
+                     const scalar_type  elem_coeff_K ,
+                     const scalar_type  elem_coeff_Q )
+  {
+    ElementComputation comp( mesh , elem_matrices , elem_vectors , elem_coeff_K , elem_coeff_Q );
+    const size_t elem_count = mesh.elem_node_ids.dimension_0();
+
+    parallel_for( elem_count , comp );
+  }
+
+  //------------------------------------
+
+  static const unsigned FLOPS_jacobian =
+    FunctionCount * SpatialDim * SpatialDim * 2 ;
+
+  KOKKOS_INLINE_FUNCTION
+  void jacobian( const ScalarCoordType * x, 
+                 const ScalarCoordType * y, 
+                 const ScalarCoordType * z, 
+                 const scalar_type * grad_vals, 
+                 scalar_type * J) const
+  {
+    int i_grad = 0 ;
+
+    for( unsigned i = 0; i < ElementNodeCount ; ++i , i_grad += SpatialDim ) {
+      const scalar_type g0 = grad_vals[ i_grad ];
+      const scalar_type g1 = grad_vals[ i_grad + 1 ];
+      const scalar_type g2 = grad_vals[ i_grad + 2 ];
+      const scalar_type x0 = x[i] ;
+      const scalar_type x1 = y[i] ;
+      const scalar_type x2 = z[i] ;
+
+      J[0] += g0 * x0 ;
+      J[1] += g0 * x1 ;
+      J[2] += g0 * x2 ;
+
+      J[3] += g1 * x0 ;
+      J[4] += g1 * x1 ;
+      J[5] += g1 * x2 ;
+
+      J[6] += g2 * x0 ;
+      J[7] += g2 * x1 ;
+      J[8] += g2 * x2 ;
+    }
+  }
+
+  //------------------------------------
+
+  static const unsigned FLOPS_inverse_and_det = 46 ;
+
+  KOKKOS_INLINE_FUNCTION
+  scalar_type inverse_and_determinant3x3( scalar_type * const J ) const
+  {
+    const scalar_type J00 = J[0];
+    const scalar_type J01 = J[1];
+    const scalar_type J02 = J[2];
+
+    const scalar_type J10 = J[3];
+    const scalar_type J11 = J[4];
+    const scalar_type J12 = J[5];
+
+    const scalar_type J20 = J[6];
+    const scalar_type J21 = J[7];
+    const scalar_type J22 = J[8];
+
+    const scalar_type term0 = J22*J11 - J21*J12;
+    const scalar_type term1 = J22*J01 - J21*J02;
+    const scalar_type term2 = J12*J01 - J11*J02;
+
+    const scalar_type detJ = J00*term0 - J10*term1 + J20*term2;
+    const scalar_type inv_detJ = 1.0/detJ;
+
+    J[0] =  term0*inv_detJ;
+    J[1] = -term1*inv_detJ;
+    J[2] =  term2*inv_detJ;
+
+    J[3] = -(J22*J10 - J20*J12)*inv_detJ;
+    J[4] =  (J22*J00 - J20*J02)*inv_detJ;
+    J[5] = -(J12*J00 - J10*J02)*inv_detJ;
+
+    J[6] =  (J21*J10 - J20*J11)*inv_detJ;
+    J[7] = -(J21*J00 - J20*J01)*inv_detJ;
+    J[8] =  (J11*J00 - J10*J01)*inv_detJ;
+
+    return detJ ;
+  }
+
+  //------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void matTransMat3x3_X_3xn( const scalar_type * A, int n,
+                             const scalar_type * B,
+                             scalar_type * C ) const
+  {
+    //A is 3x3, B is 3xn. So C is also 3xn.
+    //A,B,C are all assumed to be ordered such that columns are contiguous.
+
+    scalar_type * Cj = C;
+    const scalar_type * Bj = B;
+
+    for(int j=0; j<n; ++j) {
+      Cj[0] = A[0]*Bj[0] + A[1]*Bj[1] + A[2]*Bj[2];
+      Cj[1] = A[3]*Bj[0] + A[4]*Bj[1] + A[5]*Bj[2];
+      Cj[2] = A[6]*Bj[0] + A[7]*Bj[1] + A[8]*Bj[2];
+      Bj += 3;
+      Cj += 3;
+    }
+
+  }
+  //------------------------------------
+
+  static const unsigned FLOPS_contributeDiffusionMatrix = FunctionCount * ( 3 * 5 + FunctionCount * 7 ) ;
+
+  KOKKOS_INLINE_FUNCTION
+  void contributeDiffusionMatrix(
+    const scalar_type weight ,
+    const scalar_type grad_vals[] ,
+    const scalar_type invJ[] ,
+    scalar_type elem_mat[][8] ) const
+  {
+    scalar_type dpsidx[8], dpsidy[8], dpsidz[8];
+
+    int i_grad = 0 ;
+    for( unsigned i = 0; i < FunctionCount ; ++i , i_grad += 3 ) {
+      const scalar_type g0 = grad_vals[i_grad+0];
+      const scalar_type g1 = grad_vals[i_grad+1];
+      const scalar_type g2 = grad_vals[i_grad+2];
+
+      dpsidx[i] = g0 * invJ[0] + g1 * invJ[1] + g2 * invJ[2];
+      dpsidy[i] = g0 * invJ[3] + g1 * invJ[4] + g2 * invJ[5];
+      dpsidz[i] = g0 * invJ[6] + g1 * invJ[7] + g2 * invJ[8];
+    }
+
+    for( unsigned m = 0; m < FunctionCount; m++) {
+      for( unsigned n = 0; n < FunctionCount; n++) {
+
+        elem_mat[m][n] += weight * 
+          ((dpsidx[m] * dpsidx[n]) + 
+           (dpsidy[m] * dpsidy[n]) +
+           (dpsidz[m] * dpsidz[n]));            
+      }
+    }
+  }
+
+  //------------------------------------
+
+  static const unsigned FLOPS_contributeSourceVector = FunctionCount * 2 ;
+
+  KOKKOS_INLINE_FUNCTION
+  void contributeSourceVector( const scalar_type term ,
+                               const scalar_type psi[] ,
+                               scalar_type elem_vec[] ) const
+  {
+     for( unsigned i=0; i< FunctionCount ; ++i) {
+       elem_vec[i] += psi[i] * term ;
+     }
+  }
+
+
+  static const unsigned FLOPS_operator =
+           shape_function_data::PointCount * ( 3
+             + FLOPS_jacobian
+             + FLOPS_inverse_and_det
+             + FLOPS_contributeDiffusionMatrix
+             + FLOPS_contributeSourceVector ) ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( int ielem )const {
+
+    scalar_type elem_vec[8] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 };
+    scalar_type elem_mat[8][8] =
+      { { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
+        { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
+        { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
+        { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
+        { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
+        { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
+        { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } ,
+        { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 } };
+
+    ScalarCoordType x[8], y[8], z[8];
+
+    for ( int i = 0 ; i < 8 ; ++i ) {
+      const int node_index = elem_node_ids( ielem , i );
+      x[i] = node_coords( node_index , 0 );
+      y[i] = node_coords( node_index , 1 );
+      z[i] = node_coords( node_index , 2 );
+    }
+
+    // This loop could be parallelized; however,
+    // it would require additional per-thread temporaries
+    // of 'elem_vec' and 'elem_mat' which would
+    // consume more local memory and have to be reduced.
+
+    for ( unsigned i = 0 ; i < shape_function_data::PointCount ; ++i ) {
+
+      scalar_type J[SpatialDim*SpatialDim] = { 0, 0, 0,  0, 0, 0,  0, 0, 0 };
+
+      jacobian( x, y, z, shape_eval.gradient[i] , J );
+
+      // Overwrite J with its inverse to save scratch memory space.
+      const scalar_type detJ_w   = shape_eval.weight[i] * inverse_and_determinant3x3(J);
+      const scalar_type k_detJ_w = coeff_K * detJ_w ;
+      const scalar_type Q_detJ_w = coeff_Q * detJ_w ;
+
+      contributeDiffusionMatrix( k_detJ_w , shape_eval.gradient[i] , J , elem_mat );
+
+      contributeSourceVector( Q_detJ_w , shape_eval.value[i] , elem_vec );
+    }
+
+    for( size_type i=0; i< ElementNodeCount ; ++i) {
+      element_vectors(ielem, i) = elem_vec[i] ;
+    }
+
+    for( size_type i = 0; i < ElementNodeCount ; i++){
+      for( size_type j = 0; j < ElementNodeCount ; j++){
+        element_matrices(ielem, i, j) = elem_mat[i][j] ;
+      }
+    }
+  }
+}; /* ElementComputation */
+
+//----------------------------------------------------------------------------
+
+template< typename ScalarType , typename ScalarCoordType , class DeviceType >
+struct DirichletBoundary
+{
+  typedef DeviceType     execution_space;
+  typedef typename execution_space::size_type  size_type ;
+
+  static const size_type ElementNodeCount = 8 ;
+
+  typedef Kokkos::CrsMatrix< ScalarType , execution_space >    matrix_type ;
+  typedef Kokkos::View< ScalarType[] , execution_space >  vector_type ;
+
+  typedef FEMesh< ScalarCoordType , ElementNodeCount , execution_space > mesh_type ;
+
+  typename mesh_type::node_coords_type node_coords ;
+  matrix_type     matrix ;
+  vector_type     rhs ;
+  ScalarCoordType bc_lower_z ;
+  ScalarCoordType bc_upper_z ;
+  ScalarType      bc_lower_value ;
+  ScalarType      bc_upper_value ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type inode ) const
+  {
+    //  Apply a dirichlet boundary condition to 'irow'
+    //  to maintain the symmetry of the original 
+    //  global stiffness matrix, zero out the columns
+    //  that correspond to boundary conditions, and
+    //  adjust the load vector accordingly
+
+    const size_type iBeg = matrix.graph.row_map[inode];
+    const size_type iEnd = matrix.graph.row_map[inode+1];
+
+    const ScalarCoordType z = node_coords(inode,2);
+    const bool bc_lower = z <= bc_lower_z ;
+    const bool bc_upper = bc_upper_z <= z ;
+
+    if ( bc_lower || bc_upper ) {
+      const ScalarType bc_value = bc_lower ? bc_lower_value
+                                           : bc_upper_value ;
+
+      rhs(inode) = bc_value ; //  set the rhs vector
+
+      //  zero each value on the row, and leave a one
+      //  on the diagonal
+
+      for( size_type i = iBeg ; i < iEnd ; i++) {
+        matrix.coefficients(i) =
+          (int) inode == matrix.graph.entries(i) ? 1 : 0 ;
+      }
+    }
+    else {
+      //  Find any columns that are boundary conditions.
+      //  Clear them and adjust the load vector
+
+      for( size_type i = iBeg ; i < iEnd ; i++ ) {
+        const size_type cnode = matrix.graph.entries(i) ;
+
+        const ScalarCoordType zc = node_coords(cnode,2);
+        const bool c_bc_lower = zc <= bc_lower_z ;
+        const bool c_bc_upper = bc_upper_z <= zc ;
+
+        if ( c_bc_lower || c_bc_upper ) {
+
+          const ScalarType c_bc_value = c_bc_lower ? bc_lower_value
+                                                   : bc_upper_value ;
+
+          rhs( inode ) -= c_bc_value * matrix.coefficients(i);
+
+          matrix.coefficients(i) = 0 ;
+        }
+      }
+    }
+  }
+
+
+  static void apply( const matrix_type & linsys_matrix ,
+                     const vector_type & linsys_rhs ,
+                     const mesh_type   & mesh ,
+                     const ScalarCoordType  bc_lower_z ,
+                     const ScalarCoordType  bc_upper_z ,
+                     const ScalarType       bc_lower_value ,
+                     const ScalarType       bc_upper_value )
+  {
+    const size_t row_count = linsys_matrix.graph.row_map.dimension_0() - 1 ;
+    DirichletBoundary op ;
+    op.node_coords    = mesh.node_coords ;
+    op.matrix         = linsys_matrix ;
+    op.rhs            = linsys_rhs ;
+    op.bc_lower_z     = bc_lower_z ;
+    op.bc_upper_z     = bc_upper_z ;
+    op.bc_lower_value = bc_lower_value ;
+    op.bc_upper_value = bc_upper_value ;
+    parallel_for( row_count , op );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+} /* namespace Implicit */
+} /* namespace HybridFEM */
+
diff --git a/lib/kokkos/example/multi_fem/LinAlgBLAS.hpp b/lib/kokkos/example/multi_fem/LinAlgBLAS.hpp
new file mode 100644
index 0000000000..2478fa9aed
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/LinAlgBLAS.hpp
@@ -0,0 +1,567 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef USESCASES_LINALG_BLAS_HPP
+#define USESCASES_LINALG_BLAS_HPP
+
+#include <cmath>
+#include <utility>
+#include <ParallelComm.hpp>
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< class Scalar , class Layout , class DeviceType > struct Dot ;
+
+template< class Scalar , class Layout , class DeviceType > struct Dot1 ;
+
+template< typename ScalarA ,
+          typename ScalarY ,
+          class Layout , class Device >
+struct Scale ;
+
+template< typename ScalarA ,
+          typename ScalarY ,
+          class Layout , class Device >
+struct Fill ;
+
+template< typename ScalarA ,
+          typename ScalarX ,
+          typename ScalarY ,
+          class Layout , class Device >
+struct AXPY ;
+
+template< typename ScalarX ,
+          typename ScalarB ,
+          typename ScalarY ,
+          class Layout , class Device >
+struct XPBY ;
+
+template< typename ScalarA ,
+          typename ScalarX ,
+          typename ScalarB ,
+          typename ScalarY ,
+          typename ScalarW ,
+          class Layout , class Device >
+struct WAXPBY ;
+
+}
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_MPI )
+
+template< typename ScalarX /* Allow mix of const and non-const */ ,
+          typename ScalarY /* Allow mix of const and non-const */ ,
+          class L , class D ,
+          class MX /* Allow any management type */ ,
+          class MY /* Allow any management type */ >
+inline
+double dot( const size_t n ,
+            const View< ScalarX * , L , D , MX > & x ,
+            const View< ScalarY * , L , D , MY > & y ,
+            comm::Machine machine )
+{
+  double global_result = 0 ;
+  double local_result = 0 ;
+
+  Impl::Dot< ScalarX , L , D >( n , x , y , local_result );
+
+  MPI_Allreduce( & local_result , & global_result , 1 ,
+                 MPI_DOUBLE , MPI_SUM , machine.mpi_comm );
+
+  return global_result ;
+}
+
+#else
+
+template< typename ScalarX /* Allow mix of const and non-const */ ,
+          typename ScalarY /* Allow mix of const and non-const */ ,
+          class L , class D ,
+          class MX /* Allow any management type */ ,
+          class MY /* Allow any management type */ >
+inline
+double dot( const size_t n ,
+            const View< ScalarX * , L , D , MX > & x ,
+            const View< ScalarY * , L , D , MY > & y ,
+            comm::Machine )
+{
+  double global_result = 0 ;
+
+  Impl::Dot< ScalarX , L , D >( n , x , y , global_result );
+
+  return global_result ;
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_MPI )
+
+template< typename ScalarX /* Allow mix of const and non-const */ ,
+          class L , class D ,
+          class MX /* Allow any management type */ >
+inline
+double dot( const size_t n ,
+            const View< ScalarX * , L , D , MX > & x ,
+            comm::Machine machine )
+{
+  double global_result = 0 ;
+  double local_result = 0 ;
+
+  Impl::Dot1< ScalarX , L , D >( n , x , local_result );
+
+  MPI_Allreduce( & local_result , & global_result , 1 ,
+                 MPI_DOUBLE , MPI_SUM , machine.mpi_comm );
+
+  return global_result ;
+}
+
+#else
+
+template< typename ScalarX /* Allow mix of const and non-const */ ,
+          class L , class D ,
+          class MX /* Allow any management type */ >
+inline
+double dot( const size_t n ,
+            const View< ScalarX * , L , D , MX > & x ,
+            comm::Machine )
+{
+  double global_result = 0 ;
+
+  Impl::Dot1< ScalarX , L , D >( n , x , global_result );
+
+  return global_result ;
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+
+template< typename ScalarX /* Allow mix of const and non-const */ ,
+          class L , class D ,
+          class MX /* Allow any management type */ >
+inline
+double norm2( const size_t n ,
+              const View< ScalarX * , L , D , MX > & x ,
+              comm::Machine machine )
+{
+  return std::sqrt( dot( n , x , machine ) );
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ScalarA ,
+          typename ScalarX ,
+          class L ,
+          class D ,
+          class MX >
+void scale( const size_t n ,
+            const ScalarA & alpha ,
+            const View< ScalarX * , L , D , MX > & x )
+{
+  Impl::Scale< ScalarA , ScalarX , L , D >( n , alpha , x );
+}
+
+template< typename ScalarA ,
+          typename ScalarX ,
+          class L ,
+          class D ,
+          class MX >
+void fill( const size_t n ,
+           const ScalarA & alpha ,
+           const View< ScalarX * , L , D , MX > & x )
+{
+  Impl::Fill< ScalarA , ScalarX , L , D >( n , alpha , x );
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ScalarA ,
+          typename ScalarX ,
+          typename ScalarY ,
+          class L ,
+          class D ,
+          class MX ,
+          class MY >
+void axpy( const size_t n ,
+           const ScalarA & alpha ,
+           const View< ScalarX *, L , D , MX > & x ,
+           const View< ScalarY *, L , D , MY > & y )
+{
+  Impl::AXPY< ScalarA, ScalarX, ScalarY , L , D >( n, alpha, x, y );
+}
+
+//----------------------------------------------------------------------------
+
+template< typename ScalarX ,
+          typename ScalarB ,
+          typename ScalarY ,
+          class L ,
+          class D ,
+          class MX ,
+          class MY >
+void xpby( const size_t n ,
+           const View< ScalarX *, L , D , MX > & x ,
+           const ScalarB & beta ,
+           const View< ScalarY *, L , D , MY > & y )
+{
+  Impl::XPBY< ScalarX, ScalarB, ScalarY , L , D >( n, x, beta, y );
+}
+
+//----------------------------------------------------------------------------
+// w = alpha * x + beta * y
+
+template< typename ScalarA ,
+          typename ScalarX ,
+          typename ScalarB ,
+          typename ScalarY ,
+          typename ScalarW ,
+          class L , class D ,
+          class MX , class MY , class MW >
+void waxpby( const size_t n ,
+             const ScalarA & alpha ,
+             const View< ScalarX * , L , D , MX > & x ,
+             const ScalarB & beta ,
+             const View< ScalarY * , L , D , MY > & y ,
+             const View< ScalarW * , L , D , MW > & w )
+{
+  Impl::WAXPBY<ScalarA,ScalarX,ScalarB,ScalarY,ScalarW,L,D>
+    ( n , alpha , x , beta , y , w );
+}
+
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< typename Scalar , class L , class D >
+struct Dot
+{
+private:
+
+  typedef View< const Scalar*, L, D, MemoryUnmanaged >  vector_const_type ;
+
+  const vector_const_type x ;
+  const vector_const_type y ;
+
+public:
+
+  typedef typename vector_const_type::execution_space  execution_space ; // Manycore device
+  typedef double      value_type ;  // Reduction value
+
+  template< class ArgX , class ArgY >
+  inline
+  Dot( const size_t n , const ArgX & arg_x , const ArgY & arg_y , double & result )
+    : x( arg_x ), y( arg_y )
+  {
+    parallel_reduce( n , *this , result );
+  }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const iType & i , value_type & update ) const
+  { update += x(i) * y(i); }
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & source )
+  { update += source;    }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+  { update = 0 ; }
+}; // Dot
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class L , class D >
+struct Dot1
+{
+private:
+
+  typedef View< const Scalar*, L, D , MemoryUnmanaged >  vector_const_type ;
+
+  const vector_const_type x ;
+
+public:
+
+  typedef typename vector_const_type::execution_space  execution_space ; // Manycore device
+  typedef double      value_type ;  // Reduction value
+
+  template< class ArgX >
+  inline
+  Dot1( const size_t n , const ArgX & arg_x , double & result )
+    : x( arg_x )
+  {
+    parallel_reduce( n , *this , result );
+  }
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const iType & i , value_type & update ) const
+  { update += x(i) * x(i) ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & source )
+  { update += source ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+  { update = 0 ; }
+}; // Dot
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+template < typename ScalarA ,
+           typename ScalarX ,
+           typename ScalarB ,
+           typename ScalarY ,
+           typename ScalarW ,
+           class L , class D >
+struct WAXPBY
+{
+private:
+
+  typedef View<       ScalarW *, L , D , MemoryUnmanaged > ViewW ;
+  typedef View< const ScalarX *, L , D , MemoryUnmanaged > ViewX ;
+  typedef View< const ScalarY *, L , D , MemoryUnmanaged > ViewY ;
+
+  const ViewW    w ;
+  const ViewX    x ;
+  const ViewY    y ;
+  const ScalarA  alpha ;
+  const ScalarB  beta ;
+
+public:
+
+  typedef typename ViewW::execution_space  execution_space ;
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const iType inode ) const
+  {
+    w(inode) = alpha * x(inode) + beta * y(inode);
+  }
+
+  template< class ArgX , class ArgY , class ArgW >
+  inline
+  WAXPBY( const size_t  n ,
+          const ScalarA & arg_alpha ,
+          const ArgX    & arg_x ,
+          const ScalarB & arg_beta ,
+          const ArgY    & arg_y ,
+          const ArgW    & arg_w )
+    : w( arg_w ), x( arg_x ), y( arg_y )
+    , alpha( arg_alpha ), beta( arg_beta )
+  {
+    parallel_for( n , *this );
+  }
+}; // WAXPBY
+
+//----------------------------------------------------------------------------
+
+template < typename ScalarB ,
+           typename ScalarW ,
+           class L , class D >
+struct Scale
+{
+private:
+
+  typedef View< ScalarW *, L , D , MemoryUnmanaged >  ViewW ;
+  const ViewW    w ;
+  const ScalarB  beta ;
+
+public:
+
+  typedef typename ViewW::execution_space  execution_space ;
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const iType & i ) const
+  { w(i) *= beta ; }
+
+  template< class ArgW >
+  inline
+  Scale( const size_t n , const ScalarB & arg_beta , const ArgW & arg_w )
+    : w( arg_w )
+    , beta( arg_beta )
+  {
+    parallel_for( n , *this );
+  }
+};
+
+template < typename ScalarB ,
+           typename ScalarW ,
+           class L , class D >
+struct Fill
+{
+private:
+
+  typedef View< ScalarW *, L , D , MemoryUnmanaged >  ViewW ;
+  const ViewW    w ;
+  const ScalarB  beta ;
+
+public:
+
+  typedef typename ViewW::execution_space  execution_space ;
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const iType & i ) const
+  { w(i) = beta ; }
+
+  template< class ArgW >
+  inline
+  Fill( const size_t n , const ScalarB & arg_beta , const ArgW & arg_w )
+    : w( arg_w )
+    , beta( arg_beta )
+  {
+    parallel_for( n , *this );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template < typename ScalarA ,
+           typename ScalarX ,
+           typename ScalarW ,
+           class L , class D >
+struct AXPY
+{
+private:
+
+  typedef View<       ScalarW *, L , D , MemoryUnmanaged >  ViewW ;
+  typedef View< const ScalarX *, L , D , MemoryUnmanaged >  ViewX ;
+
+  const ViewW    w ;
+  const ViewX    x ;
+  const ScalarA  alpha ;
+
+public:
+
+  typedef typename ViewW::execution_space  execution_space ;
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const iType & i ) const
+  { w(i) += alpha * x(i); }
+
+  template< class ArgX , class ArgW >
+  inline
+  AXPY( const size_t  n ,
+        const ScalarA & arg_alpha ,
+        const ArgX    & arg_x ,
+        const ArgW    & arg_w )
+    : w( arg_w ), x( arg_x )
+    , alpha( arg_alpha )
+  {
+    parallel_for( n , *this );
+  }
+}; // AXPY
+
+template< typename ScalarX ,
+          typename ScalarB ,
+          typename ScalarW ,
+          class L , class D >
+struct XPBY
+{
+private:
+
+  typedef View<       ScalarW *, L , D , MemoryUnmanaged >  ViewW ;
+  typedef View< const ScalarX *, L , D , MemoryUnmanaged >  ViewX ;
+
+  const ViewW    w ;
+  const ViewX    x ;
+  const ScalarB  beta ;
+
+public:
+
+  typedef typename ViewW::execution_space  execution_space ;
+
+  template< typename iType >
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const iType & i ) const
+  { w(i) = x(i) + beta * w(i); }
+
+  template< class ArgX , class ArgW >
+  inline
+  XPBY( const size_t  n ,
+        const ArgX    & arg_x ,
+        const ScalarB & arg_beta ,
+        const ArgW    & arg_w )
+    : w( arg_w ), x( arg_x )
+    , beta( arg_beta )
+  {
+    parallel_for( n , *this );
+  }
+}; // XPBY
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef USESCASES_LINALG_BLAS_HPP */
+
+
diff --git a/lib/kokkos/example/multi_fem/Makefile b/lib/kokkos/example/multi_fem/Makefile
new file mode 100644
index 0000000000..72e1768fcb
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/Makefile
@@ -0,0 +1,53 @@
+KOKKOS_PATH ?= ../..
+
+MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
+SRC_DIR := $(dir $(MAKEFILE_PATH))
+
+SRC = $(wildcard $(SRC_DIR)/*.cpp)
+OBJ = $(SRC:$(SRC_DIR)/%.cpp=%.o)
+
+#SRC = $(wildcard *.cpp)
+#OBJ = $(SRC:%.cpp=%.o)
+
+default: build
+	echo "Start Build"
+
+# use installed Makefile.kokkos
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = $(NVCC_WRAPPER)
+CXXFLAGS = -I$(SRC_DIR) -I$(CUDA_PATH) -O3
+LINK = $(CXX)
+LINKFLAGS = -L$(CUDA_PATH)/lib64 -lcusparse
+EXE = $(addsuffix .cuda, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "Cuda,OpenMP"
+#KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS =  
+EXE = $(addsuffix .host, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "OpenMP"
+#KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+LIB =
+
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: 
+	rm -f *.a *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:$(SRC_DIR)/%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
diff --git a/lib/kokkos/example/multi_fem/Nonlinear.hpp b/lib/kokkos/example/multi_fem/Nonlinear.hpp
new file mode 100644
index 0000000000..1d243395c2
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/Nonlinear.hpp
@@ -0,0 +1,573 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef HYBRIDFEM_NONLINEAR_HPP
+#define HYBRIDFEM_NONLINEAR_HPP
+
+#include <utility>
+#include <iostream>
+#include <iomanip>
+
+#include <Kokkos_Core.hpp>
+#include <SparseLinearSystem.hpp>
+#include <SparseLinearSystemFill.hpp>
+#include <NonlinearFunctors.hpp>
+
+#include <FEMesh.hpp>
+#include <HexElement.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace HybridFEM {
+namespace Nonlinear {
+
+struct PerformanceData {
+  double mesh_time ;
+  double graph_time ;
+  double elem_time ;
+  double matrix_gather_fill_time ;
+  double matrix_boundary_condition_time ;
+  double cg_iteration_time ;
+  size_t cg_iteration_count ;
+  size_t newton_iteration_count ;
+  double error_max ;
+
+  PerformanceData()
+    : mesh_time(0)
+    , graph_time(0)
+    , elem_time(0)
+    , matrix_gather_fill_time(0)
+    , matrix_boundary_condition_time(0)
+    , cg_iteration_time(0)
+    , cg_iteration_count(0)
+    , newton_iteration_count(0)
+    , error_max(0)
+    {}
+
+  void best( const PerformanceData & rhs )
+  {
+    mesh_time = std::min( mesh_time , rhs.mesh_time );
+    graph_time = std::min( graph_time , rhs.graph_time );
+    elem_time = std::min( elem_time , rhs.elem_time );
+    matrix_gather_fill_time = std::min( matrix_gather_fill_time , rhs.matrix_gather_fill_time );
+    matrix_boundary_condition_time = std::min( matrix_boundary_condition_time , rhs.matrix_boundary_condition_time );
+    cg_iteration_time = std::min( cg_iteration_time , rhs.cg_iteration_time );
+    cg_iteration_count = std::min( cg_iteration_count , rhs.cg_iteration_count );
+    newton_iteration_count = std::min( newton_iteration_count , rhs.newton_iteration_count );
+    error_max = std::min( error_max , rhs.error_max );
+  }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+class ManufacturedSolution {
+public:
+
+  // Manufactured solution for one dimensional nonlinear PDE
+  //
+  //  -K T_zz + T^2 = 0 ; T(zmin) = T_zmin ; T(zmax) = T_zmax
+  //
+  //  Has an analytic solution of the form:
+  //
+  //    T(z) = ( a ( z - zmin ) + b )^(-2) where K = 1 / ( 6 a^2 )
+  //
+  //  Given T_0 and T_L compute K for this analytic solution.
+  //
+  //  Two analytic solutions:
+  //
+  //    Solution with singularity:
+  //    , a( ( 1.0 / sqrt(T_zmax) + 1.0 / sqrt(T_zmin) ) / ( zmax - zmin ) )
+  //    , b( -1.0 / sqrt(T_zmin) )
+  //
+  //    Solution without singularity:
+  //    , a( ( 1.0 / sqrt(T_zmax) - 1.0 / sqrt(T_zmin) ) / ( zmax - zmin ) )
+  //    , b( 1.0 / sqrt(T_zmin) )
+
+  const double zmin ;
+  const double zmax ;
+  const double T_zmin ;
+  const double T_zmax ;
+  const double a ;
+  const double b ;
+  const double K ;
+
+  ManufacturedSolution( const double arg_zmin ,
+                        const double arg_zmax ,
+                        const double arg_T_zmin ,
+                        const double arg_T_zmax )
+    : zmin( arg_zmin )
+    , zmax( arg_zmax )
+    , T_zmin( arg_T_zmin )
+    , T_zmax( arg_T_zmax )
+    , a( ( 1.0 / sqrt(T_zmax) - 1.0 / sqrt(T_zmin) ) / ( zmax - zmin ) )
+    , b( 1.0 / sqrt(T_zmin) )
+    , K( 1.0 / ( 6.0 * a * a ) )
+    {}
+
+  double operator()( const double z ) const
+  {
+    const double tmp = a * ( z - zmin ) + b ;
+    return 1.0 / ( tmp * tmp );
+  }
+};
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class FixtureType >
+PerformanceData run( const typename FixtureType::FEMeshType & mesh ,
+                     const int , // global_max_x ,
+                     const int , // global_max_y ,
+                     const int global_max_z ,
+                     const bool print_error )
+{
+  typedef Scalar                              scalar_type ;
+  typedef FixtureType                         fixture_type ;
+  typedef typename fixture_type::execution_space  execution_space;
+  //typedef typename execution_space::size_type     size_type ; // unused
+
+  typedef typename fixture_type::FEMeshType mesh_type ;
+  typedef typename fixture_type::coordinate_scalar_type coordinate_scalar_type ;
+
+  enum { ElementNodeCount = fixture_type::element_node_count };
+
+  const comm::Machine machine = mesh.parallel_data_map.machine ;
+
+  const size_t element_count = mesh.elem_node_ids.dimension_0();
+
+  //------------------------------------
+  // The amount of nonlinearity is proportional to the ratio
+  // between T(zmax) and T(zmin).  For the manufactured solution
+  // 0 < T(zmin) and 0 < T(zmax)
+
+  const ManufacturedSolution
+    exact_solution( /* zmin */ 0 ,
+                    /* zmax */ global_max_z ,
+                    /* T(zmin) */ 1 ,
+                    /* T(zmax) */ 20 );
+
+  //-----------------------------------
+  // Convergence Criteria and perf data:
+
+  const size_t cg_iteration_limit = 200 ;
+  const double cg_tolerance = 1e-14 ;
+
+  const size_t newton_iteration_limit = 150 ;
+  const double newton_tolerance = 1e-14 ;
+
+  size_t cg_iteration_count_total = 0 ;
+  double cg_iteration_time = 0 ;
+
+  size_t newton_iteration_count = 0 ;
+  double residual_norm_init = 0 ;
+  double residual_norm = 0 ;
+
+  PerformanceData perf_data ;
+
+  //------------------------------------
+  // Sparse linear system types:
+
+  typedef Kokkos::View< scalar_type* , execution_space >     vector_type ;
+  typedef Kokkos::CrsMatrix< scalar_type , execution_space >  matrix_type ;
+  typedef typename matrix_type::graph_type                matrix_graph_type ;
+  typedef typename matrix_type::coefficients_type         matrix_coefficients_type ;
+
+  typedef GraphFactory< matrix_graph_type , mesh_type > graph_factory ;
+
+  //------------------------------------
+  // Problem setup types:
+
+  typedef ElementComputation < mesh_type , scalar_type > ElementFunctor ;
+  typedef DirichletSolution  < mesh_type , scalar_type > DirichletSolutionFunctor ;
+  typedef DirichletResidual  < mesh_type , scalar_type > DirichletResidualFunctor ;
+
+  typedef typename ElementFunctor::elem_matrices_type elem_matrices_type ;
+  typedef typename ElementFunctor::elem_vectors_type  elem_vectors_type ;
+
+  typedef GatherFill< matrix_type ,
+                      mesh_type ,
+                      elem_matrices_type ,
+                      elem_vectors_type > GatherFillFunctor ;
+
+  //------------------------------------
+
+  matrix_type jacobian ;
+  vector_type residual ;
+  vector_type delta ;
+  vector_type nodal_solution ;
+
+  typename graph_factory::element_map_type element_map ;
+
+  //------------------------------------
+  // Generate mesh and corresponding sparse matrix graph
+
+  Kokkos::Timer wall_clock ;
+
+  //------------------------------------
+  // Generate sparse matrix graph and element->graph map.
+
+  wall_clock.reset();
+
+  graph_factory::create( mesh , jacobian.graph , element_map );
+
+  execution_space::fence();
+
+  perf_data.graph_time = comm::max( machine , wall_clock.seconds() );
+
+  //------------------------------------
+  // Allocate linear system coefficients and rhs:
+
+  const size_t local_owned_length = jacobian.graph.row_map.dimension_0() - 1 ;
+  const size_t local_total_length = mesh.node_coords.dimension_0();
+
+  jacobian.coefficients =
+    matrix_coefficients_type( "jacobian_coeff" , jacobian.graph.entries.dimension_0() );
+
+  // Nonlinear residual for owned nodes:
+  residual = vector_type( "residual" , local_owned_length );
+
+  // Nonlinear solution for owned and ghosted nodes:
+  nodal_solution = vector_type( "solution" , local_total_length );
+
+  // Nonlinear solution update for owned nodes:
+  delta = vector_type( "delta" , local_owned_length );
+
+  //------------------------------------
+  // Allocation of arrays to fill the linear system
+
+  elem_matrices_type elem_matrices ; // Jacobian matrices
+  elem_vectors_type  elem_vectors ;  // Residual vectors
+
+  if ( element_count ) {
+    elem_matrices = elem_matrices_type( std::string("elem_matrices"), element_count );
+    elem_vectors = elem_vectors_type( std::string("elem_vectors"), element_count );
+  }
+
+  //------------------------------------
+  // For boundary condition set the correct values in the solution vector
+  //   The 'zmin' face is assigned to 'T_zmin'.
+  //   The 'zmax' face is assigned to 'T_zmax'.
+  //   The resulting solution is one dimensional along the 'Z' axis.
+
+  DirichletSolutionFunctor::apply( nodal_solution , mesh ,
+                                   exact_solution.zmin ,
+                                   exact_solution.zmax ,
+                                   exact_solution.T_zmin ,
+                                   exact_solution.T_zmax );
+
+  for(;;) { // Nonlinear loop
+
+#if defined( KOKKOS_HAVE_MPI )
+
+    { //------------------------------------
+      // Import off-processor nodal solution values
+      // for residual and jacobian computations
+
+      Kokkos::AsyncExchange< typename vector_type::value_type , execution_space ,
+                                  Kokkos::ParallelDataMap >
+        exchange( mesh.parallel_data_map , 1 );
+
+      Kokkos::PackArray< vector_type >
+        ::pack( exchange.buffer() ,
+                mesh.parallel_data_map.count_interior ,
+                mesh.parallel_data_map.count_send ,
+                nodal_solution );
+
+      exchange.setup();
+
+      exchange.send_receive();
+
+      Kokkos::UnpackArray< vector_type >
+        ::unpack( nodal_solution , exchange.buffer() ,
+                  mesh.parallel_data_map.count_owned ,
+                  mesh.parallel_data_map.count_receive );
+    }
+
+#endif
+
+    //------------------------------------
+    // Compute element matrices and vectors:
+
+    wall_clock.reset();
+
+    ElementFunctor( mesh ,
+                    elem_matrices ,
+                    elem_vectors ,
+                    nodal_solution ,
+                    exact_solution.K );
+
+    execution_space::fence();
+    perf_data.elem_time += comm::max( machine , wall_clock.seconds() );
+
+    //------------------------------------
+    // Fill linear system coefficients:
+
+    wall_clock.reset();
+
+    fill( jacobian.coefficients.dimension_0(), 0 , jacobian.coefficients );
+    fill( residual.dimension_0() , 0 , residual );
+
+    GatherFillFunctor::apply( jacobian ,
+                              residual ,
+                              mesh ,
+                              element_map ,
+                              elem_matrices ,
+                              elem_vectors );
+
+    execution_space::fence();
+    perf_data.matrix_gather_fill_time += comm::max( machine , wall_clock.seconds() );
+
+    // Apply boundary conditions:
+
+    wall_clock.reset();
+
+    // Updates jacobian matrix to 1 on the diagonal, zero elsewhere,
+    // and 0 in the residual due to the solution vector having the correct value
+    DirichletResidualFunctor::apply( jacobian, residual, mesh ,
+                                     exact_solution.zmin ,
+                                     exact_solution.zmax );
+
+    execution_space::fence();
+    perf_data.matrix_boundary_condition_time +=
+      comm::max( machine , wall_clock.seconds() );
+
+    //------------------------------------
+    // Has the residual converged?
+
+    residual_norm = norm2( mesh.parallel_data_map.count_owned,
+                           residual,
+                           mesh.parallel_data_map.machine );
+
+    if ( 0 == newton_iteration_count ) {
+      residual_norm_init = residual_norm ;
+    }
+
+    if ( residual_norm / residual_norm_init < newton_tolerance ) {
+      break ;
+    }
+
+    //------------------------------------
+    // Solve linear sytem
+
+    size_t cg_iteration_count = 0 ;
+    double cg_residual_norm = 0 ;
+
+    cgsolve( mesh.parallel_data_map ,
+             jacobian , residual , delta ,
+             cg_iteration_count ,
+             cg_residual_norm ,
+             cg_iteration_time ,
+             cg_iteration_limit , cg_tolerance ) ;
+
+    perf_data.cg_iteration_time += cg_iteration_time ;
+    cg_iteration_count_total += cg_iteration_count ;
+
+    // Update non-linear solution with delta...
+    // delta is : - Dx = [Jacobian]^1 * Residual which is the negative update
+    // LaTeX:
+    // \vec {x}_{n+1} = \vec {x}_{n} - ( - \Delta \vec{x}_{n} )
+    // text:
+    // x[n+1] = x[n] + Dx
+
+    axpy( mesh.parallel_data_map.count_owned ,
+          -1.0, delta, nodal_solution);
+
+    ++newton_iteration_count ;
+
+    if ( newton_iteration_limit < newton_iteration_count ) {
+      break ;
+    }
+  };
+
+  if ( newton_iteration_count ) {
+    perf_data.elem_time /= newton_iteration_count ;
+    perf_data.matrix_gather_fill_time /= newton_iteration_count ;
+    perf_data.matrix_boundary_condition_time /= newton_iteration_count ;
+  }
+
+  if ( cg_iteration_count_total ) {
+    perf_data.cg_iteration_time /= cg_iteration_count_total ;
+  }
+
+  perf_data.newton_iteration_count = newton_iteration_count ;
+  perf_data.cg_iteration_count = cg_iteration_count_total ;
+
+  //------------------------------------
+
+  {
+    // For extracting the nodal solution and its coordinates:
+
+    typename mesh_type::node_coords_type::HostMirror node_coords_host =
+      Kokkos::create_mirror( mesh.node_coords );
+
+    typename vector_type::HostMirror nodal_solution_host =
+      Kokkos::create_mirror( nodal_solution );
+
+    Kokkos::deep_copy( node_coords_host , mesh.node_coords );
+    Kokkos::deep_copy( nodal_solution_host , nodal_solution );
+
+    double tmp = 0 ;
+
+    for ( size_t i = 0 ; i < mesh.parallel_data_map.count_owned ; ++i ) {
+      const coordinate_scalar_type x = node_coords_host(i,0);
+      const coordinate_scalar_type y = node_coords_host(i,1);
+      const coordinate_scalar_type z = node_coords_host(i,2);
+
+      const double Tx = exact_solution(z);
+      const double Ts = nodal_solution_host(i);
+      const double Te = std::abs( Tx - Ts ) / std::abs( Tx );
+
+      tmp = std::max( tmp , Te );
+
+      if ( print_error && 0.02 < Te ) {
+        std::cout << "  node( " << x << " " << y << " " << z << " ) = "
+                  << Ts << " != exact_solution " << Tx
+                  << std::endl ;
+      }
+    }
+    perf_data.error_max = comm::max( machine , tmp );
+  }
+
+  return perf_data ;
+}
+
+//----------------------------------------------------------------------------
+
+template< typename Scalar , class Device , class FixtureElement >
+void driver( const char * const label ,
+             comm::Machine machine ,
+             const int gang_count ,
+             const int elem_count_beg ,
+             const int elem_count_end ,
+             const int runs )
+{
+  typedef Scalar          scalar_type ;
+  typedef Device          execution_space ;
+  typedef double          coordinate_scalar_type ;
+  typedef FixtureElement  fixture_element_type ;
+
+  typedef BoxMeshFixture< coordinate_scalar_type ,
+                          execution_space ,
+                          fixture_element_type > fixture_type ;
+
+  typedef typename fixture_type::FEMeshType mesh_type ;
+
+  const size_t proc_count = comm::size( machine );
+  const size_t proc_rank  = comm::rank( machine );
+
+  if ( elem_count_beg == 0 || elem_count_end == 0 || runs == 0 ) return ;
+
+  if ( comm::rank( machine ) == 0 ) {
+    std::cout << std::endl ;
+    std::cout << "\"Kokkos::HybridFE::Nonlinear " << label << "\"" << std::endl;
+    std::cout
+      << "\"Size\" ,  \"Size\" ,  \"Graphing\" , \"Element\" ,  \"Fill\" ,     \"Boundary\" , \"CG-Iter\" , \"CG-Iter\" ,      \"Newton-Iter\" , \"Max-node-error\""
+      << std::endl
+      << "\"elems\" , \"nodes\" , \"millisec\" , \"millisec\" , \"millisec\" , \"millisec\" , \"millisec\" , \"total-count\" , \"total-count\" , \"ratio\""
+      << std::endl ;
+  }
+
+  const bool print_sample = 0 ;
+  const double x_curve = 1.0 ;
+  const double y_curve = 1.0 ;
+  const double z_curve = 0.8 ;
+
+  for(int i = elem_count_beg ; i < elem_count_end ; i *= 2 )
+  {
+    const int ix = std::max( 1 , (int) cbrt( ((double) i) / 2.0 ) );
+    const int iy = 1 + ix ;
+    const int iz = 2 * iy ;
+    const int global_elem_count = ix * iy * iz ;
+    const int global_node_count = ( 2 * ix + 1 ) *
+                                  ( 2 * iy + 1 ) *
+                                  ( 2 * iz + 1 );
+
+    mesh_type mesh =
+      fixture_type::create( proc_count , proc_rank , gang_count ,
+                            ix , iy , iz ,
+                            x_curve , y_curve , z_curve );
+
+    mesh.parallel_data_map.machine = machine ;
+
+
+    PerformanceData perf_data , perf_best ;
+
+    for(int j = 0; j < runs; j++){
+
+      perf_data = run<scalar_type,fixture_type>(mesh,ix,iy,iz, print_sample );
+
+      if( j == 0 ) {
+        perf_best = perf_data ;
+      }
+      else {
+        perf_best.best( perf_data );
+      }
+    }
+
+    if ( comm::rank( machine ) == 0 ) {
+
+      std::cout << std::setw(8) << global_elem_count << " , "
+                << std::setw(8) << global_node_count << " , "
+                << std::setw(10) << perf_best.graph_time * 1000 << " , "
+                << std::setw(10) << perf_best.elem_time * 1000 << " , "
+                << std::setw(10) << perf_best.matrix_gather_fill_time * 1000 << " , "
+                << std::setw(10) << perf_best.matrix_boundary_condition_time * 1000 << " , "
+                << std::setw(10) << perf_best.cg_iteration_time * 1000 << " , "
+                << std::setw(7) << perf_best.cg_iteration_count << " , "
+                << std::setw(3) << perf_best.newton_iteration_count << " , "
+                << std::setw(10) << perf_best.error_max
+                << std::endl ;
+    }
+  }
+}
+
+//----------------------------------------------------------------------------
+
+} /* namespace Nonlinear */
+} /* namespace HybridFEM */
+
+
+#endif /* #ifndef HYBRIDFEM_IMPLICIT_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/NonlinearElement_Cuda.hpp b/lib/kokkos/example/multi_fem/NonlinearElement_Cuda.hpp
new file mode 100644
index 0000000000..b2adc2adab
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/NonlinearElement_Cuda.hpp
@@ -0,0 +1,390 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#include <stdio.h>
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+
+#include <Kokkos_Core.hpp>
+#include <HexElement.hpp>
+#include <FEMesh.hpp>
+
+namespace HybridFEM {
+namespace Nonlinear {
+
+template< class MeshType , typename ScalarType > struct ElementComputation ;
+
+//----------------------------------------------------------------------------
+
+template<>
+struct ElementComputation< FEMesh< double , 27 , Kokkos::Cuda > , double >
+{
+  typedef Kokkos::Cuda    execution_space ;
+
+  static const unsigned ElementNodeCount = 27 ;
+
+  typedef HexElement_Data< ElementNodeCount >                element_data_type ;
+  typedef FEMesh< double , ElementNodeCount , execution_space >  mesh_type ;
+
+  static const unsigned SpatialDim       = element_data_type::spatial_dimension ;
+  static const unsigned FunctionCount    = element_data_type::function_count ;
+  static const unsigned IntegrationCount = element_data_type::integration_count ;
+  static const unsigned TensorDim        = SpatialDim * SpatialDim ;
+
+  typedef Kokkos::View< double[][FunctionCount][FunctionCount] , execution_space > elem_matrices_type ;
+  typedef Kokkos::View< double[][FunctionCount] , execution_space > elem_vectors_type ;
+  typedef Kokkos::View< double[] , execution_space > value_vector_type ;
+
+private:
+
+  const element_data_type                       elem_data ;
+  const typename mesh_type::elem_node_ids_type  elem_node_ids ;
+  const typename mesh_type::node_coords_type    node_coords ;
+  const value_vector_type                       nodal_values ;
+  const elem_matrices_type                      element_matrices ;
+  const elem_vectors_type                       element_vectors ;
+  const float                                   coeff_K ;
+  const unsigned                                elem_count ;
+        unsigned                                invJacIndex[9][4] ;
+
+  static const unsigned j11 = 0 , j12 = 1 , j13 = 2 ,
+                        j21 = 3 , j22 = 4 , j23 = 5 ,
+                        j31 = 6 , j32 = 7 , j33 = 8 ;
+
+  // Can only handle up to 16 warps:
+  static const unsigned BlockDimX = 32 ;
+  static const unsigned BlockDimY = 7 ;
+
+  struct WorkSpace {
+    double sum[ BlockDimY ][ BlockDimX ];
+
+    double  value_at_integ[ IntegrationCount ];
+    double  gradx_at_integ[ IntegrationCount ];
+    double  grady_at_integ[ IntegrationCount ];
+    double  gradz_at_integ[ IntegrationCount ];
+
+    float  spaceJac[    BlockDimY ][ 9 ];
+    float  spaceInvJac[ BlockDimY ][ 9 ];
+
+    float  detJweight[ IntegrationCount ];
+
+    float  dpsidx[ FunctionCount ][ IntegrationCount ];
+    float  dpsidy[ FunctionCount ][ IntegrationCount ];
+    float  dpsidz[ FunctionCount ][ IntegrationCount ];
+  };
+
+public:
+
+  ElementComputation ( const mesh_type          & arg_mesh ,
+                       const elem_matrices_type & arg_element_matrices ,
+                       const elem_vectors_type  & arg_element_vectors ,
+                       const value_vector_type  & arg_nodal_values ,
+                       const float                arg_coeff_K )
+  : elem_data()
+  , elem_node_ids(    arg_mesh.elem_node_ids )
+  , node_coords(      arg_mesh.node_coords )
+  , nodal_values(     arg_nodal_values )
+  , element_matrices( arg_element_matrices )
+  , element_vectors(  arg_element_vectors )
+  , coeff_K(          arg_coeff_K )
+  , elem_count(       arg_mesh.elem_node_ids.dimension_0() )
+  {
+    const unsigned jInvJ[9][4] = 
+     { { j22 , j33 , j23 , j32 } ,
+       { j13 , j32 , j12 , j33 } ,
+       { j12 , j23 , j13 , j22 } ,
+
+       { j23 , j31 , j21 , j33 } ,
+       { j11 , j33 , j13 , j31 } ,
+       { j13 , j21 , j11 , j23 } ,
+
+       { j21 , j32 , j22 , j31 } ,
+       { j12 , j31 , j11 , j32 } ,
+       { j11 , j22 , j12 , j21 } };
+
+    for ( unsigned i = 0 ; i < 9 ; ++i ) {
+    for ( unsigned j = 0 ; j < 4 ; ++j ) {
+      invJacIndex[i][j] = jInvJ[i][j] ;
+    }
+    }
+
+    const unsigned shmem = sizeof(WorkSpace);
+    const unsigned grid_max = 65535 ;
+    const unsigned grid_count = std::min( grid_max , elem_count );
+
+    // For compute capability 2.x up to 1024 threads per block
+    const dim3 block( BlockDimX , BlockDimY , 1 );
+    const dim3 grid( grid_count , 1 , 1 );
+
+    Kokkos::Impl::CudaParallelLaunch< ElementComputation >( *this , grid , block , shmem );
+  }
+
+public:
+
+  //------------------------------------
+  // Sum among the threadIdx.x 
+
+  template< typename Type >
+  __device__ inline static
+  void sum_x( Type & result , const double value )
+  {
+    extern __shared__ WorkSpace work_data[] ;
+
+    volatile double * const base_sum =
+      & work_data->sum[ threadIdx.y ][ threadIdx.x ] ;
+
+    base_sum[ 0] = value ;
+
+    if ( threadIdx.x < 16 ) {
+      base_sum[0] += base_sum[16];
+      base_sum[0] += base_sum[ 8];
+      base_sum[0] += base_sum[ 4];
+      base_sum[0] += base_sum[ 2];
+      base_sum[0] += base_sum[ 1];
+    }
+
+    if ( 0 == threadIdx.x ) {
+      result = base_sum[0] ;
+    }
+  }
+
+  __device__ inline static
+  void sum_x_clear()
+  {
+    extern __shared__ WorkSpace work_data[] ;
+
+    work_data->sum[ threadIdx.y ][ threadIdx.x ] = 0 ;
+  }
+
+  //------------------------------------
+  //------------------------------------
+
+  __device__ inline
+  void evaluateFunctions( const unsigned ielem ) const
+  {
+    extern __shared__ WorkSpace work_data[] ;
+
+    // Each warp (threadIdx.y) computes an integration point
+    // Each thread is responsible for a node / function.
+
+    const unsigned iFunc = threadIdx.x ;
+    const bool     hasFunc = iFunc < FunctionCount ;
+
+    //------------------------------------
+    // Each warp gathers a different variable into 'elem_mat' shared memory.
+
+    if ( hasFunc ) {
+
+      const unsigned node = elem_node_ids( ielem , iFunc );
+
+      for ( unsigned iy = threadIdx.y ; iy < 4 ; iy += blockDim.y ) {
+      switch( iy ) {
+      case 0 : work_data->sum[0][iFunc] = node_coords(node,0); break ;
+      case 1 : work_data->sum[1][iFunc] = node_coords(node,1); break ;
+      case 2 : work_data->sum[2][iFunc] = node_coords(node,2); break ;
+      case 3 : work_data->sum[3][iFunc] = nodal_values(node); break ;
+      default: break ;
+      }
+      }
+    }
+
+    __syncthreads(); // Wait for all warps to finish gathering
+
+    // now get local 'const' copies in register space:
+
+    const double x       = work_data->sum[0][ iFunc ];
+    const double y       = work_data->sum[1][ iFunc ];
+    const double z       = work_data->sum[2][ iFunc ];
+    const double dof_val = work_data->sum[3][ iFunc ];
+
+    __syncthreads(); // Wait for all warps to finish extracting
+
+    sum_x_clear(); // Make sure summation scratch is zero
+
+    //------------------------------------
+    // Each warp is now on its own computing an integration point
+    // so no further explicit synchronizations are required.
+
+    if ( hasFunc ) {
+
+      float * const J    = work_data->spaceJac[    threadIdx.y ];
+      float * const invJ = work_data->spaceInvJac[ threadIdx.y ];
+
+      for ( unsigned iInt = threadIdx.y ;
+                     iInt < IntegrationCount ; iInt += blockDim.y ) {
+
+        const float val = elem_data.values[iInt][iFunc] ;
+        const float gx  = elem_data.gradients[iInt][0][iFunc] ;
+        const float gy  = elem_data.gradients[iInt][1][iFunc] ;
+        const float gz  = elem_data.gradients[iInt][2][iFunc] ;
+
+        sum_x( J[j11], gx * x );
+        sum_x( J[j12], gx * y );
+        sum_x( J[j13], gx * z );
+
+        sum_x( J[j21], gy * x );
+        sum_x( J[j22], gy * y );
+        sum_x( J[j23], gy * z );
+
+        sum_x( J[j31], gz * x );
+        sum_x( J[j32], gz * y );
+        sum_x( J[j33], gz * z );
+
+        // Inverse jacobian, only enough parallel work for 9 threads in the warp
+
+        if ( iFunc < TensorDim ) {
+
+          invJ[ iFunc ] =
+            J[ invJacIndex[iFunc][0] ] * J[ invJacIndex[iFunc][1] ] -
+            J[ invJacIndex[iFunc][2] ] * J[ invJacIndex[iFunc][3] ] ;
+
+          // Let all threads in the warp compute determinant into a register
+
+          const float detJ = J[j11] * invJ[j11] +
+                             J[j21] * invJ[j12] +
+                             J[j31] * invJ[j13] ;
+
+          invJ[ iFunc ] /= detJ ;
+
+          if ( 0 == iFunc ) {
+            work_data->detJweight[ iInt ] = detJ * elem_data.weights[ iInt ] ;
+          }
+        }
+
+        // Transform bases gradients and compute value and gradient
+
+        const float dx = gx * invJ[j11] + gy * invJ[j12] + gz * invJ[j13];
+        const float dy = gx * invJ[j21] + gy * invJ[j22] + gz * invJ[j23];
+        const float dz = gx * invJ[j31] + gy * invJ[j32] + gz * invJ[j33];
+
+        work_data->dpsidx[iFunc][iInt] = dx ;
+        work_data->dpsidy[iFunc][iInt] = dy ;
+        work_data->dpsidz[iFunc][iInt] = dz ;
+
+        sum_x( work_data->gradx_at_integ[iInt] , dof_val * dx );
+        sum_x( work_data->grady_at_integ[iInt] , dof_val * dy );
+        sum_x( work_data->gradz_at_integ[iInt] , dof_val * dz );
+        sum_x( work_data->value_at_integ[iInt] , dof_val * val );
+      }
+    }
+
+    __syncthreads(); // All shared data must be populated at return.
+  }
+
+  __device__ inline
+  void contributeResidualJacobian( const unsigned ielem ) const
+  {
+    extern __shared__ WorkSpace work_data[] ;
+
+    sum_x_clear(); // Make sure summation scratch is zero
+
+    // $$ R_i = \int_{\Omega} \nabla \phi_i \cdot (k \nabla T) + \phi_i T^2 d \Omega $$ 
+    // $$ J_{i,j} = \frac{\partial R_i}{\partial T_j} = \int_{\Omega} k \nabla \phi_i \cdot \nabla \phi_j + 2 \phi_i \phi_j T d \Omega $$ 
+
+    const unsigned iInt = threadIdx.x ;
+
+    if ( iInt < IntegrationCount ) {
+
+      const double value_at_integ = work_data->value_at_integ[ iInt ] ;
+      const double gradx_at_integ = work_data->gradx_at_integ[ iInt ] ;
+      const double grady_at_integ = work_data->grady_at_integ[ iInt ] ;
+      const double gradz_at_integ = work_data->gradz_at_integ[ iInt ] ;
+
+      const float detJweight     = work_data->detJweight[ iInt ] ;
+      const float coeff_K_detJweight = coeff_K * detJweight ;
+
+      for ( unsigned iRow = threadIdx.y ;
+                     iRow < FunctionCount ; iRow += blockDim.y ) {
+
+        const float value_row  = elem_data.values[ iInt ][ iRow ] * detJweight ;
+        const float dpsidx_row = work_data->dpsidx[ iRow ][ iInt ] * coeff_K_detJweight ;
+        const float dpsidy_row = work_data->dpsidy[ iRow ][ iInt ] * coeff_K_detJweight ;
+        const float dpsidz_row = work_data->dpsidz[ iRow ][ iInt ] * coeff_K_detJweight ;
+
+        const double res_del = dpsidx_row * gradx_at_integ +
+                               dpsidy_row * grady_at_integ +
+                               dpsidz_row * gradz_at_integ ;
+
+        const double res_val = value_at_integ * value_at_integ * value_row ;
+        const double jac_val_row = 2 * value_at_integ * value_row ;
+
+        sum_x( element_vectors( ielem , iRow ) , res_del + res_val );
+
+        for ( unsigned iCol = 0 ; iCol < FunctionCount ; ++iCol ) {
+
+          const float jac_del = 
+            dpsidx_row * work_data->dpsidx[iCol][iInt] +
+            dpsidy_row * work_data->dpsidy[iCol][iInt] +
+            dpsidz_row * work_data->dpsidz[iCol][iInt] ;
+
+          const double jac_val =
+            jac_val_row * elem_data.values[ iInt ][ iCol ] ;
+
+          sum_x( element_matrices( ielem , iRow , iCol ) , jac_del + jac_val );
+        }
+      }
+    }
+
+    __syncthreads(); // All warps finish before refilling shared data 
+  }
+
+  __device__ inline
+  void operator()(void) const
+  {
+    extern __shared__ WorkSpace work_data[] ;
+
+    for ( unsigned ielem = blockIdx.x ; ielem < elem_count ; ielem += gridDim.x ) {
+
+      evaluateFunctions( ielem );
+
+      contributeResidualJacobian( ielem );
+    }
+  }
+
+}; /* ElementComputation */
+
+} /* namespace Nonlinear */
+} /* namespace HybridFEM */
+
diff --git a/lib/kokkos/example/multi_fem/NonlinearFunctors.hpp b/lib/kokkos/example/multi_fem/NonlinearFunctors.hpp
new file mode 100644
index 0000000000..9628236181
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/NonlinearFunctors.hpp
@@ -0,0 +1,482 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_NONLINEARFUNCTORS_HPP
+#define KOKKOS_NONLINEARFUNCTORS_HPP
+
+#include <iostream>
+#include <fstream>
+#include <iomanip>
+#include <cstdlib>
+#include <cmath>
+
+namespace HybridFEM {
+namespace Nonlinear {
+
+template< class MeshType , typename ScalarType > struct ElementComputation ;
+template< class MeshType , typename ScalarType > struct DirichletSolution ;
+template< class MeshType , typename ScalarType > struct DirichletResidual ;
+
+}
+}
+
+/* A Cuda-specific specialization for the element computation functor. */
+#if defined( __CUDACC__ )
+#include <NonlinearElement_Cuda.hpp>
+#endif
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace HybridFEM {
+namespace Nonlinear {
+
+template< typename ScalarCoordType , unsigned ElemNode , class DeviceType ,
+          typename ScalarType >
+struct ElementComputation<
+  FEMesh< ScalarCoordType , ElemNode , DeviceType > , ScalarType >
+{
+  typedef DeviceType  execution_space;
+  typedef ScalarType           scalar_type ;
+
+  static const unsigned ElementNodeCount = ElemNode ;
+
+  typedef FEMesh< ScalarCoordType , ElementNodeCount , execution_space > mesh_type ;
+
+  typedef HexElement_Data< ElementNodeCount > element_data_type ;
+
+  static const unsigned SpatialDim       = element_data_type::spatial_dimension ;
+  static const unsigned FunctionCount    = element_data_type::function_count ;
+  static const unsigned IntegrationCount = element_data_type::integration_count ;
+  static const unsigned TensorDim        = SpatialDim * SpatialDim ;
+
+  typedef Kokkos::View< scalar_type[][FunctionCount][FunctionCount] , execution_space > elem_matrices_type ;
+  typedef Kokkos::View< scalar_type[][FunctionCount] , execution_space > elem_vectors_type ;
+  typedef Kokkos::View< scalar_type[] , execution_space > value_vector_type ;
+
+
+private:
+
+  const element_data_type                 elem_data ;
+  typename mesh_type::elem_node_ids_type  elem_node_ids ;
+  typename mesh_type::node_coords_type    node_coords ;
+  value_vector_type                       nodal_values ;
+  elem_matrices_type                      element_matrices ;
+  elem_vectors_type                       element_vectors ;
+  scalar_type                             coeff_K ;
+
+public:
+
+  ElementComputation( const mesh_type   & arg_mesh ,
+                      const elem_matrices_type  & arg_element_matrices ,
+                      const elem_vectors_type   & arg_element_vectors ,
+                      const value_vector_type   & arg_nodal_values ,
+	              const scalar_type   arg_coeff_K )
+  : elem_data()
+  , elem_node_ids( arg_mesh.elem_node_ids )
+  , node_coords(   arg_mesh.node_coords )
+  , nodal_values(   arg_nodal_values )
+  , element_matrices( arg_element_matrices )
+  , element_vectors( arg_element_vectors )
+  , coeff_K( arg_coeff_K )
+  {
+    const size_t elem_count = arg_mesh.elem_node_ids.dimension_0();
+
+    parallel_for( elem_count , *this );
+  }
+
+  //------------------------------------
+
+  static const unsigned FLOPS_transform_gradients =
+     /* Jacobian */           FunctionCount * TensorDim * 2 +
+     /* Inverse jacobian */   TensorDim * 6 + 6 +
+     /* Gradient transform */ FunctionCount * 15 ;
+
+  KOKKOS_INLINE_FUNCTION
+  float transform_gradients(
+    const float grad[][ FunctionCount ] , // Gradient of bases master element
+    const double x[] ,
+    const double y[] ,
+    const double z[] ,
+    float dpsidx[] ,
+    float dpsidy[] ,
+    float dpsidz[] ) const
+  {
+    enum { j11 = 0 , j12 = 1 , j13 = 2 ,
+           j21 = 3 , j22 = 4 , j23 = 5 ,
+           j31 = 6 , j32 = 7 , j33 = 8 };
+
+    // Jacobian accumulation:
+
+    double J[ TensorDim ] = { 0, 0, 0,  0, 0, 0,  0, 0, 0 };
+
+    for( unsigned i = 0; i < FunctionCount ; ++i ) {
+      const double x1 = x[i] ;
+      const double x2 = y[i] ;
+      const double x3 = z[i] ;
+
+      const float g1 = grad[0][i] ;
+      const float g2 = grad[1][i] ;
+      const float g3 = grad[2][i] ;
+
+      J[j11] += g1 * x1 ;
+      J[j12] += g1 * x2 ;
+      J[j13] += g1 * x3 ;
+
+      J[j21] += g2 * x1 ;
+      J[j22] += g2 * x2 ;
+      J[j23] += g2 * x3 ;
+
+      J[j31] += g3 * x1 ;
+      J[j32] += g3 * x2 ;
+      J[j33] += g3 * x3 ;
+    }
+
+    // Inverse jacobian:
+
+    float invJ[ TensorDim ] = {
+      static_cast<float>( J[j22] * J[j33] - J[j23] * J[j32] ) ,
+      static_cast<float>( J[j13] * J[j32] - J[j12] * J[j33] ) ,
+      static_cast<float>( J[j12] * J[j23] - J[j13] * J[j22] ) ,
+
+      static_cast<float>( J[j23] * J[j31] - J[j21] * J[j33] ) ,
+      static_cast<float>( J[j11] * J[j33] - J[j13] * J[j31] ) ,
+      static_cast<float>( J[j13] * J[j21] - J[j11] * J[j23] ) ,
+
+      static_cast<float>( J[j21] * J[j32] - J[j22] * J[j31] ) ,
+      static_cast<float>( J[j12] * J[j31] - J[j11] * J[j32] ) ,
+      static_cast<float>( J[j11] * J[j22] - J[j12] * J[j21] ) };
+
+    const float detJ = J[j11] * invJ[j11] +
+                       J[j21] * invJ[j12] +
+                       J[j31] * invJ[j13] ;
+
+    const float detJinv = 1.0 / detJ ;
+
+    for ( unsigned i = 0 ; i < TensorDim ; ++i ) { invJ[i] *= detJinv ; }
+
+    // Transform gradients:
+
+    for( unsigned i = 0; i < FunctionCount ; ++i ) {
+      const float g0 = grad[0][i];
+      const float g1 = grad[1][i];
+      const float g2 = grad[2][i];
+
+      dpsidx[i] = g0 * invJ[j11] + g1 * invJ[j12] + g2 * invJ[j13];
+      dpsidy[i] = g0 * invJ[j21] + g1 * invJ[j22] + g2 * invJ[j23];
+      dpsidz[i] = g0 * invJ[j31] + g1 * invJ[j32] + g2 * invJ[j33];
+    }
+
+    return detJ ;
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void contributeResidualJacobian(
+    const float coeff_k ,
+    const double dof_values[] ,
+    const float dpsidx[] ,
+    const float dpsidy[] ,
+    const float dpsidz[] ,
+    const float detJ ,
+    const float integ_weight ,
+    const float bases_vals[] ,
+    double elem_res[] ,
+    double elem_mat[][ FunctionCount ] ) const
+  {
+    double value_at_pt = 0 ;
+    double gradx_at_pt = 0 ;
+    double grady_at_pt = 0 ;
+    double gradz_at_pt = 0 ;
+
+    for ( unsigned m = 0 ; m < FunctionCount ; m++ ) {
+      value_at_pt += dof_values[m] * bases_vals[m] ;
+      gradx_at_pt += dof_values[m] * dpsidx[m] ;
+      grady_at_pt += dof_values[m] * dpsidy[m] ;
+      gradz_at_pt += dof_values[m] * dpsidz[m] ;
+    }
+
+    const scalar_type k_detJ_weight = coeff_k        * detJ * integ_weight ;
+    const double res_val = value_at_pt * value_at_pt * detJ * integ_weight ;
+    const double mat_val = 2.0 * value_at_pt         * detJ * integ_weight ;
+
+    // $$ R_i = \int_{\Omega} \nabla \phi_i \cdot (k \nabla T) + \phi_i T^2 d \Omega $$
+    // $$ J_{i,j} = \frac{\partial R_i}{\partial T_j} = \int_{\Omega} k \nabla \phi_i \cdot \nabla \phi_j + 2 \phi_i \phi_j T d \Omega $$
+
+    for ( unsigned m = 0; m < FunctionCount; m++) {
+      double * const mat = elem_mat[m] ;
+      const float bases_val_m = bases_vals[m];
+      const float dpsidx_m    = dpsidx[m] ;
+      const float dpsidy_m    = dpsidy[m] ;
+      const float dpsidz_m    = dpsidz[m] ;
+
+      elem_res[m] += k_detJ_weight * ( dpsidx_m * gradx_at_pt +
+                                       dpsidy_m * grady_at_pt +
+                                       dpsidz_m * gradz_at_pt ) +
+                     res_val * bases_val_m ;
+
+      for( unsigned n = 0; n < FunctionCount; n++) {
+
+        mat[n] += k_detJ_weight * ( dpsidx_m * dpsidx[n] +
+                                    dpsidy_m * dpsidy[n] +
+                                    dpsidz_m * dpsidz[n] ) +
+                  mat_val * bases_val_m * bases_vals[n];
+      }
+    }
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned ielem ) const
+  {
+    // Gather nodal coordinates and solution vector:
+
+    double x[ FunctionCount ] ;
+    double y[ FunctionCount ] ;
+    double z[ FunctionCount ] ;
+    double val[ FunctionCount ] ;
+
+    for ( unsigned i = 0 ; i < ElementNodeCount ; ++i ) {
+      const unsigned node_index = elem_node_ids( ielem , i );
+
+      x[i] = node_coords( node_index , 0 );
+      y[i] = node_coords( node_index , 1 );
+      z[i] = node_coords( node_index , 2 );
+
+      val[i] = nodal_values( node_index );
+    }
+
+    double elem_vec[ FunctionCount ] ;
+    double elem_mat[ FunctionCount ][ FunctionCount ] ;
+
+    for( unsigned i = 0; i < FunctionCount ; i++ ) {
+      elem_vec[i] = 0 ;
+      for( unsigned j = 0; j < FunctionCount ; j++){
+        elem_mat[i][j] = 0 ;
+      }
+    }
+
+    for ( unsigned i = 0 ; i < IntegrationCount ; ++i ) {
+      float dpsidx[ FunctionCount ] ;
+      float dpsidy[ FunctionCount ] ;
+      float dpsidz[ FunctionCount ] ;
+
+      const float detJ =
+        transform_gradients( elem_data.gradients[i] , x , y , z ,
+                             dpsidx , dpsidy , dpsidz );
+
+      contributeResidualJacobian( coeff_K ,
+                                  val , dpsidx , dpsidy , dpsidz ,
+                                  detJ ,
+                                  elem_data.weights[i] ,
+                                  elem_data.values[i] ,
+                                  elem_vec , elem_mat );
+    }
+
+    for( unsigned i = 0; i < FunctionCount ; i++){
+      element_vectors(ielem, i) = elem_vec[i] ;
+      for( unsigned j = 0; j < FunctionCount ; j++){
+        element_matrices(ielem, i, j) = elem_mat[i][j] ;
+      }
+    }
+  }
+
+}; /* ElementComputation */
+
+//----------------------------------------------------------------------------
+
+template< typename ScalarCoordType , unsigned ElemNode , class DeviceType ,
+          typename ScalarType >
+struct DirichletSolution<
+  FEMesh< ScalarCoordType , ElemNode , DeviceType > ,
+  ScalarType >
+{
+  typedef DeviceType  execution_space;
+
+  static const unsigned ElementNodeCount = ElemNode ;
+
+  typedef Kokkos::View< ScalarType[] , execution_space >  vector_type ;
+
+  typedef FEMesh< ScalarCoordType , ElementNodeCount , execution_space > mesh_type ;
+
+  typename mesh_type::node_coords_type node_coords ;
+
+  vector_type     solution ;
+  ScalarCoordType bc_lower_z ;
+  ScalarCoordType bc_upper_z ;
+  ScalarType      bc_lower_value ;
+  ScalarType      bc_upper_value ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned inode ) const
+  {
+
+  // Apply dirichlet boundary condition on the Solution vector.
+  // Define boundary node values to be either bc_lower_value or
+  // bc_upper_value, depending on which boundary face they lie on.
+  // Non-boundary terms will be left at their previous value.
+
+    const ScalarCoordType z = node_coords(inode,2);
+    const bool bc_lower = z <= bc_lower_z ;
+    const bool bc_upper = bc_upper_z <= z ;
+
+    if ( bc_lower || bc_upper ) {
+      const ScalarType bc_value = bc_lower ? bc_lower_value
+                                           : bc_upper_value ;
+
+      solution(inode) = bc_value ; //  set the solution vector
+    }
+  }
+
+  static void apply( const vector_type    & solution ,
+                     const mesh_type      & mesh ,
+                     const ScalarCoordType  bc_lower_z ,
+                     const ScalarCoordType  bc_upper_z ,
+                     const ScalarType       bc_lower_value ,
+                     const ScalarType       bc_upper_value )
+  {
+    DirichletSolution op ;
+    op.node_coords    = mesh.node_coords ;
+    op.solution       = solution ;
+    op.bc_lower_z     = bc_lower_z ;
+    op.bc_upper_z     = bc_upper_z ;
+    op.bc_lower_value = bc_lower_value ;
+    op.bc_upper_value = bc_upper_value ;
+    parallel_for( solution.dimension_0() , op );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< typename ScalarCoordType , unsigned ElemNode , class DeviceType ,
+          typename ScalarType >
+struct DirichletResidual<
+  FEMesh< ScalarCoordType , ElemNode , DeviceType > , ScalarType >
+{
+  typedef DeviceType     execution_space;
+  typedef typename execution_space::size_type  size_type ;
+
+  static const unsigned ElementNodeCount = ElemNode ;
+
+  typedef Kokkos::CrsMatrix< ScalarType , execution_space >    matrix_type ;
+  typedef Kokkos::View< ScalarType[] , execution_space >  vector_type ;
+
+  typedef FEMesh< ScalarCoordType , ElementNodeCount , execution_space > mesh_type ;
+
+  typename mesh_type::node_coords_type node_coords ;
+  matrix_type     matrix ;
+  vector_type     rhs ;
+  ScalarCoordType bc_lower_z ;
+  ScalarCoordType bc_upper_z ;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const unsigned inode ) const
+  {
+    //  Apply a dirichlet boundary condition to 'irow'
+    //  to maintain the symmetry of the original
+    //  global stiffness matrix, zero out the columns
+    //  that correspond to boundary conditions, and
+    //  adjust the load vector accordingly
+
+    const size_type iBeg = matrix.graph.row_map[inode];
+    const size_type iEnd = matrix.graph.row_map[inode+1];
+
+    const ScalarCoordType z = node_coords(inode,2);
+    const bool bc_lower = z <= bc_lower_z ;
+    const bool bc_upper = bc_upper_z <= z ;
+
+    if ( bc_lower || bc_upper ) {
+      rhs(inode) = 0 ; //  set the residual vector
+
+      //  zero each value on the row, and leave a one
+      //  on the diagonal
+
+      for( size_type i = iBeg ; i < iEnd ; i++) {
+        matrix.coefficients(i) =
+          (int) inode == matrix.graph.entries(i) ? 1 : 0 ;
+      }
+    }
+    else {
+
+      //  Find any columns that are boundary conditions.
+      //  Clear them and adjust the load vector
+
+      for( size_type i = iBeg ; i < iEnd ; i++ ) {
+        const size_type cnode = matrix.graph.entries(i) ;
+
+        const ScalarCoordType zc = node_coords(cnode,2);
+        const bool c_bc_lower = zc <= bc_lower_z ;
+        const bool c_bc_upper = bc_upper_z <= zc ;
+
+        if ( c_bc_lower || c_bc_upper ) {
+
+	   matrix.coefficients(i) = 0 ;
+        }
+      }
+    }
+  }
+
+
+  static void apply( const matrix_type & linsys_matrix ,
+                     const vector_type & linsys_rhs ,
+                     const mesh_type   & mesh ,
+                     const ScalarCoordType  bc_lower_z ,
+                     const ScalarCoordType  bc_upper_z)
+  {
+    const size_t row_count = linsys_matrix.graph.row_map.dimension_0() - 1 ;
+
+    DirichletResidual op ;
+    op.node_coords    = mesh.node_coords ;
+    op.matrix         = linsys_matrix ;
+    op.rhs            = linsys_rhs ;
+    op.bc_lower_z     = bc_lower_z ;
+    op.bc_upper_z     = bc_upper_z ;
+    parallel_for( row_count , op );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+} /* namespace Nonlinear */
+} /* namespace HybridFEM */
+
+#endif /* #ifndef KOKKOS_NONLINEARFUNCTORS_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/ParallelComm.hpp b/lib/kokkos/example/multi_fem/ParallelComm.hpp
new file mode 100644
index 0000000000..163e84a958
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/ParallelComm.hpp
@@ -0,0 +1,167 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef PARALLELCOMM_HPP
+#define PARALLELCOMM_HPP
+
+//------------------------------------------------------------------------
+
+#include <Kokkos_Macros.hpp>
+
+//------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_MPI )
+
+#include <mpi.h>
+#include <string>
+
+namespace comm {
+
+struct Machine {
+  MPI_Comm mpi_comm ;
+
+  Machine() : mpi_comm( MPI_COMM_NULL ) {}
+
+  Machine( const Machine & rhs )
+    : mpi_comm( rhs.mpi_comm ) {}
+
+  Machine( MPI_Comm c ) : mpi_comm( c ) {}
+
+  static Machine init( int * argc , char *** argv )
+  {
+    MPI_Init( argc , argv );
+    return Machine( MPI_COMM_WORLD );
+  }
+
+  static void finalize() { MPI_Finalize(); }
+};
+
+inline
+unsigned  size( Machine machine )
+{
+  int np ; MPI_Comm_size( machine.mpi_comm , & np ); return np ;
+}
+
+inline
+unsigned  rank( Machine machine )
+{
+  int ip ; MPI_Comm_rank( machine.mpi_comm , & ip ); return ip ;
+}
+
+inline
+double max( Machine machine , double local )
+{
+  double global = 0;
+  MPI_Allreduce( & local , & global , 1 , MPI_DOUBLE , MPI_MAX , machine.mpi_comm );
+  return global ;
+}
+
+inline
+std::string command_line( Machine machine , const int argc , const char * const * const argv )
+{
+  std::string argline ;
+
+  if ( 0 == rank( machine ) ) {
+    for ( int i = 1 ; i < argc ; ++i ) {
+      argline.append(" ").append( argv[i] );
+    }
+  }
+
+  int length = argline.length();
+  MPI_Bcast( & length , 1 , MPI_INT , 0 , machine.mpi_comm );
+  argline.resize( length , ' ' );
+  MPI_Bcast( (void*) argline.data() , length , MPI_CHAR , 0 , machine.mpi_comm );
+
+  return argline ;
+}
+
+}
+
+#else /* ! defined( KOKKOS_HAVE_MPI ) */
+
+#include <string>
+
+namespace comm {
+
+// Stub for non-parallel
+
+struct Machine {
+  static Machine init( int * , char *** )
+  { return Machine(); }
+
+  static void finalize() {}
+};
+
+inline
+unsigned  size( Machine ) { return 1 ; }
+
+inline
+unsigned  rank( Machine ) { return 0 ; }
+
+inline
+double max( Machine , double local )
+{ return local ; }
+
+inline
+std::string command_line( Machine machine , const int argc , const char * const * const argv )
+{
+  std::string argline ;
+
+  if ( 0 == rank( machine ) ) {
+    for ( int i = 1 ; i < argc ; ++i ) {
+      argline.append(" ").append( argv[i] );
+    }
+  }
+
+  return argline ;
+}
+
+}
+
+#endif /* ! defined( KOKKOS_HAVE_MPI ) */
+
+//------------------------------------------------------------------------
+
+#endif /* #ifndef PARALLELCOMM_HPP */
+
+
diff --git a/lib/kokkos/example/multi_fem/ParallelDataMap.hpp b/lib/kokkos/example/multi_fem/ParallelDataMap.hpp
new file mode 100644
index 0000000000..22a1cfefa1
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/ParallelDataMap.hpp
@@ -0,0 +1,517 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef KOKKOS_PARALLELDATAMAP_HPP
+#define KOKKOS_PARALLELDATAMAP_HPP
+
+#include <utility>
+#include <limits>
+#include <iostream>
+#include <sstream>
+#include <stdexcept>
+
+#include <Kokkos_Core.hpp>
+#include <ParallelComm.hpp>
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+/** \brief  Parallel distributed data mapping
+ *
+ *  ordering { interior : { owned items not sent elsewhere }
+ *             send     : { owned items sent }
+ *             receive  : { not-owned items received } }
+ *
+ *  recv { { N ghosted items from process P : ( P , N ) } }
+ *
+ *  send { { N send items to process P : ( P , N ) } }
+ *
+ *  send_item { send item offsets within 'send' range }
+ */
+struct ParallelDataMap {
+  typedef View< unsigned*[2], HostSpace >  host_recv_type ;
+  typedef View< unsigned*[2], HostSpace >  host_send_type ;
+  typedef View< unsigned* ,   HostSpace >  host_send_item_type ;
+
+  comm::Machine        machine ;
+  host_recv_type       host_recv ;
+  host_send_type       host_send ;
+  host_send_item_type  host_send_item ;
+  unsigned             count_interior ;
+  unsigned             count_send ;
+  unsigned             count_owned ; // = count_interior + count_send
+  unsigned             count_receive ;
+
+  void assign( const unsigned arg_count_interior ,
+               const unsigned arg_count_owned ,
+               const unsigned arg_count_total ,
+               const unsigned arg_recv_msg ,
+               const unsigned arg_send_msg ,
+               const unsigned arg_send_count )
+  {
+    const std::string label("Kokkos::ParallelDataMap buffer");
+
+    count_interior = arg_count_interior ;
+    count_owned    = arg_count_owned ;
+    count_send     = arg_count_owned - arg_count_interior ;
+    count_receive  = arg_count_total - arg_count_owned ;
+
+    host_recv = host_recv_type( label , arg_recv_msg );
+    host_send = host_send_type( label , arg_send_msg );
+    host_send_item = host_send_item_type( label , arg_send_count );
+  }
+};
+
+//----------------------------------------------------------------------------
+//PackArray
+//----------------------------------------------------------------------------
+template< class ArrayType , class Rank = void >
+struct PackArray ;
+
+template< typename DeviceType, typename ValueType >
+struct PackArray< View< ValueType* , DeviceType > , void >
+{
+  typedef DeviceType                         execution_space ;
+  typedef typename DeviceType::size_type     size_type ;
+  typedef View< ValueType* , execution_space >  array_type ;
+  typedef View< ValueType* , execution_space >  buffer_type ;
+
+private:
+
+  buffer_type  output ;
+  array_type   input ;
+  size_type    base ;
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i ) const
+  { output[i] = input(base+i); }
+
+  inline
+  static
+  void pack( const buffer_type & arg_output ,
+             const size_type     arg_begin ,
+             const size_type     arg_count ,
+             const array_type  & arg_input )
+  {
+    PackArray op ;
+    op.output = arg_output ;
+    op.input  = arg_input ;
+    op.base   = arg_begin ;
+    parallel_for( arg_count , op );
+  }
+};
+
+template< typename DeviceType, typename ValueType , unsigned N1 >
+struct PackArray< View< ValueType*[N1] , DeviceType > , void >
+{
+  typedef DeviceType                                  execution_space ;
+  typedef typename DeviceType::size_type              size_type ;
+  typedef View< ValueType*[N1] , execution_space >       array_type ;
+  typedef View< ValueType* , execution_space >           buffer_type ;
+
+private:
+
+  buffer_type  output ;
+  array_type   input ;
+  size_type    base ;
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i ) const
+  {
+    for ( size_type j = 0 , k = i * N1 ; j < N1 ; ++j , ++k ) {
+      output[k] = input(base+i,j);
+    }
+  }
+
+  inline static
+  void pack( const buffer_type & arg_output ,
+             const size_type     arg_begin ,
+             const size_type     arg_count ,
+             const array_type  & arg_input )
+  {
+    if ( arg_count ) {
+      PackArray op ;
+      op.output = arg_output ;
+      op.input  = arg_input ;
+      op.base   = arg_begin ;
+      parallel_for( arg_count , op );
+    }
+  }
+};
+
+//----------------------------------------------------------------------------
+//UnpackArray
+//----------------------------------------------------------------------------
+template< class ArrayType , class Rank = void > struct UnpackArray ;
+
+template< typename DeviceType, typename ValueType >
+struct UnpackArray< View< ValueType* , DeviceType > , void >
+{
+  typedef DeviceType                         execution_space ;
+  typedef typename DeviceType::size_type     size_type ;
+  typedef View< ValueType* , execution_space >  array_type ;
+  typedef View< ValueType* , execution_space >  buffer_type ;
+
+private:
+
+  array_type   output ;
+  buffer_type  input ;
+  size_type    base ;
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i ) const
+  { output(base+i) = input[i]; }
+
+  inline
+  static
+  void unpack( const array_type  & arg_output ,
+               const buffer_type & arg_input ,
+               const size_type     arg_begin ,
+               const size_type     arg_count )
+  {
+    UnpackArray op ;
+    op.output = arg_output ;
+    op.input  = arg_input ;
+    op.base   = arg_begin ;
+    parallel_for( arg_count , op );
+  }
+};
+
+template< typename DeviceType, typename ValueType , unsigned N1 >
+struct UnpackArray< View< ValueType*[N1] , DeviceType > , void >
+{
+  typedef DeviceType                                  execution_space ;
+  typedef typename DeviceType::size_type              size_type ;
+  typedef View< ValueType* , execution_space >           buffer_type ;
+  typedef View< ValueType*[N1] , execution_space >       array_type ;
+
+private:
+
+  array_type   output ;
+  buffer_type  input ;
+  size_type    base ;
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i ) const
+  {
+    for ( size_type j = 0 , k = i * N1 ; j < N1 ; ++j , ++k ) {
+      output(base+i,j) = input(k);
+    }
+  }
+
+  inline
+  static
+  void unpack( const array_type  & arg_output ,
+               const buffer_type & arg_input ,
+               const size_type     arg_begin ,
+               const size_type     arg_count )
+  {
+    if ( arg_count ) {
+      UnpackArray op ;
+      op.output = arg_output ;
+      op.input  = arg_input ;
+      op.base   = arg_begin ;
+      parallel_for( arg_count , op );
+    }
+  }
+};
+//----------------------------------------------------------------------------
+template< class ValueType , class Device , class DataMap >
+class AsyncExchange ;
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+// Application call procedure:
+//
+// construct: AsyncExchange object
+// * pack send buffer on device
+// initiate: copy send buffer from device to host
+// * dispatch asynchronous local work
+// complete: send/receive on host, copy receive buffer to device
+// * unpack receive buffer on device
+// destroy: AsyncExchange object
+//
+//----------------------------------------------------------------------------
+
+#ifdef KOKKOS_HAVE_MPI
+
+namespace Kokkos {
+
+template< class ValueType , class Device >
+class AsyncExchange< ValueType, Device , Kokkos::ParallelDataMap > {
+public:
+
+  typedef Device                                    execution_space ;
+  typedef Kokkos::ParallelDataMap                   data_map_type ;
+  typedef Kokkos::View< ValueType* , execution_space >  buffer_dev_type ;
+  typedef typename buffer_dev_type::HostMirror      buffer_host_type ;
+
+private:
+
+  static const int mpi_tag = 11 ;
+
+  const data_map_type  data_map ;
+  unsigned             chunk_size ;
+  unsigned             send_count_max ;
+  buffer_host_type     host_recv_buffer ;
+  buffer_host_type     host_send_buffer ;
+  buffer_host_type     send_msg_buffer ;
+  buffer_dev_type      dev_buffer ;
+  buffer_dev_type      dev_send_buffer ; // Subview for send
+  buffer_dev_type      dev_recv_buffer ; // Subview for receive
+  std::vector< MPI_Request > recv_request ;
+
+public:
+
+  const buffer_dev_type & buffer() const { return dev_buffer ; }
+
+  AsyncExchange( const data_map_type & arg_data_map ,
+                 const size_t          arg_chunk )
+  : data_map( arg_data_map )
+  , chunk_size( arg_chunk )
+  , send_count_max( 0 )
+  , host_recv_buffer()
+  , host_send_buffer()
+  , send_msg_buffer()
+  , dev_buffer()
+  , dev_send_buffer()
+  , dev_recv_buffer()
+  , recv_request()
+  {
+    const size_t send_msg_count = arg_data_map.host_send.dimension_0();
+    const size_t recv_msg_count = arg_data_map.host_recv.dimension_0();
+
+    const size_t send_msg_length = arg_chunk * arg_data_map.count_send ;
+    const size_t recv_msg_length = arg_chunk * arg_data_map.count_receive ;
+
+    for ( size_t i = 0 ; i < send_msg_count ; ++i ) {
+      send_count_max = std::max( send_count_max ,
+                                 (unsigned) arg_data_map.host_send(i,1) );
+    }
+
+    // A single shared buffer on the device can be used for
+    // send and receive message buffers.
+    dev_buffer = buffer_dev_type(
+                     std::string("AsyncExchange dev_buffer") ,
+                     std::max( send_msg_length , recv_msg_length ) );
+
+    // Total send subview of the device buffer
+    dev_send_buffer =
+      Kokkos::subview( dev_buffer , std::pair<size_t,size_t>( 0 , send_msg_length ) );
+
+    // Total receive subview of the device buffer
+    dev_recv_buffer =
+      Kokkos::subview( dev_buffer , std::pair<size_t,size_t>( 0 , recv_msg_length ) );
+
+    // Total receive message buffer on the host:
+    host_recv_buffer = buffer_host_type(
+                           std::string("AsyncExchange host_recv_buffer") ,
+                           recv_msg_length );
+
+    // Total send message buffer on the host:
+    host_send_buffer = buffer_host_type(
+                           std::string("AsyncExchange host_send_buffer") ,
+                           send_msg_length );
+
+    // Individual send message buffer on the host:
+    send_msg_buffer = buffer_host_type(
+                          std::string("AsyncExchange send_msg_buffer") ,
+                          arg_chunk * send_count_max );
+
+    // MPI asynchronous receive request handles:
+    recv_request.assign( recv_msg_count , MPI_REQUEST_NULL );
+  }
+
+  //------------------------------------------------------------------------
+
+  void setup()
+  {
+    { // Post receives:
+      const size_t recv_msg_count = data_map.host_recv.dimension_0();
+
+      ValueType * ptr = host_recv_buffer.ptr_on_device();
+
+      for ( size_t i = 0 ; i < recv_msg_count ; ++i ) {
+        const int proc  = data_map.host_recv(i,0);
+        const int count = data_map.host_recv(i,1) * chunk_size ;
+
+        MPI_Irecv( ptr , count * sizeof(ValueType) , MPI_BYTE ,
+                   proc , mpi_tag , data_map.machine.mpi_comm ,
+                   & recv_request[i] );
+
+        ptr += count ;
+      }
+    }
+
+    // Copy send buffer from the device to host memory for sending
+
+    Kokkos::deep_copy( host_send_buffer , dev_send_buffer );
+
+    // Done with the device until communication is complete.
+    // Application can dispatch asynchronous work on the device.
+  }
+
+  // Application can dispatch local work to device ...
+  // No communication progress until main thread calls 'send_receive'
+
+  void send_receive()
+  {
+    const size_t recv_msg_count = data_map.host_recv.dimension_0();
+    const size_t send_msg_count = data_map.host_send.dimension_0();
+
+    // Pack and send:
+
+    for ( size_t i = 0 , j = 0 ; i < send_msg_count ; ++i ) {
+      const int proc  = data_map.host_send(i,0);
+      const int count = data_map.host_send(i,1);
+
+      for ( int k = 0 , km = 0 ; k < count ; ++k , ++j ) {
+        const int km_end = km + chunk_size ;
+        int ki = chunk_size * data_map.host_send_item(j);
+
+        for ( ; km < km_end ; ++km , ++ki ) {
+          send_msg_buffer[km] = host_send_buffer[ki];
+        }
+      }
+
+      // MPI_Ssend blocks until
+      // (1) a receive is matched for the message and
+      // (2) the send buffer can be re-used.
+      //
+      // It is suggested that MPI_Ssend will have the best performance:
+      // http://www.mcs.anl.gov/research/projects/mpi/sendmode.html .
+
+      MPI_Ssend( send_msg_buffer.ptr_on_device(),
+                 count * chunk_size * sizeof(ValueType) , MPI_BYTE ,
+                 proc , mpi_tag , data_map.machine.mpi_comm );
+    }
+
+    // Wait for receives and verify:
+
+    for ( size_t i = 0 ; i < recv_msg_count ; ++i ) {
+      MPI_Status recv_status ;
+      int recv_which = 0 ;
+      int recv_size  = 0 ;
+
+      MPI_Waitany( recv_msg_count , & recv_request[0] ,
+                   & recv_which , & recv_status );
+
+      const int recv_proc = recv_status.MPI_SOURCE ;
+
+      MPI_Get_count( & recv_status , MPI_BYTE , & recv_size );
+
+      // Verify message properly received:
+
+      const int  expected_proc = data_map.host_recv(recv_which,0);
+      const int  expected_size = data_map.host_recv(recv_which,1) *
+                                 chunk_size * sizeof(ValueType);
+
+      if ( ( expected_proc != recv_proc ) ||
+           ( expected_size != recv_size ) ) {
+        std::ostringstream msg ;
+        msg << "AsyncExchange error:"
+            << " P" << comm::rank( data_map.machine )
+            << " received from P" << recv_proc
+            << " size "     << recv_size
+            << " expected " << expected_size
+            << " from P"    << expected_proc ;
+        throw std::runtime_error( msg.str() );
+      }
+    }
+
+    // Copy received data to device memory.
+
+    Kokkos::deep_copy( dev_recv_buffer , host_recv_buffer );
+  }
+};
+
+} // namespace Kokkos
+
+#else /* ! #ifdef KOKKOS_HAVE_MPI */
+
+namespace Kokkos {
+
+template< class ValueType , class Device >
+class AsyncExchange< ValueType, Device , Kokkos::ParallelDataMap > {
+public:
+
+  typedef Device                                    execution_space ;
+  typedef Kokkos::ParallelDataMap                   data_map_type ;
+  typedef Kokkos::View< ValueType* , execution_space >  buffer_dev_type ;
+  typedef typename buffer_dev_type::HostMirror      buffer_host_type ;
+
+  buffer_dev_type      dev_buffer ;
+
+public:
+
+  const buffer_dev_type & buffer() const { return dev_buffer ; }
+
+  AsyncExchange( const data_map_type & , const size_t )
+  : dev_buffer()
+  { }
+
+  //------------------------------------------------------------------------
+
+  void setup() { }
+
+  void send_receive() { }
+};
+
+} // namespace Kokkos
+
+#endif /* ! #ifdef KOKKOS_HAVE_MPI */
+
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef KOKKOS_PARALLELDATAMAP_HPP */
+
+
diff --git a/lib/kokkos/example/multi_fem/ParallelMachine.cpp b/lib/kokkos/example/multi_fem/ParallelMachine.cpp
new file mode 100644
index 0000000000..0953cab760
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/ParallelMachine.cpp
@@ -0,0 +1,178 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#if 0
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <ParallelMachine.hpp>
+
+#include <Kokkos_Core.hpp>
+
+#if ! defined( KOKKOS_HAVE_MPI )
+#define MPI_COMM_NULL 0
+#endif
+
+//------------------------------------------------------------------------
+
+namespace Parallel {
+
+Machine::Machine( int * argc , char *** argv )
+  : m_mpi_comm( MPI_COMM_NULL )
+  , m_mpi_size(0)
+  , m_mpi_rank(0)
+  , m_mpi_gpu(0)
+{
+
+#if defined( KOKKOS_HAVE_CUDA )
+  //------------------------------------
+  // Might be using a Cuda aware version of MPI.
+  // Must select Cuda device before initializing MPI.
+  {
+    int i = 1 ;
+    for ( ; i < *argc && strcmp((*argv)[i],"mpi_cuda") ; ++i );
+
+    if ( i < *argc ) {
+      // Determine, if possible, what will be the node-local
+      // rank of the MPI process once MPI has been initialized.
+      // This rank is needed to set the Cuda device before 'mvapich'
+      // is initialized.
+
+      const char * const mvapich_local_rank = getenv("MV2_COMM_WORLD_LOCAL_RANK");
+      const char * const slurm_local_rank   = getenv("SLURM_LOCALID");
+
+      const int pre_mpi_local_rank =
+        0 != mvapich_local_rank ? atoi( mvapich_local_rank ) : (
+        0 != slurm_local_rank   ? atoi( slurm_local_rank ) : (
+        -1 ) );
+
+      if ( 0 <= pre_mpi_local_rank ) {
+
+        const int ngpu = Kokkos::Cuda::detect_device_count();
+
+        const int cuda_device_rank = pre_mpi_local_rank % ngpu ;
+
+        Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice( cuda_device_rank ) );
+
+        m_mpi_gpu = 1 ;
+      }
+    }
+  }
+#endif
+
+  //------------------------------------
+
+#if defined( KOKKOS_HAVE_MPI )
+  MPI_Init( argc , argv );
+  m_mpi_comm = MPI_COMM_WORLD ;
+  MPI_Comm_size( m_mpi_comm , & m_mpi_size );
+  MPI_Comm_rank( m_mpi_comm , & m_mpi_rank );
+#endif
+
+  // Query hwloc after MPI initialization to allow MPI binding:
+  //------------------------------------
+  // Request to use host device:
+  {
+    int i = 1 ;
+    for ( ; i < *argc && strcmp((*argv)[i],"host") ; ++i );
+
+    if ( i < *argc ) {
+
+      unsigned team_count       = Kokkos::hwloc::get_available_numa_count();
+      unsigned threads_per_team = Kokkos::hwloc::get_available_cores_per_numa() *
+                                  Kokkos::hwloc::get_available_threads_per_core();
+ 
+      if ( i + 2 < *argc ) {
+        team_count       = atoi( (*argv)[i+1] );
+        threads_per_team = atoi( (*argv)[i+2] );
+      }
+
+      Kokkos::Threads::initialize( team_count * threads_per_team );
+    }
+  }
+
+#if defined( KOKKOS_HAVE_CUDA )
+  //------------------------------------
+  // Request to use Cuda device and not already initialized.
+  if ( ! m_mpi_gpu ) {
+    int i = 1 ;
+    for ( ; i < *argc && strcmp((*argv)[i],"mpi_cuda") && strcmp((*argv)[i],"cuda") ; ++i );
+
+    if ( i < *argc ) {
+
+      const int ngpu = Kokkos::Cuda::detect_device_count();
+
+      const int cuda_device_rank = m_mpi_rank % ngpu ;
+
+      Kokkos::Cuda::initialize( Kokkos::Cuda::SelectDevice( cuda_device_rank ) );
+    }
+  }
+#endif
+
+}
+
+Machine::~Machine()
+{
+  Kokkos::Threads::finalize();
+#if defined( KOKKOS_HAVE_CUDA )
+  Kokkos::Cuda::finalize();
+#endif
+#if defined( KOKKOS_HAVE_MPI )
+  MPI_Finalize();
+#endif
+}
+
+void Machine::print_configuration( std::ostream & msg ) const
+{
+  msg << "MPI [ " << m_mpi_rank << " / " << m_mpi_size << " ]" << std::endl ;
+  Kokkos::Threads::print_configuration( msg );
+#if defined( KOKKOS_HAVE_CUDA )
+  Kokkos::Cuda::print_configuration( msg );
+#endif
+}
+
+}
+
+#endif /* #if 0 */
+
diff --git a/lib/kokkos/example/multi_fem/ParallelMachine.hpp b/lib/kokkos/example/multi_fem/ParallelMachine.hpp
new file mode 100644
index 0000000000..1ddf50ab3b
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/ParallelMachine.hpp
@@ -0,0 +1,118 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#error "ParallelMachine"
+
+#ifndef PARALLELMACHINE_HPP
+#define PARALLELMACHINE_HPP
+
+//------------------------------------------------------------------------
+
+#include <iosfwd>
+
+#include <Kokkos_Core.hpp>
+
+//------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_MPI )
+#include <mpi.h>
+#else
+  typedef int MPI_Comm ;
+#endif
+
+//------------------------------------------------------------------------
+//------------------------------------------------------------------------
+
+namespace Parallel {
+
+/** \brief  Hybrid parallel machine with MPI+Kokkos::Threads or MPI+Kokkos::Cuda.
+ *
+ *  Initialization of MPI and Kokkos device has interdependencies which this
+ *  class manages.  The command line and environment variables are queried to initialize
+ *  the Threads or Cuda device:
+ *
+ *    1)  cuda               : initializes Cuda device
+ *    2)  host               : initializes Threads device with all hwloc detected cores.
+ *    3)  host #gang #worker : initializes Threads with specified
+ */
+class Machine {
+private:
+
+  MPI_Comm m_mpi_comm ;
+  int      m_mpi_size ;
+  int      m_mpi_rank ;
+  unsigned m_mpi_gpu ;
+  unsigned m_gpu_arch ;
+
+  Machine();
+  Machine( const Machine & );
+  Machine & operator = ( const Machine & );
+
+public:
+
+  /** \brief  Coordinated initialize MPI, Cuda, or Threads devices from 'main'.  */
+  Machine( int * argc , char *** argv );
+
+  ~Machine();
+
+  MPI_Comm mpi_comm() const { return m_mpi_comm ; }
+
+  int mpi_size() const { return m_mpi_size ; }
+  int mpi_rank() const { return m_mpi_rank ; }
+
+  /** \brief  If using MPI that can directly operate on GPU memory */
+  bool mpi_gpu() const { return m_mpi_gpu ; }
+
+  /** \brief  If using GPU then what architecture */
+  unsigned gpu_arch() const { return m_gpu_arch ; }
+
+  void print_configuration( std::ostream & ) const ;
+};
+
+}
+
+//------------------------------------------------------------------------
+
+#endif /* #ifndef PARALLELMACHINE_HPP */
+
+
diff --git a/lib/kokkos/example/multi_fem/SparseLinearSystem.hpp b/lib/kokkos/example/multi_fem/SparseLinearSystem.hpp
new file mode 100644
index 0000000000..8d140b6d25
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/SparseLinearSystem.hpp
@@ -0,0 +1,400 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef SPARSELINEARSYSTEM_HPP
+#define SPARSELINEARSYSTEM_HPP
+
+#include <cmath>
+#include <impl/Kokkos_Timer.hpp>
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_StaticCrsGraph.hpp>
+
+#include <LinAlgBLAS.hpp>
+
+namespace Kokkos {
+
+template< typename ScalarType , class Device >
+struct CrsMatrix {
+  typedef Device      execution_space ;
+  typedef ScalarType  value_type ;
+
+  typedef StaticCrsGraph< int , execution_space , void , int >  graph_type ;
+  typedef View< value_type* , execution_space >   coefficients_type ;
+
+  graph_type         graph ;
+  coefficients_type  coefficients ;
+};
+
+//----------------------------------------------------------------------------
+
+namespace Impl {
+
+template< class Matrix , class OutputVector , class InputVector >
+struct Multiply ;
+
+}
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+template< typename AScalarType ,
+          typename VScalarType ,
+          class DeviceType >
+struct Multiply< CrsMatrix<AScalarType,DeviceType> ,
+                 View<VScalarType*,DeviceType > ,
+                 View<VScalarType*,DeviceType > >
+{
+  typedef DeviceType                       execution_space ;
+  typedef typename execution_space::size_type  size_type ;
+
+  typedef View<       VScalarType*, execution_space, MemoryUnmanaged >  vector_type ;
+  typedef View< const VScalarType*, execution_space, MemoryUnmanaged >  vector_const_type ;
+
+  typedef CrsMatrix< AScalarType , execution_space >    matrix_type ;
+
+private:
+
+  matrix_type        m_A ;
+  vector_const_type  m_x ;
+  vector_type        m_y ;
+
+public:
+
+  //--------------------------------------------------------------------------
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type iRow ) const
+  {
+    const size_type iEntryBegin = m_A.graph.row_map[iRow];
+    const size_type iEntryEnd   = m_A.graph.row_map[iRow+1];
+
+    double sum = 0 ;
+
+#if defined( __INTEL_COMPILER )
+#pragma simd reduction(+:sum)
+#pragma ivdep
+    for ( size_type iEntry = iEntryBegin ; iEntry < iEntryEnd ; ++iEntry ) {
+      sum += m_A.coefficients(iEntry) * m_x( m_A.graph.entries(iEntry) );
+    }
+#else
+    for ( size_type iEntry = iEntryBegin ; iEntry < iEntryEnd ; ++iEntry ) {
+      sum += m_A.coefficients(iEntry) * m_x( m_A.graph.entries(iEntry) );
+    }
+#endif
+
+    m_y(iRow) = sum ;
+  }
+
+  Multiply( const matrix_type & A ,
+            const size_type nrow ,
+            const size_type , // ncol ,
+            const vector_type & x ,
+            const vector_type & y )
+    : m_A( A ), m_x( x ), m_y( y )
+  {
+    parallel_for( nrow , *this );
+  }
+};
+
+//----------------------------------------------------------------------------
+
+} // namespace Impl
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+
+//----------------------------------------------------------------------------
+
+template< typename AScalarType ,
+          typename VScalarType ,
+          class Device >
+class Operator {
+  typedef CrsMatrix<AScalarType,Device>  matrix_type ;
+  typedef View<VScalarType*,Device>     vector_type ;
+
+private:
+  const CrsMatrix<AScalarType,Device> A ;
+
+  ParallelDataMap                                         data_map ;
+  AsyncExchange< VScalarType , Device , ParallelDataMap > exchange ;
+
+public:
+
+  Operator( const ParallelDataMap                  & arg_data_map ,
+            const CrsMatrix<AScalarType,Device>    & arg_A )
+    : A( arg_A )
+    , data_map( arg_data_map )
+    , exchange( arg_data_map , 1 )
+    {}
+
+  void apply( const View<VScalarType*,Device>  & x ,
+              const View<VScalarType*,Device>  & y )
+  {
+    // Gather off-processor data for 'x'
+
+    PackArray< vector_type >::pack( exchange.buffer() ,
+                                    data_map.count_interior ,
+                                    data_map.count_send , x );
+
+    exchange.setup();
+
+    // If interior & boundary matrices then could launch interior multiply
+
+    exchange.send_receive();
+
+    UnpackArray< vector_type >::unpack( x , exchange.buffer() ,
+                                        data_map.count_owned ,
+                                        data_map.count_receive );
+
+    const typename Device::size_type nrow = data_map.count_owned ;
+    const typename Device::size_type ncol = data_map.count_owned +
+                                            data_map.count_receive ;
+
+    Impl::Multiply<matrix_type,vector_type,vector_type>( A, nrow, ncol, x, y);
+  }
+};
+
+//----------------------------------------------------------------------------
+
+template< typename AScalarType , typename VScalarType , class Device >
+void cgsolve(
+  const ParallelDataMap                 data_map ,
+  const CrsMatrix<AScalarType,Device>   A ,
+  const View<VScalarType*,Device> b ,
+  const View<VScalarType*,Device> x ,
+  size_t & iteration ,
+  double & normr ,
+  double & iter_time ,
+  const size_t maximum_iteration = 200 ,
+  const double tolerance = std::numeric_limits<VScalarType>::epsilon() )
+{
+  typedef View<VScalarType*,Device> vector_type ;
+  //typedef View<VScalarType,  Device> value_type ; // unused
+
+  const size_t count_owned = data_map.count_owned ;
+  const size_t count_total = data_map.count_owned + data_map.count_receive ;
+
+  Operator<AScalarType,VScalarType,Device> matrix_operator( data_map , A );
+
+  // Need input vector to matvec to be owned + received
+  vector_type pAll ( "cg::p" , count_total );
+
+  vector_type p = Kokkos::subview( pAll , std::pair<size_t,size_t>(0,count_owned) );
+  vector_type r ( "cg::r" , count_owned );
+  vector_type Ap( "cg::Ap", count_owned );
+
+  /* r = b - A * x ; */
+
+  /* p  = x      */ deep_copy( p , x );
+  /* Ap = A * p  */ matrix_operator.apply( pAll , Ap );
+  /* r  = b - Ap */ waxpby( count_owned , 1.0 , b , -1.0 , Ap , r );
+  /* p  = r      */ deep_copy( p , r );
+
+  double old_rdot = dot( count_owned , r , data_map.machine );
+
+  normr     = sqrt( old_rdot );
+  iteration = 0 ;
+
+  Kokkos::Timer wall_clock ;
+
+  while ( tolerance < normr && iteration < maximum_iteration ) {
+
+    /* pAp_dot = dot( p , Ap = A * p ) */
+
+    /* Ap = A * p  */ matrix_operator.apply( pAll , Ap );
+
+    const double pAp_dot = dot( count_owned , p , Ap , data_map.machine );
+    const double alpha   = old_rdot / pAp_dot ;
+
+    /* x += alpha * p ;  */ axpy( count_owned,  alpha, p , x );
+    /* r -= alpha * Ap ; */ axpy( count_owned, -alpha, Ap, r );
+
+    const double r_dot = dot( count_owned , r , data_map.machine );
+    const double beta  = r_dot / old_rdot ;
+
+    /* p = r + beta * p ; */ xpby( count_owned , r , beta , p );
+
+    normr = sqrt( old_rdot = r_dot );
+    ++iteration ;
+  }
+
+  iter_time = wall_clock.seconds();
+}
+
+//----------------------------------------------------------------------------
+
+} // namespace Kokkos
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+#if ( CUDA_VERSION < 6000 )
+#pragma message "cusparse_v2.h"
+#include <cusparse_v2.h>
+#else
+#pragma message "cusparse.h"
+#include <cusparse.h>
+#endif
+
+namespace Kokkos {
+namespace Impl {
+
+struct CudaSparseSingleton {
+  cusparseHandle_t   handle;
+  cusparseMatDescr_t descra;
+
+  CudaSparseSingleton()
+  {
+    cusparseCreate( & handle );
+    cusparseCreateMatDescr( & descra );
+    cusparseSetMatType(       descra , CUSPARSE_MATRIX_TYPE_GENERAL );
+    cusparseSetMatIndexBase(  descra , CUSPARSE_INDEX_BASE_ZERO );
+  }
+
+  static CudaSparseSingleton & singleton();
+
+};
+
+template<>
+struct Multiply< CrsMatrix<double,Cuda> ,
+                 View<double*,Cuda > ,
+                 View<double*,Cuda > >
+{
+  typedef Cuda                                      execution_space ;
+  typedef execution_space::size_type                    size_type ;
+  typedef double                                    scalar_type ;
+  typedef View< scalar_type* , execution_space >        vector_type ;
+  typedef CrsMatrix< scalar_type , execution_space >    matrix_type ;
+
+public:
+
+  Multiply( const matrix_type & A ,
+            const size_type nrow ,
+            const size_type ncol ,
+            const vector_type & x ,
+            const vector_type & y )
+  {
+    CudaSparseSingleton & s = CudaSparseSingleton::singleton();
+    const scalar_type alpha = 1 , beta = 0 ;
+
+    cusparseStatus_t status =
+      cusparseDcsrmv( s.handle ,
+                      CUSPARSE_OPERATION_NON_TRANSPOSE ,
+                      nrow , ncol , A.coefficients.dimension_0() ,
+                      &alpha ,
+                      s.descra ,
+                      A.coefficients.ptr_on_device() ,
+                      A.graph.row_map.ptr_on_device() ,
+                      A.graph.entries.ptr_on_device() ,
+                      x.ptr_on_device() ,
+                      &beta ,
+                      y.ptr_on_device() );
+
+    if ( CUSPARSE_STATUS_SUCCESS != status ) {
+      throw std::runtime_error( std::string("ERROR - cusparseDcsrmv " ) );
+    }
+  }
+};
+
+
+template<>
+struct Multiply< CrsMatrix<float,Cuda> ,
+                 View<float*,Cuda > ,
+                 View<float*,Cuda > >
+{
+  typedef Cuda                                      execution_space ;
+  typedef execution_space::size_type                    size_type ;
+  typedef float                                     scalar_type ;
+  typedef View< scalar_type* , execution_space >        vector_type ;
+  typedef CrsMatrix< scalar_type , execution_space >    matrix_type ;
+
+public:
+
+  Multiply( const matrix_type & A ,
+            const size_type nrow ,
+            const size_type ncol ,
+            const vector_type & x ,
+            const vector_type & y )
+  {
+    CudaSparseSingleton & s = CudaSparseSingleton::singleton();
+    const scalar_type alpha = 1 , beta = 0 ;
+
+    cusparseStatus_t status =
+      cusparseScsrmv( s.handle ,
+                      CUSPARSE_OPERATION_NON_TRANSPOSE ,
+                      nrow , ncol , A.coefficients.dimension_0() ,
+                      &alpha ,
+                      s.descra ,
+                      A.coefficients.ptr_on_device() ,
+                      A.graph.row_map.ptr_on_device() ,
+                      A.graph.entries.ptr_on_device() ,
+                      x.ptr_on_device() ,
+                      &beta ,
+                      y.ptr_on_device() );
+
+    if ( CUSPARSE_STATUS_SUCCESS != status ) {
+      throw std::runtime_error( std::string("ERROR - cusparseDcsrmv " ) );
+    }
+  }
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+#endif /* #if defined( KOKKOS_HAVE_CUDA ) */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef SPARSELINEARSYSTEM_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/SparseLinearSystemFill.hpp b/lib/kokkos/example/multi_fem/SparseLinearSystemFill.hpp
new file mode 100644
index 0000000000..78680cfb6a
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/SparseLinearSystemFill.hpp
@@ -0,0 +1,276 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef SPARSELINEARSYSTEMFILL_HPP
+#define SPARSELINEARSYSTEMFILL_HPP
+
+#include <vector>
+#include <algorithm>
+#include <limits>
+
+#include <FEMesh.hpp>
+#include <SparseLinearSystem.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace HybridFEM {
+
+template< class MatrixType , class MeshType ,
+          class elem_matrices_type ,
+          class elem_vectors_type > struct GatherFill ;
+
+
+template< typename ScalarType ,
+          class    DeviceType ,
+          unsigned ElemNode ,
+          typename CoordScalarType ,
+          class elem_matrices_type ,
+          class elem_vectors_type >
+struct GatherFill< 
+  Kokkos::CrsMatrix< ScalarType , DeviceType > ,
+  FEMesh< CoordScalarType , ElemNode , DeviceType > ,
+  elem_matrices_type , elem_vectors_type >
+{
+  typedef DeviceType     execution_space ;
+  typedef typename execution_space::size_type  size_type ;
+
+  static const size_type ElemNodeCount = ElemNode ;
+
+  typedef Kokkos::CrsMatrix< ScalarType , execution_space >    matrix_type ;
+  typedef typename matrix_type::coefficients_type   coefficients_type ;
+  typedef Kokkos::View< ScalarType[] , execution_space >  vector_type ;
+  typedef Kokkos::View< size_type[][ElemNodeCount][ElemNodeCount] , execution_space >       elem_graph_type ;
+
+  typedef FEMesh< CoordScalarType , ElemNodeCount , execution_space > mesh_type ;
+  typedef typename mesh_type::node_elem_ids_type node_elem_ids_type ;
+
+private:
+
+  node_elem_ids_type  node_elem_ids ;
+  elem_graph_type     elem_graph ;
+  elem_matrices_type  elem_matrices ;
+  elem_vectors_type   elem_vectors ;
+  coefficients_type   system_coeff ;
+  vector_type         system_rhs ;
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( size_type irow ) const
+  {
+    const size_type node_elem_begin = node_elem_ids.row_map[irow];
+    const size_type node_elem_end   = node_elem_ids.row_map[irow+1];
+
+    //  for each element that a node belongs to 
+
+    for ( size_type i = node_elem_begin ; i < node_elem_end ; i++ ) {
+
+      const size_type elem_id   = node_elem_ids.entries( i, 0);
+      const size_type row_index = node_elem_ids.entries( i, 1);
+
+      system_rhs(irow) += elem_vectors(elem_id, row_index);
+
+      //  for each node in a particular related element  
+      //  gather the contents of the element stiffness
+      //  matrix that belong in irow
+
+      for ( size_type j = 0 ; j < ElemNodeCount ; ++j ){
+        const size_type A_index = elem_graph( elem_id , row_index , j );
+
+        system_coeff( A_index ) += elem_matrices( elem_id, row_index, j );
+      }
+    }
+  }
+
+
+  static void apply( const matrix_type & matrix ,
+                     const vector_type & rhs ,
+                     const mesh_type   & mesh ,
+                     const elem_graph_type    & elem_graph ,
+                     const elem_matrices_type & elem_matrices ,
+                     const elem_vectors_type  & elem_vectors )
+  {
+    const size_t row_count = matrix.graph.row_map.dimension_0() - 1 ;
+    GatherFill op ;
+    op.node_elem_ids = mesh.node_elem_ids ;
+    op.elem_graph    = elem_graph ;
+    op.elem_matrices = elem_matrices ;
+    op.elem_vectors  = elem_vectors ;
+    op.system_coeff  = matrix.coefficients ;
+    op.system_rhs    = rhs ;
+
+    parallel_for( row_count , op );
+  }
+};
+
+} /* namespace HybridFEM */
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace HybridFEM {
+
+template< class GraphType , class MeshType >
+struct GraphFactory {
+  typedef GraphType                         graph_type ;
+  typedef MeshType                          mesh_type ;
+  typedef typename graph_type::execution_space  execution_space ;
+  typedef typename execution_space::size_type   size_type  ;
+
+  static const unsigned ElemNodeCount = mesh_type::element_node_count ;
+
+  typedef Kokkos::View< size_type[][ElemNodeCount][ElemNodeCount] , execution_space >         element_map_type ;
+
+  static
+  void
+  create( const mesh_type & mesh ,
+          graph_type & graph ,
+          element_map_type & elem_map )
+  {
+    typename mesh_type::node_elem_ids_type::HostMirror
+      node_elem_ids = create_mirror( mesh.node_elem_ids );
+
+    typename mesh_type::elem_node_ids_type::HostMirror
+      elem_node_ids = create_mirror( mesh.elem_node_ids );
+
+    typedef typename element_map_type::HostMirror element_map_host_type ;
+
+    deep_copy( elem_node_ids , mesh.elem_node_ids );
+    deep_copy( node_elem_ids.entries , mesh.node_elem_ids.entries );
+
+    const size_t owned_node = mesh.parallel_data_map.count_owned ;
+    const size_t total_elem = mesh.elem_node_ids.dimension_0();
+
+    if ( total_elem ) {
+      elem_map = element_map_type( std::string("element_map"), total_elem );
+    }
+
+    element_map_host_type elem_map_host = create_mirror( elem_map );
+
+    //------------------------------------
+    //  Node->node mapping for the CrsMatrix graph
+
+    std::vector< std::vector< unsigned > > node_node_ids( owned_node );
+    std::vector< unsigned > node_node_begin( owned_node );
+
+    size_t offset = 0 ;
+    for ( size_t i = 0 ; i < owned_node ; ++i ) {
+      const size_t j_end = node_elem_ids.row_map[i+1];
+            size_t j     = node_elem_ids.row_map[i];
+
+      node_node_begin[i] = offset ;
+
+      std::vector< unsigned > & work = node_node_ids[i] ;
+
+      for ( ; j < j_end ; ++j ) {
+        const size_t elem_id = node_elem_ids.entries(j,0);
+        for ( size_t k = 0 ; k < ElemNodeCount ; ++k ) {
+          work.push_back( elem_node_ids( elem_id , k ) );
+        }
+      }
+
+      std::sort( work.begin() , work.end() );
+
+      work.erase( std::unique( work.begin() , work.end() ) , work.end() );
+
+      offset += work.size();
+    }
+
+    graph = Kokkos::create_staticcrsgraph< graph_type >( "node_node_ids" , node_node_ids );
+
+    //------------------------------------
+    // ( element , node_row , node_column ) -> matrix_crs_column
+
+    for ( size_t elem_id = 0 ; elem_id < total_elem ; ++elem_id ) {
+      for ( size_t i = 0 ; i < ElemNodeCount ; ++i ) {
+
+        const size_t node_row = elem_node_ids( elem_id , i );
+        const size_t node_row_begin = node_node_begin[ node_row ];
+        const std::vector< unsigned > & column = node_node_ids[ node_row ] ;
+
+        if ( owned_node <= node_row ) {
+          for ( unsigned j = 0 ; j < ElemNodeCount ; ++j ) {
+            elem_map_host( elem_id , i , j ) = std::numeric_limits<size_type>::max();
+          }
+        }
+        else {
+
+          for ( unsigned j = 0 ; j < ElemNodeCount ; ++j ) {
+            const size_type node_col = elem_node_ids( elem_id , j );
+
+            int col_search = 0 ;
+
+            for ( int len = column.size() ; 0 < len ; ) {
+
+              const int half = len >> 1;
+              const int middle = col_search + half ;
+
+              if ( column[middle] < node_col ){
+                col_search = middle + 1 ;
+                len -= half + 1 ;
+              }
+              else {
+                len = half ;
+              }
+            }
+if ( node_col != column[col_search] ) {
+  throw std::runtime_error(std::string("Failed"));
+}
+            elem_map_host( elem_id , i , j ) = col_search + node_row_begin ;
+          }
+        }
+      }
+    }
+
+    deep_copy( elem_map , elem_map_host );
+  }
+};
+
+} // namespace HybridFEM
+
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef SPARSELINEARSYSTEMFILL_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/SparseLinearSystem_Cuda.hpp b/lib/kokkos/example/multi_fem/SparseLinearSystem_Cuda.hpp
new file mode 100644
index 0000000000..3b22d4c5d0
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/SparseLinearSystem_Cuda.hpp
@@ -0,0 +1,164 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef SPARSELINEARSYSTEM_CUDA_HPP
+#define SPARSELINEARSYSTEM_CUDA_HPP
+
+#if defined( BUILD_FROM_CU_FILE )
+
+#include <cusparse_v2.h>
+#include <Kokkos_Core.hpp>
+
+namespace Kokkos {
+namespace Impl {
+
+
+struct CudaSparseSingleton {
+  cusparseHandle_t   handle;
+  cusparseMatDescr_t descra;
+
+  CudaSparseSingleton()
+  {
+    cusparseCreate( & handle );
+    cusparseCreateMatDescr( & descra );
+    cusparseSetMatType(       descra , CUSPARSE_MATRIX_TYPE_GENERAL );
+    cusparseSetMatIndexBase(  descra , CUSPARSE_INDEX_BASE_ZERO );
+  }
+
+  static CudaSparseSingleton & singleton();
+
+};
+
+CudaSparseSingleton & CudaSparseSingleton::singleton()
+{ static CudaSparseSingleton s ; return s ; }
+
+
+template<>
+struct Multiply< CrsMatrix<double,Cuda> ,
+                 View<double*,Cuda > ,
+                 View<double*,Cuda > >
+{
+  typedef Cuda                                      execution_space ;
+  typedef execution_space::size_type                    size_type ;
+  typedef double                                    scalar_type ;
+  typedef View< scalar_type* , execution_space >        vector_type ;
+  typedef CrsMatrix< scalar_type , execution_space >    matrix_type ;
+
+public:
+
+  Multiply( const matrix_type & A ,
+            const size_type nrow ,
+            const size_type ncol ,
+            const vector_type & x ,
+            const vector_type & y )
+  {
+    CudaSparseSingleton & s = CudaSparseSingleton::singleton();
+    const scalar_type alpha = 1 , beta = 0 ;
+
+    cusparseStatus_t status =
+      cusparseDcsrmv( s.handle ,
+                      CUSPARSE_OPERATION_NON_TRANSPOSE ,
+                      nrow , ncol , A.coefficients.dimension_0() ,
+                      &alpha ,
+                      s.descra ,
+                      A.coefficients.ptr_on_device() ,
+                      A.graph.row_map.ptr_on_device() ,
+                      A.graph.entries.ptr_on_device() ,
+                      x.ptr_on_device() ,
+                      &beta ,
+                      y.ptr_on_device() );
+
+    if ( CUSPARSE_STATUS_SUCCESS != status ) {
+      throw std::runtime_error( std::string("ERROR - cusparseDcsrmv " ) );
+    }
+  }
+};
+
+
+template<>
+struct Multiply< CrsMatrix<float,Cuda> ,
+                 View<float*,Cuda > ,
+                 View<float*,Cuda > >
+{
+  typedef Cuda                                      execution_space ;
+  typedef execution_space::size_type                    size_type ;
+  typedef float                                     scalar_type ;
+  typedef View< scalar_type* , execution_space >        vector_type ;
+  typedef CrsMatrix< scalar_type , execution_space >    matrix_type ;
+
+public:
+
+  Multiply( const matrix_type & A ,
+            const size_type nrow ,
+            const size_type ncol ,
+            const vector_type & x ,
+            const vector_type & y )
+  {
+    CudaSparseSingleton & s = CudaSparseSingleton::singleton();
+    const scalar_type alpha = 1 , beta = 0 ;
+
+    cusparseStatus_t status =
+      cusparseScsrmv( s.handle ,
+                      CUSPARSE_OPERATION_NON_TRANSPOSE ,
+                      nrow , ncol , A.coefficients.dimension_0() ,
+                      &alpha ,
+                      s.descra ,
+                      A.coefficients.ptr_on_device() ,
+                      A.graph.row_map.ptr_on_device() ,
+                      A.graph.entries.ptr_on_device() ,
+                      x.ptr_on_device() ,
+                      &beta ,
+                      y.ptr_on_device() );
+
+    if ( CUSPARSE_STATUS_SUCCESS != status ) {
+      throw std::runtime_error( std::string("ERROR - cusparseDcsrmv " ) );
+    }
+  }
+};
+
+} /* namespace Impl */
+} /* namespace Kokkos */
+
+#endif /* #if defined( __CUDACC__ ) */
+#endif /* #ifndef SPARSELINEARSYSTEM_CUDA_HPP */
+
diff --git a/lib/kokkos/example/multi_fem/TestBoxMeshFixture.hpp b/lib/kokkos/example/multi_fem/TestBoxMeshFixture.hpp
new file mode 100644
index 0000000000..9cc32b6b10
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/TestBoxMeshFixture.hpp
@@ -0,0 +1,242 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef TESTFEMESHBOXFIXTURE_HPP
+#define TESTFEMESHBOXFIXTURE_HPP
+
+#include <stdio.h>
+#include <iostream>
+#include <stdexcept>
+#include <limits>
+#include <utility>
+#include <BoxMeshFixture.hpp>
+
+#include <ParallelComm.hpp>
+
+//----------------------------------------------------------------------------
+
+namespace TestFEMesh {
+
+template< class ViewType >
+struct VerifyUnpack  ;
+
+template< typename DeviceType, typename T >
+struct VerifyUnpack< Kokkos::View< T*[3] , DeviceType > >
+{
+  typedef DeviceType     execution_space ;
+  typedef typename execution_space::size_type  size_type ;
+  typedef size_type               value_type ;
+
+  typedef Kokkos::View< T* ,    execution_space > buffer_type ;
+  typedef Kokkos::View< T*[3] , execution_space > array_type ;
+
+private:
+
+  array_type  node_coords ;
+  buffer_type buffer ;
+  size_type   node_begin ;
+
+public:
+
+  KOKKOS_INLINE_FUNCTION
+  static void init( value_type & update )
+  { update = 0 ; }
+
+  KOKKOS_INLINE_FUNCTION
+  static void join( volatile value_type & update ,
+                    const volatile value_type & source )
+  { update += source ; }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator()( const size_type i , value_type & update ) const
+  {
+    const size_type node_id = i + node_begin ;
+    const size_type k = i * 3 ;
+
+    const long xb = buffer[k];
+    const long yb = buffer[k+1];
+    const long zb = buffer[k+2];
+    const long xn = node_coords(node_id,0);
+    const long yn = node_coords(node_id,1);
+    const long zn = node_coords(node_id,2);
+
+    if ( xb != xn || yb != yn || zb != zn ) {
+      printf("TestFEMesh::VerifyUnpack failed at %d : node %d : { %ld %ld %ld } != { %ld %ld %ld }\n",
+             (int)i,(int)node_id, xb,yb,zb, xn, yn, zn );
+      ++update ;
+    }
+  }
+
+  static inline
+  size_type unpack( const array_type  & arg_node_coords ,
+                    const size_type     arg_node_begin ,
+                    const size_type     arg_node_count ,
+                    const buffer_type & arg_buffer )
+  {
+    VerifyUnpack op ;
+    op.node_coords = arg_node_coords ;
+    op.buffer      = arg_buffer ;
+    op.node_begin  = arg_node_begin ;
+    size_type count = 0 ;
+    Kokkos::parallel_reduce( arg_node_count , op , count );
+    return count ;
+  }
+};
+
+}
+
+//----------------------------------------------------------------------------
+
+#ifdef KOKKOS_HAVE_MPI
+
+namespace TestFEMesh {
+
+template< typename coordinate_scalar_type ,
+          unsigned ElemNodeCount ,
+          class Device >
+void verify_parallel(
+  const HybridFEM::FEMesh< coordinate_scalar_type ,
+                           ElemNodeCount ,
+                           Device > & mesh )
+{
+  typedef HybridFEM::FEMesh< coordinate_scalar_type, ElemNodeCount, Device > femesh_type ;
+  typedef typename femesh_type::node_coords_type node_coords_type ;
+
+  comm::Machine machine = mesh.parallel_data_map.machine ;
+
+  // Communicate node coordinates to verify communication and setup.
+
+  const size_t chunk_size = 3 ;
+
+  Kokkos::AsyncExchange< coordinate_scalar_type, Device, Kokkos::ParallelDataMap >
+    exchange( mesh.parallel_data_map , chunk_size );
+
+  const size_t send_begin = mesh.parallel_data_map.count_interior ;
+  const size_t send_count = mesh.parallel_data_map.count_send ;
+
+  const size_t recv_begin = mesh.parallel_data_map.count_owned ;
+  const size_t recv_count = mesh.parallel_data_map.count_receive ;
+
+  typedef Kokkos::PackArray< node_coords_type > pack_type ;
+
+  pack_type::pack( exchange.buffer(), send_begin, send_count, mesh.node_coords );
+
+  exchange.setup();
+
+  // Launch local-action device kernels
+
+  exchange.send_receive();
+
+  unsigned long local[3] ;
+  local[0] = mesh.parallel_data_map.count_owned ;
+  local[1] = mesh.parallel_data_map.count_receive ;
+  local[2] = TestFEMesh::VerifyUnpack< node_coords_type >::unpack( mesh.node_coords, recv_begin, recv_count, exchange.buffer() );
+
+  unsigned long global[3] = { 0 , 0 , 0 };
+
+  MPI_Allreduce( local , global ,
+                 3 , MPI_UNSIGNED_LONG , MPI_SUM , machine.mpi_comm );
+
+  if ( 0 == comm::rank( machine ) ) {
+    std::cout << ( global[2] ? "FAILED" : "PASSED" )
+              << ": TestFEMesh::verify_parallel "
+              << "NP(" << comm::size( machine )
+              << ") total_node(" << global[0]
+              << ") verified_nodes(" << global[1]
+              << ") failed_nodes(" << global[2]
+              << ")" << std::endl ;
+  }
+}
+
+} // namespace TestFEMesh
+
+#else /* ! #ifdef KOKKOS_HAVE_MPI */
+
+namespace TestFEMesh {
+
+template< typename coordinate_scalar_type ,
+          unsigned ElemNodeCount ,
+          class Device >
+void verify_parallel(
+  const HybridFEM::FEMesh< coordinate_scalar_type ,
+                           ElemNodeCount ,
+                           Device > & )
+{}
+
+} // namespace TestFEMesh
+
+#endif /* ! #ifdef KOKKOS_HAVE_MPI */
+
+//----------------------------------------------------------------------------
+
+template< class Device >
+void test_box_fixture( comm::Machine machine ,
+                       const size_t gang_count ,
+                       const size_t nodes_nx ,
+                       const size_t nodes_ny ,
+                       const size_t nodes_nz )
+{
+  typedef long                coordinate_scalar_type ;
+  typedef FixtureElementHex8  fixture_element_type ;
+
+  typedef BoxMeshFixture< coordinate_scalar_type ,
+                          Device ,
+                          fixture_element_type > fixture_type ;
+
+  typedef typename fixture_type::FEMeshType  mesh_type ;
+
+  const size_t proc_count = comm::size( machine );
+  const size_t proc_local = comm::rank( machine ) ;
+
+  mesh_type mesh =
+    fixture_type::create( proc_count , proc_local , gang_count ,
+                          nodes_nx - 1 , nodes_ny - 1 , nodes_nz - 1 );
+
+  mesh.parallel_data_map.machine = machine ;
+
+  TestFEMesh::verify_parallel( mesh );
+}
+
+#endif /* #ifndef TESTFEMESHBOXFIXTURE_HPP */
+
+
diff --git a/lib/kokkos/example/multi_fem/TestBoxMeshPartition.cpp b/lib/kokkos/example/multi_fem/TestBoxMeshPartition.cpp
new file mode 100644
index 0000000000..ffaeeb6af5
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/TestBoxMeshPartition.cpp
@@ -0,0 +1,172 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+#include <iostream>
+#include <stdexcept>
+#include <limits>
+#include <utility>
+#include <BoxMeshPartition.hpp>
+
+//----------------------------------------------------------------------------
+
+void test_box_partition( bool print )
+{
+  const size_t np_max = 10000 ;
+
+  const BoxBoundsLinear use_box ;
+
+  BoxType root_box ;
+
+  root_box[0][0] = 0 ; root_box[0][1] = 100 ;
+  root_box[1][0] = 0 ; root_box[1][1] = 200 ;
+  root_box[2][0] = 0 ; root_box[2][1] = 300 ;
+
+  const size_t cell_total =
+    ( root_box[0][1] - root_box[0][0] ) *
+    ( root_box[1][1] - root_box[1][0] ) *
+    ( root_box[2][1] - root_box[2][0] );
+
+  for ( size_t np = 2 ; np < np_max ; np = 2 * ( np + 1 ) ) {
+
+    std::vector<BoxType> part_boxes( np );
+
+    box_partition_rcb( root_box , part_boxes );
+
+    size_t cell_goal = ( cell_total + np - 1 ) / np ;
+    size_t cell_max = 0 ;
+
+    for ( size_t i = 0 ; i < np ; ++i ) {
+      cell_max = std::max( cell_max , count( part_boxes[i] ) );
+    }
+
+    if ( print ) {
+      std::cout << std::endl
+                << "box_part( " << np 
+                << " ) max( " << cell_max
+                << " ) goal( " << cell_goal
+                << " ) ratio( " << double(cell_max) / double(cell_goal)
+                << " )" << std::endl ;
+    }
+
+    const size_t nsample = std::min(np,(size_t)4);
+    const size_t stride = ( np + nsample - 1 ) / nsample ;
+
+    for ( size_t my_part = 0 ; my_part < np ; my_part += stride ) {
+      BoxType             my_use_box ;
+      std::vector<size_t> my_use_id_map ;
+      size_t              my_count_interior ;
+      size_t              my_count_owned ;
+      size_t              my_count_uses ;
+      std::vector<size_t> my_recv_counts ;
+      std::vector<std::vector<size_t> > my_send_map ;
+
+      size_t count_verify = 0 ;
+
+      box_partition_maps( root_box , part_boxes ,
+                          use_box , my_part ,
+                          my_use_box , my_use_id_map ,
+                          my_count_interior ,
+                          my_count_owned ,
+                          my_count_uses ,
+                          my_recv_counts ,
+                          my_send_map );
+
+      count_verify = my_count_owned ;
+
+      if ( print ) {
+        std::cout << "  my_part(" << my_part << ") layout { "
+                  << "P" << my_part
+                  << "(" << my_count_interior
+                  << "," << ( my_count_owned - my_count_interior )
+                  << ")" ;
+      }
+
+      for ( size_t i = 1 ; i < np ; ++i ) {
+        if ( my_recv_counts[i] ) {
+          count_verify += my_recv_counts[i] ;
+          const size_t ip = ( my_part + i ) % np ;
+
+          if ( print ) {
+            std::cout << " P" << ip << "(" << my_recv_counts[i] << ")" ;
+          }
+
+          // Compare recv & send lists
+
+          BoxType             ip_use_box ;
+          std::vector<size_t> ip_use_id_map ;
+          size_t              ip_count_interior ;
+          size_t              ip_count_owned ;
+          size_t              ip_count_uses ;
+          std::vector<size_t> ip_recv_counts ;
+          std::vector<std::vector<size_t> > ip_send_map ;
+
+          box_partition_maps( root_box , part_boxes ,
+                              use_box , ip ,
+                              ip_use_box , ip_use_id_map ,
+                              ip_count_interior ,
+                              ip_count_owned ,
+                              ip_count_uses ,
+                              ip_recv_counts ,
+                              ip_send_map );
+
+          // Sent by ip, received by my_part:
+
+          const BoxType recv_send = intersect( part_boxes[ip] , my_use_box );
+          const size_t recv_send_count = count( recv_send );
+
+          const size_t j = ( my_part + np - ip ) % np ;
+
+          if ( recv_send_count != my_recv_counts[i] ||
+               recv_send_count != ip_send_map[j].size() ) {
+            throw std::runtime_error( std::string("bad recv/send map") );
+          }
+        }
+      }
+      if ( print ) { std::cout << " }" << std::endl ; }
+
+      if ( count_verify != my_count_uses ) {
+        throw std::runtime_error( std::string("bad partition map") );
+      }
+    }
+  }
+}
+
+
diff --git a/lib/kokkos/example/multi_fem/TestCuda.cpp b/lib/kokkos/example/multi_fem/TestCuda.cpp
new file mode 100644
index 0000000000..11370a5350
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/TestCuda.cpp
@@ -0,0 +1,192 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+
+#include <TestBoxMeshFixture.hpp>
+#include <Implicit.hpp>
+#include <Nonlinear.hpp>
+#include <Explicit.hpp>
+
+#include <SparseLinearSystem.hpp>
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+//----------------------------------------------------------------------------
+
+namespace Kokkos {
+namespace Impl {
+
+CudaSparseSingleton & CudaSparseSingleton::singleton()
+{ static CudaSparseSingleton s ; return s ; }
+
+}
+}
+
+//----------------------------------------------------------------------------
+
+void test_cuda_query( comm::Machine machine )
+{
+  const size_t comm_rank = comm::rank( machine );
+  std::cout << "P" << comm_rank
+            << ": Cuda device_count = "
+            << Kokkos::Cuda::detect_device_count()
+            << std::endl ;
+}
+
+//----------------------------------------------------------------------------
+
+void test_cuda_fixture( comm::Machine machine ,
+                        size_t nx , size_t ny , size_t nz )
+{
+  const size_t comm_rank = comm::rank( machine );
+  const size_t comm_size = comm::size( machine );
+  const size_t dev_count = Kokkos::Cuda::detect_device_count();
+  const size_t dev_rank =
+    dev_count && dev_count <= comm_size ? comm_rank % dev_count : 0 ;
+  const size_t gang_count = 0 ;
+
+  Kokkos::HostSpace::execution_space::initialize();
+  Kokkos::Cuda::SelectDevice select_device( dev_rank );
+  Kokkos::Cuda::initialize( select_device );
+  test_box_fixture<Kokkos::Cuda>( machine , gang_count , nx , ny , nz );
+  Kokkos::Cuda::finalize();
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+//----------------------------------------------------------------------------
+
+void test_cuda_implicit( comm::Machine machine , 
+                         size_t elem_count_begin ,
+                         size_t elem_count_end ,
+                         size_t count_run )
+{
+  const size_t comm_rank = comm::rank( machine );
+  const size_t comm_size = comm::size( machine );
+  const size_t dev_count = Kokkos::Cuda::detect_device_count();
+  const size_t dev_rank =
+    dev_count && dev_count <= comm_size ? comm_rank % dev_count : 0 ;
+  const size_t gang_count = 0 ;
+
+  Kokkos::HostSpace::execution_space::initialize();
+  Kokkos::Cuda::SelectDevice select_device( dev_rank );
+  Kokkos::Cuda::initialize( select_device );
+  HybridFEM::Implicit::driver<double,Kokkos::Cuda>( "Cuda" , machine , gang_count , elem_count_begin , elem_count_end , count_run );
+  Kokkos::Cuda::finalize();
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+//----------------------------------------------------------------------------
+
+void test_cuda_explicit( comm::Machine machine , 
+                         size_t elem_count_begin ,
+                         size_t elem_count_end ,
+                         size_t count_run )
+{
+  const size_t comm_rank = comm::rank( machine );
+  const size_t comm_size = comm::size( machine );
+  const size_t dev_count = Kokkos::Cuda::detect_device_count();
+  const size_t dev_rank =
+    dev_count && dev_count <= comm_size ? comm_rank % dev_count : 0 ;
+  const size_t gang_count = 0 ;
+
+  Kokkos::HostSpace::execution_space::initialize();
+  Kokkos::Cuda::SelectDevice select_device( dev_rank );
+  Kokkos::Cuda::initialize( select_device );
+  Explicit::driver<double,Kokkos::Cuda>( "Cuda" , machine , gang_count , elem_count_begin , elem_count_end , count_run );
+  Kokkos::Cuda::finalize();
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+//----------------------------------------------------------------------------
+
+void test_cuda_nonlinear( comm::Machine machine , 
+                          size_t elem_count_begin ,
+                          size_t elem_count_end ,
+                          size_t count_run )
+{
+  const size_t comm_rank = comm::rank( machine );
+  const size_t comm_size = comm::size( machine );
+  const size_t dev_count = Kokkos::Cuda::detect_device_count();
+  const size_t dev_rank =
+    dev_count && dev_count <= comm_size ? comm_rank % dev_count : 0 ;
+  const size_t gang_count = 0 ;
+
+  Kokkos::HostSpace::execution_space::initialize();
+  Kokkos::Cuda::SelectDevice select_device( dev_rank );
+  Kokkos::Cuda::initialize( select_device );
+
+  typedef Kokkos::Cuda device ;
+  typedef FixtureElementHex8 hex8 ;
+  HybridFEM::Nonlinear::driver<double,device,hex8>( "Cuda" , machine , gang_count , elem_count_begin , elem_count_end , count_run );
+  Kokkos::Cuda::finalize();
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+void test_cuda_nonlinear_quadratic( comm::Machine machine , 
+                                    size_t elem_count_begin ,
+                                    size_t elem_count_end ,
+                                    size_t count_run )
+{
+  const size_t comm_rank = comm::rank( machine );
+  const size_t comm_size = comm::size( machine );
+  const size_t dev_count = Kokkos::Cuda::detect_device_count();
+  const size_t dev_rank =
+    dev_count && dev_count <= comm_size ? comm_rank % dev_count : 0 ;
+  const size_t gang_count = 0 ;
+
+  Kokkos::HostSpace::execution_space::initialize();
+  Kokkos::Cuda::SelectDevice select_device( dev_rank );
+  Kokkos::Cuda::initialize( select_device );
+
+  typedef Kokkos::Cuda device ;
+  typedef FixtureElementHex27 hex27 ;
+  HybridFEM::Nonlinear::driver<double,device,hex27>( "Cuda" , machine , gang_count , elem_count_begin , elem_count_end , count_run );
+  Kokkos::Cuda::finalize();
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+//----------------------------------------------------------------------------
+
+#endif  /* #if defined( KOKKOS_HAVE_CUDA ) */
+
diff --git a/lib/kokkos/example/multi_fem/TestHost.cpp b/lib/kokkos/example/multi_fem/TestHost.cpp
new file mode 100644
index 0000000000..facdd0f28a
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/TestHost.cpp
@@ -0,0 +1,137 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+// Must be included first on Intel-Phi systems due to
+// redefinition of SEEK_SET in <mpi.h>.
+
+#include <ParallelComm.hpp>
+
+#include <iostream>
+#include <stdexcept>
+#include <limits>
+#include <utility>
+
+//----------------------------------------------------------------------------
+
+#include <Kokkos_Core.hpp>
+
+#include <BoxMeshFixture.hpp>
+#include <TestBoxMeshFixture.hpp>
+#include <Implicit.hpp>
+#include <Nonlinear.hpp>
+#include <Explicit.hpp>
+#include <SparseLinearSystem.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+void test_host_fixture( comm::Machine machine ,
+                        size_t gang_count ,
+                        size_t gang_worker_count ,
+                        size_t nx , size_t ny , size_t nz )
+{
+  Kokkos::HostSpace::execution_space::initialize( gang_count * gang_worker_count );
+  test_box_fixture<Kokkos::HostSpace::execution_space>( machine , gang_count , nx , ny , nz );
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+//----------------------------------------------------------------------------
+
+void test_host_implicit( comm::Machine machine ,
+                         size_t gang_count ,
+                         size_t gang_worker_count ,
+                         size_t elem_count_begin ,
+                         size_t elem_count_end ,
+                         size_t count_run )
+{
+  Kokkos::HostSpace::execution_space::initialize( gang_count * gang_worker_count );
+  HybridFEM::Implicit::driver<double,Kokkos::HostSpace::execution_space>( "Threads" , machine , gang_count , elem_count_begin , elem_count_end , count_run );
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+//----------------------------------------------------------------------------
+
+void test_host_explicit( comm::Machine machine ,
+                         size_t gang_count ,
+                         size_t gang_worker_count ,
+                         size_t elem_count_begin ,
+                         size_t elem_count_end ,
+                         size_t count_run )
+{
+  Kokkos::HostSpace::execution_space::initialize( gang_count * gang_worker_count );
+  Explicit::driver<double,Kokkos::HostSpace::execution_space>( "Threads" , machine , gang_count , elem_count_begin , elem_count_end , count_run );
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+void test_host_nonlinear( comm::Machine machine ,
+                          size_t gang_count ,
+                          size_t gang_worker_count ,
+                          size_t elem_count_begin ,
+                          size_t elem_count_end ,
+                          size_t count_run )
+{
+  Kokkos::HostSpace::execution_space::initialize( gang_count * gang_worker_count );
+  typedef FixtureElementHex8 hex8 ;
+  typedef Kokkos::HostSpace::execution_space             device ;
+  HybridFEM::Nonlinear::driver<double,device,hex8>( "Threads" , machine , gang_count , elem_count_begin , elem_count_end , count_run );
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+void test_host_nonlinear_quadratic( comm::Machine machine ,
+                                    size_t gang_count ,
+                                    size_t gang_worker_count ,
+                                    size_t elem_count_begin ,
+                                    size_t elem_count_end ,
+                                    size_t count_run )
+{
+  Kokkos::HostSpace::execution_space::initialize( gang_count * gang_worker_count );
+  typedef FixtureElementHex27 hex27 ;
+  typedef Kokkos::HostSpace::execution_space              device ;
+  HybridFEM::Nonlinear::driver<double,device,hex27>( "Threads" , machine , gang_count , elem_count_begin , elem_count_end , count_run );
+  Kokkos::HostSpace::execution_space::finalize();
+}
+
+//----------------------------------------------------------------------------
+
+
diff --git a/lib/kokkos/example/multi_fem/TestHybridFEM.cpp b/lib/kokkos/example/multi_fem/TestHybridFEM.cpp
new file mode 100644
index 0000000000..1bbd74e4d7
--- /dev/null
+++ b/lib/kokkos/example/multi_fem/TestHybridFEM.cpp
@@ -0,0 +1,348 @@
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+
+// Must be included first on Intel-Phi systems due to
+// redefinition of SEEK_SET in <mpi.h>.
+
+#include <ParallelComm.hpp>
+
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <Kokkos_hwloc.hpp>
+
+//----------------------------------------------------------------------------
+
+void test_box_partition( bool print );
+
+//----------------------------------------------------------------------------
+
+void test_host_fixture( comm::Machine machine ,
+                        size_t gang_count ,
+                        size_t gang_worker_count ,
+                        size_t nx , size_t ny , size_t nz );
+
+void test_host_implicit( comm::Machine machine ,
+                         size_t gang_count ,
+                         size_t gang_worker_count ,
+                         size_t elem_count_begin ,
+                         size_t elem_count_end ,
+                         size_t count_run );
+
+void test_host_explicit( comm::Machine machine ,
+                         size_t gang_count ,
+                         size_t gang_worker_count ,
+                         size_t elem_count_begin ,
+                         size_t elem_count_end ,
+                         size_t count_run );
+
+void test_host_nonlinear( comm::Machine machine ,
+                          size_t gang_count ,
+                          size_t gang_worker_count ,
+                          size_t elem_count_begin ,
+                          size_t elem_count_end ,
+                          size_t count_run );
+
+void test_host_nonlinear_quadratic( comm::Machine machine ,
+                                    size_t gang_count ,
+                                    size_t gang_worker_count ,
+                                    size_t elem_count_begin ,
+                                    size_t elem_count_end ,
+                                    size_t count_run );
+
+
+//----------------------------------------------------------------------------
+
+void test_cuda_query( comm::Machine );
+
+void test_cuda_fixture( comm::Machine machine ,
+                        size_t nx , size_t ny , size_t nz );
+
+void test_cuda_implicit( comm::Machine machine ,
+                         size_t elem_count_begin ,
+                         size_t elem_count_end ,
+                         size_t count_run );
+
+void test_cuda_explicit( comm::Machine machine ,
+                         size_t elem_count_begin ,
+                         size_t elem_count_end ,
+                         size_t count_run );
+
+void test_cuda_nonlinear( comm:: Machine machine ,
+                          size_t elem_count_begin ,
+                          size_t elem_count_end ,
+                          size_t count_run );
+
+void test_cuda_nonlinear_quadratic( comm::Machine machine ,
+                                    size_t elem_count_begin ,
+                                    size_t elem_count_end ,
+                                    size_t count_run );
+
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace {
+
+bool run_host( std::istream & input ,
+               comm::Machine machine ,
+               const size_t host_gang_count ,
+               const size_t host_gang_worker_count )
+{
+  bool cmd_error = false ;
+
+  std::string which ; input >> which ;
+
+  if ( which == std::string("fixture") ) {
+
+    size_t nx = 0 , ny = 0 , nz = 0 ;
+    input >> nx >> ny >> nz ;
+    test_host_fixture( machine , host_gang_count , host_gang_worker_count , nx , ny , nz );
+
+  }
+  else if ( which == std::string("explicit") ) {
+
+    size_t mesh_node_begin = 100 ;
+    size_t mesh_node_end   = 300 ;
+    size_t run             =   1 ;
+    input >> mesh_node_begin >> mesh_node_end >> run ;
+    test_host_explicit( machine , host_gang_count , host_gang_worker_count , mesh_node_begin , mesh_node_end , run );
+
+  }
+  else if ( which == std::string("implicit") ) {
+
+    size_t mesh_node_begin = 100 ;
+    size_t mesh_node_end   = 300 ;
+    size_t run             =   1 ;
+    input >> mesh_node_begin >> mesh_node_end >> run ;
+    test_host_implicit( machine , host_gang_count , host_gang_worker_count , mesh_node_begin , mesh_node_end , run );
+
+  }
+  else if ( which == std::string("nonlinear") ) {
+
+    size_t mesh_node_begin = 100 ;
+    size_t mesh_node_end   = 300 ;
+    size_t run             =   1 ;
+    input >> mesh_node_begin >> mesh_node_end >> run ;
+    test_host_nonlinear( machine , host_gang_count , host_gang_worker_count , mesh_node_begin , mesh_node_end , run );
+
+  }
+  else if ( which == std::string("nonlinear_quadratic") ) {
+
+    size_t mesh_node_begin = 100 ;
+    size_t mesh_node_end   = 300 ;
+    size_t run             =   1 ;
+    input >> mesh_node_begin >> mesh_node_end >> run ;
+    test_host_nonlinear_quadratic( machine , host_gang_count , host_gang_worker_count , mesh_node_begin , mesh_node_end , run );
+
+  }
+  else {
+    cmd_error = true ;
+  }
+
+  return cmd_error ;
+}
+
+#if defined( KOKKOS_HAVE_CUDA )
+bool run_cuda( std::istream & input , comm::Machine machine )
+{
+  bool cmd_error = false ;
+
+  std::string which ; input >> which ;
+
+  if ( which == std::string("fixture") ) {
+
+    size_t nx = 0 , ny = 0 , nz = 0 ;
+    input >> nx >> ny >> nz ;
+    test_cuda_fixture( machine , nx , ny , nz );
+
+  }
+  else if ( which == std::string("explicit") ) {
+
+    size_t mesh_node_begin = 100 ;
+    size_t mesh_node_end   = 300 ;
+    size_t run             =   1 ;
+    input >> mesh_node_begin >> mesh_node_end >> run ;
+    test_cuda_explicit( machine , mesh_node_begin , mesh_node_end , run );
+
+  }
+  else if ( which == std::string("implicit") ) {
+
+    size_t mesh_node_begin = 100 ;
+    size_t mesh_node_end   = 300 ;
+    size_t run             =   1 ;
+    input >> mesh_node_begin >> mesh_node_end >> run ;
+    test_cuda_implicit( machine , mesh_node_begin , mesh_node_end , run );
+
+  }
+  else if ( which == std::string("nonlinear") ) {
+
+    size_t mesh_node_begin = 100 ;
+    size_t mesh_node_end   = 300 ;
+    size_t run             =   1 ;
+    input >> mesh_node_begin >> mesh_node_end >> run ;
+    test_cuda_nonlinear( machine , mesh_node_begin , mesh_node_end , run );
+
+  }
+  else if ( which == std::string("nonlinear_quadratic") ) {
+
+    size_t mesh_node_begin = 100 ;
+    size_t mesh_node_end   = 300 ;
+    size_t run             =   1 ;
+    input >> mesh_node_begin >> mesh_node_end >> run ;
+    test_cuda_nonlinear_quadratic( machine , mesh_node_begin , mesh_node_end , run );
+
+  }
+  else {
+    cmd_error = true ;
+  }
+
+  return cmd_error ;
+}
+#endif
+
+void run( const std::string & argline , comm::Machine machine )
+{
+  const unsigned numa_count       = Kokkos::hwloc::get_available_numa_count();
+  const unsigned cores_per_numa   = Kokkos::hwloc::get_available_cores_per_numa();
+  const unsigned threads_per_core = Kokkos::hwloc::get_available_threads_per_core();
+
+  std::istringstream input( argline );
+
+  bool cmd_error = false ;
+
+  std::string which ; input >> which ;
+
+  if ( which == std::string("query") ) {
+    std::cout << "P" << comm::rank( machine )
+              << ": hwloc { NUMA[" << numa_count << "]"
+              << " CORE[" << cores_per_numa << "]"
+              << " PU[" << threads_per_core << "] }"
+              << std::endl ;
+#if defined( KOKKOS_HAVE_CUDA )
+    test_cuda_query( machine );
+#endif
+  }
+  else if ( which == std::string("partition") ) {
+    if ( 0 == comm::rank( machine ) ) {
+      test_box_partition( false /* print flag */ );
+    }
+  }
+  else {
+    if ( which == std::string("host") ) {
+      size_t host_gang_count = 0 ;
+      size_t host_gang_worker_count = 1 ;
+
+      input >> host_gang_count ;
+      input >> host_gang_worker_count ;
+
+      cmd_error = run_host( input , machine , host_gang_count , host_gang_worker_count );
+    }
+    else if ( which == std::string("host-all") ) {
+      size_t host_gang_count        = numa_count ;
+      size_t host_gang_worker_count = cores_per_numa * threads_per_core ;
+
+      cmd_error = run_host( input , machine , host_gang_count , host_gang_worker_count );
+    }
+    else if ( which == std::string("host-most") ) {
+      size_t host_gang_count        = numa_count ;
+      size_t host_gang_worker_count = ( cores_per_numa - 1 ) * threads_per_core ;
+
+      cmd_error = run_host( input , machine , host_gang_count , host_gang_worker_count );
+    }
+#if defined( KOKKOS_HAVE_CUDA )
+    else if ( which == std::string("cuda") ) {
+      cmd_error = run_cuda( input , machine );
+    }
+#endif
+    else {
+      cmd_error = true ;
+    }
+  }
+
+  if ( cmd_error && 0 == comm::rank( machine ) ) {
+    std::cout << "Expecting command line with" << std::endl
+              << "    query" << std::endl
+              << "    partition" << std::endl
+              << "    host NumNumaNode NumThreadPerNode <test>" << std::endl
+              << "    host-all <test>" << std::endl
+              << "    host-most <test>" << std::endl
+              << "    cuda <test>" << std::endl
+              << "where <test> is" << std::endl
+              << "    fixture   NumElemX NumElemY NumElemZ" << std::endl
+              << "    implicit  NumElemBegin NumElemEnd NumRun" << std::endl
+              << "    explicit  NumElemBegin NumElemEnd NumRun" << std::endl
+              << "    nonlinear NumElemBegin NumElemEnd NumRun" << std::endl
+              << "    nonlinear_quadratic NumElemBegin NumElemEnd NumRun" << std::endl ;
+
+  }
+}
+
+} // namespace
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+int main( int argc , char ** argv )
+{
+  comm::Machine machine = comm::Machine::init( & argc , & argv );
+
+  const unsigned comm_rank = comm::rank( machine );
+
+  const std::string argline = comm::command_line( machine , argc , argv );
+
+  try {
+    run( argline , machine );
+  }
+  catch( const std::exception & x ) {
+    std::cerr << "P" << comm_rank << " throw: " << x.what() << std::endl ;
+  }
+  catch( ... ) {
+    std::cerr << "P" << comm_rank << " throw: unknown exception" << std::endl ;
+  }
+
+  comm::Machine::finalize();
+
+  return 0 ;
+}
+
diff --git a/lib/kokkos/example/query_device/CMakeLists.txt b/lib/kokkos/example/query_device/CMakeLists.txt
new file mode 100644
index 0000000000..dade7f01fe
--- /dev/null
+++ b/lib/kokkos/example/query_device/CMakeLists.txt
@@ -0,0 +1,14 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(SOURCES "")
+
+FILE(GLOB SOURCES *.cpp)
+
+TRIBITS_ADD_EXECUTABLE(
+  query_device
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  )
+
diff --git a/lib/kokkos/example/query_device/Makefile b/lib/kokkos/example/query_device/Makefile
new file mode 100644
index 0000000000..bf8fbea3e0
--- /dev/null
+++ b/lib/kokkos/example/query_device/Makefile
@@ -0,0 +1,53 @@
+KOKKOS_PATH ?= ../..
+
+MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
+SRC_DIR := $(dir $(MAKEFILE_PATH))
+
+SRC = $(wildcard $(SRC_DIR)/*.cpp)
+OBJ = $(SRC:$(SRC_DIR)/%.cpp=%.o)
+
+#SRC = $(wildcard *.cpp)
+#OBJ = $(SRC:%.cpp=%.o)
+
+default: build
+	echo "Start Build"
+
+# use installed Makefile.kokkos
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = $(NVCC_WRAPPER)
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS = 
+EXE = $(addsuffix .cuda, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "Cuda,OpenMP"
+#KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS =  
+EXE = $(addsuffix .host, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "OpenMP"
+#KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+LIB =
+
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: 
+	rm -f *.a *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:$(SRC_DIR)/%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
diff --git a/lib/kokkos/example/query_device/query_device.cpp b/lib/kokkos/example/query_device/query_device.cpp
new file mode 100644
index 0000000000..ced8cc4e95
--- /dev/null
+++ b/lib/kokkos/example/query_device/query_device.cpp
@@ -0,0 +1,100 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <iostream>
+#include <sstream>
+
+#include <Kokkos_Macros.hpp>
+
+#if defined( KOKKOS_HAVE_MPI )
+#include <mpi.h>
+#endif
+
+#include <Kokkos_Core.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+int main( int argc , char ** argv )
+{
+  std::ostringstream msg ;
+
+#if defined( KOKKOS_HAVE_MPI )
+
+  MPI_Init( & argc , & argv );
+
+  int mpi_rank = 0 ;
+
+  MPI_Comm_rank( MPI_COMM_WORLD , & mpi_rank );
+
+  msg << "MPI rank(" << mpi_rank << ") " ;
+
+#endif
+
+  msg << "{" << std::endl ;
+
+  if ( Kokkos::hwloc::available() ) {
+    msg << "hwloc( NUMA[" << Kokkos::hwloc::get_available_numa_count()
+        << "] x CORE["    << Kokkos::hwloc::get_available_cores_per_numa()
+        << "] x HT["      << Kokkos::hwloc::get_available_threads_per_core()
+        << "] )"
+        << std::endl ;
+  }
+
+#if defined( KOKKOS_HAVE_CUDA )
+  Kokkos::Cuda::print_configuration( msg );
+#endif
+
+  msg << "}" << std::endl ;
+
+  std::cout << msg.str();
+
+#if defined( KOKKOS_HAVE_MPI )
+
+  MPI_Finalize();
+
+#endif
+
+  return 0 ;
+}
+
diff --git a/lib/kokkos/example/sort_array/CMakeLists.txt b/lib/kokkos/example/sort_array/CMakeLists.txt
new file mode 100644
index 0000000000..0c7da74f4a
--- /dev/null
+++ b/lib/kokkos/example/sort_array/CMakeLists.txt
@@ -0,0 +1,14 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+SET(SOURCES "")
+
+FILE(GLOB SOURCES *.cpp)
+
+TRIBITS_ADD_EXECUTABLE(
+  sort_array
+  SOURCES ${SOURCES}
+  COMM serial mpi
+  )
+
diff --git a/lib/kokkos/example/sort_array/Makefile b/lib/kokkos/example/sort_array/Makefile
new file mode 100644
index 0000000000..bf8fbea3e0
--- /dev/null
+++ b/lib/kokkos/example/sort_array/Makefile
@@ -0,0 +1,53 @@
+KOKKOS_PATH ?= ../..
+
+MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
+SRC_DIR := $(dir $(MAKEFILE_PATH))
+
+SRC = $(wildcard $(SRC_DIR)/*.cpp)
+OBJ = $(SRC:$(SRC_DIR)/%.cpp=%.o)
+
+#SRC = $(wildcard *.cpp)
+#OBJ = $(SRC:%.cpp=%.o)
+
+default: build
+	echo "Start Build"
+
+# use installed Makefile.kokkos
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = $(NVCC_WRAPPER)
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS = 
+EXE = $(addsuffix .cuda, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "Cuda,OpenMP"
+#KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -I$(SRC_DIR) -O3
+LINK = $(CXX)
+LINKFLAGS =  
+EXE = $(addsuffix .host, $(shell basename $(SRC_DIR)))
+#KOKKOS_DEVICES = "OpenMP"
+#KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+LIB =
+
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: 
+	rm -f *.a *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:$(SRC_DIR)/%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
+
diff --git a/lib/kokkos/example/sort_array/main.cpp b/lib/kokkos/example/sort_array/main.cpp
new file mode 100644
index 0000000000..74c4ab154c
--- /dev/null
+++ b/lib/kokkos/example/sort_array/main.cpp
@@ -0,0 +1,95 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <iostream>
+#include <sstream>
+
+#include <Kokkos_Core.hpp>
+
+#include <sort_array.hpp>
+
+
+int main( int argc , char ** argv )
+{
+#if defined( KOKKOS_HAVE_CUDA ) || defined( KOKKOS_HAVE_PTHREAD ) || defined( KOKKOS_HAVE_OPENMP )
+  Kokkos::initialize( argc , argv );
+
+  int length_array = 100000 ;
+
+  for ( int i = 0 ; i < argc ; ++i ) {
+    if ( 0 == strcmp( argv[i] , "length_array" ) ) {
+      length_array = atoi( argv[i+1] );
+    }
+  }
+
+  int length_total_array  = length_array * 100;
+
+#if defined( KOKKOS_HAVE_CUDA )
+  if ( Kokkos::Cuda::is_initialized() ) {
+    std::cout << "Kokkos::Cuda" << std::endl ;
+    Example::sort_array< Kokkos::Cuda >( length_array , length_total_array );
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_PTHREAD )
+  if ( Kokkos::Threads::is_initialized() ) {
+    std::cout << "Kokkos::Threads" << std::endl ;
+    Example::sort_array< Kokkos::Threads >( length_array , length_total_array );
+  }
+#endif
+
+#if defined( KOKKOS_HAVE_OPENMP )
+  if ( Kokkos::OpenMP::is_initialized() ) {
+    std::cout << "Kokkos::OpenMP" << std::endl ;
+    Example::sort_array< Kokkos::OpenMP >( length_array , length_total_array );
+  }
+#endif
+
+  Kokkos::finalize();
+#endif
+
+  return 0 ;
+}
+
diff --git a/lib/kokkos/example/sort_array/sort_array.hpp b/lib/kokkos/example/sort_array/sort_array.hpp
new file mode 100644
index 0000000000..d21f998958
--- /dev/null
+++ b/lib/kokkos/example/sort_array/sort_array.hpp
@@ -0,0 +1,190 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#ifndef EXAMPLE_SORT_ARRAY
+#define EXAMPLE_SORT_ARRAY
+
+#include <stdlib.h>
+#include <algorithm>
+
+#include <Kokkos_Core.hpp>
+
+#include <impl/Kokkos_Timer.hpp>
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Example {
+
+template< class Device >
+struct SortView {
+
+  template< typename ValueType >
+  SortView( const Kokkos::View<ValueType*,Device> v , int begin , int end )
+    {
+      std::sort( v.ptr_on_device() + begin , v.ptr_on_device() + end );
+    }
+};
+
+}
+
+#if defined(KOKKOS_HAVE_CUDA)
+
+#include <thrust/device_ptr.h>
+#include <thrust/sort.h>
+
+namespace Example {
+
+template<>
+struct SortView< Kokkos::Cuda > {
+  template< typename ValueType >
+  SortView( const Kokkos::View<ValueType*,Kokkos::Cuda> v , int begin , int end )
+    {
+      thrust::sort( thrust::device_ptr<ValueType>( v.ptr_on_device() + begin )
+                  , thrust::device_ptr<ValueType>( v.ptr_on_device() + end ) );
+    }
+};
+
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+//----------------------------------------------------------------------------
+
+namespace Example {
+
+template< class Device >
+void sort_array( const size_t array_length /* length of spans of array to sort */
+               , const size_t total_length /* total length of array */
+               , const int print = 1 )
+{
+  typedef Device execution_space ;
+  typedef Kokkos::View<int*,Device>  device_array_type ;
+
+#if defined( KOKKOS_HAVE_CUDA )
+
+  typedef typename
+    Kokkos::Impl::if_c< Kokkos::Impl::is_same< Device , Kokkos::Cuda >::value
+                      , Kokkos::View<int*,Kokkos::Cuda::array_layout,Kokkos::CudaHostPinnedSpace>
+                      , typename device_array_type::HostMirror
+                      >::type  host_array_type ;
+
+#else
+
+  typedef typename device_array_type::HostMirror  host_array_type ;
+
+#endif
+
+  Kokkos::Timer timer;
+
+  const device_array_type  work_array("work_array" , array_length );
+  const host_array_type    host_array("host_array" , total_length );
+
+  std::cout << "sort_array length( " << total_length << " )"
+            << " in chunks( " << array_length << " )"
+            << std::endl ;
+
+  double sec = timer.seconds();
+  std::cout << "declaring Views took "
+            << sec << " seconds" << std::endl;
+  timer.reset();
+
+  for ( size_t i = 0 ; i < total_length ; ++i ) {
+    host_array(i) = ( lrand48() * total_length ) >> 31 ;
+  }
+
+  sec = timer.seconds();
+  std::cout << "initializing " << total_length << " elements on host took "
+            << sec << " seconds" << std::endl;
+  timer.reset();
+
+  double sec_copy_in  = 0 ;
+  double sec_sort     = 0 ;
+  double sec_copy_out = 0 ;
+  double sec_error    = 0 ;
+  size_t error_count  = 0 ;
+
+  for ( size_t begin = 0 ; begin < total_length ; begin += array_length ) {
+
+    const size_t end = begin + array_length < total_length
+                     ? begin + array_length : total_length ;
+
+    const std::pair<size_t,size_t> host_range(begin,end);
+
+    const host_array_type host_subarray = Kokkos::subview( host_array , host_range );
+
+    timer.reset();
+
+    Kokkos::deep_copy( work_array , host_subarray );
+
+    sec_copy_in += timer.seconds(); timer.reset();
+
+    SortView< execution_space >( work_array , 0 , end - begin );
+
+    sec_sort += timer.seconds(); timer.reset();
+
+    Kokkos::deep_copy( host_subarray , work_array );
+
+    sec_copy_out += timer.seconds(); timer.reset();
+
+    for ( size_t i = begin + 1 ; i < end ; ++i ) {
+      if ( host_array(i) < host_array(i-1) ) ++error_count ;
+    }
+
+    sec_error += timer.seconds(); timer.reset();
+  }
+
+  std::cout << "copy to   device " << sec_copy_in  << " seconds" << std::endl
+            << "sort on   device " << sec_sort     << " seconds" << std::endl
+            << "copy from device " << sec_copy_out << " seconds" << std::endl
+            << "errors " << error_count << " took " << sec_error << " seconds" << std::endl
+            ;
+}
+
+} // namespace Example
+
+//----------------------------------------------------------------------------
+
+#endif /* #ifndef EXAMPLE_SORT_ARRAY */
+
diff --git a/lib/kokkos/example/tutorial/01_hello_world/CMakeLists.txt b/lib/kokkos/example/tutorial/01_hello_world/CMakeLists.txt
new file mode 100644
index 0000000000..5e5b1fcb46
--- /dev/null
+++ b/lib/kokkos/example/tutorial/01_hello_world/CMakeLists.txt
@@ -0,0 +1,11 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_01_hello_world
+  SOURCES hello_world.cpp
+  COMM serial mpi
+  )
+
diff --git a/lib/kokkos/example/tutorial/01_hello_world/Makefile b/lib/kokkos/example/tutorial/01_hello_world/Makefile
new file mode 100644
index 0000000000..78a9fed0cc
--- /dev/null
+++ b/lib/kokkos/example/tutorial/01_hello_world/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/01_hello_world/hello_world.cpp b/lib/kokkos/example/tutorial/01_hello_world/hello_world.cpp
new file mode 100644
index 0000000000..459b9b094f
--- /dev/null
+++ b/lib/kokkos/example/tutorial/01_hello_world/hello_world.cpp
@@ -0,0 +1,130 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+#include <typeinfo>
+
+//
+// "Hello world" parallel_for example:
+//   1. Start up Kokkos
+//   2. Execute a parallel for loop in the default execution space,
+//      using a functor to define the loop body
+//   3. Shut down Kokkos
+//
+// If Kokkos was built with C++11 enabled, try comparing this example
+// to 01_hello_world_lambda.  The latter uses C++11 lambdas (anonymous
+// functions) to define the loop body of the parallel_for.  That makes
+// the code much more concise and readable.  On the other hand,
+// breaking out the loop body into an explicit functor makes it easier
+// to test the loop independently of the parallel pattern.
+//
+
+// Functor that defines the parallel_for's loop body.
+//
+// A "functor" is just a class or struct with a public operator()
+// instance method.
+struct hello_world {
+  // If a functor has an "execution_space" (or "execution_space", for
+  // backwards compatibility) public typedef, parallel_* will only run
+  // the functor in that execution space.  That's a good way to mark a
+  // functor as specific to an execution space.  If the functor lacks
+  // this typedef, parallel_for will run it in the default execution
+  // space, unless you tell it otherwise (that's an advanced topic;
+  // see "execution policies").
+
+  // The functor's operator() defines the loop body.  It takes an
+  // integer argument which is the parallel for loop index.  Other
+  // arguments are possible; see the "hierarchical parallelism" part
+  // of the tutorial.
+  //
+  // The operator() method must be const, and must be marked with the
+  // KOKKOS_INLINE_FUNCTION macro.  If building with CUDA, this macro
+  // will mark your method as suitable for running on the CUDA device
+  // (as well as on the host).  If not building with CUDA, the macro
+  // is unnecessary but harmless.
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int i) const {
+    printf ("Hello from i = %i\n", i);
+  }
+};
+
+int main (int argc, char* argv[]) {
+  // You must call initialize() before you may call Kokkos.
+  //
+  // With no arguments, this initializes the default execution space
+  // (and potentially its host execution space) with default
+  // parameters.  You may also pass in argc and argv, analogously to
+  // MPI_Init().  It reads and removes command-line arguments that
+  // start with "--kokkos-".
+  Kokkos::initialize (argc, argv);
+
+  // Print the name of Kokkos' default execution space.  We're using
+  // typeid here, so the name might get a bit mangled by the linker,
+  // but you should still be able to figure out what it is.
+  printf ("Hello World on Kokkos execution space %s\n",
+          typeid (Kokkos::DefaultExecutionSpace).name ());
+
+  // Run the above functor on the default Kokkos execution space in
+  // parallel, with a parallel for loop count of 15.
+  //
+  // The Kokkos::DefaultExecutionSpace typedef gives the default
+  // execution space.  Depending on how Kokkos was configured, this
+  // could be OpenMP, Threads, Cuda, Serial, or even some other
+  // execution space.
+  //
+  // The following line of code would look like this in OpenMP:
+  //
+  // #pragma omp parallel for
+  // for (int i = 0; i < 15; ++i) {
+  //   printf ("Hello from i = %i\n", i);
+  // }
+  //
+  // You may notice that the printed numbers do not print out in
+  // order.  Parallel for loops may execute in any order.
+  Kokkos::parallel_for ("HelloWorld",15, hello_world ());
+
+  // You must call finalize() after you are done using Kokkos.
+  Kokkos::finalize ();
+}
+
diff --git a/lib/kokkos/example/tutorial/01_hello_world_lambda/CMakeLists.txt b/lib/kokkos/example/tutorial/01_hello_world_lambda/CMakeLists.txt
new file mode 100644
index 0000000000..3fcca4bceb
--- /dev/null
+++ b/lib/kokkos/example/tutorial/01_hello_world_lambda/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+IF (Kokkos_ENABLE_CXX11)
+  # This is a tutorial, not a test, so we don't ask CTest to run it.
+  TRIBITS_ADD_EXECUTABLE(
+    tutorial_01_hello_world_lambda
+    SOURCES hello_world_lambda.cpp
+    COMM serial mpi
+    )
+ENDIF ()
+
diff --git a/lib/kokkos/example/tutorial/01_hello_world_lambda/Makefile b/lib/kokkos/example/tutorial/01_hello_world_lambda/Makefile
new file mode 100644
index 0000000000..95ee2c47fe
--- /dev/null
+++ b/lib/kokkos/example/tutorial/01_hello_world_lambda/Makefile
@@ -0,0 +1,44 @@
+KOKKOS_PATH = ../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+KOKKOS_CUDA_OPTIONS = "enable_lambda"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/01_hello_world_lambda/hello_world_lambda.cpp b/lib/kokkos/example/tutorial/01_hello_world_lambda/hello_world_lambda.cpp
new file mode 100644
index 0000000000..b6c9cc5e43
--- /dev/null
+++ b/lib/kokkos/example/tutorial/01_hello_world_lambda/hello_world_lambda.cpp
@@ -0,0 +1,109 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+#include <typeinfo>
+
+//
+// "Hello world" parallel_for example:
+//   1. Start up Kokkos
+//   2. Execute a parallel for loop in the default execution space,
+//      using a C++11 lambda to define the loop body
+//   3. Shut down Kokkos
+//
+// This example only builds if C++11 is enabled.  Compare this example
+// to 01_hello_world, which uses functors (explicitly defined classes)
+// to define the loop body of the parallel_for.  Both functors and
+// lambdas have their places.
+//
+
+int main (int argc, char* argv[]) {
+  // You must call initialize() before you may call Kokkos.
+  //
+  // With no arguments, this initializes the default execution space
+  // (and potentially its host execution space) with default
+  // parameters.  You may also pass in argc and argv, analogously to
+  // MPI_Init().  It reads and removes command-line arguments that
+  // start with "--kokkos-".
+  Kokkos::initialize (argc, argv);
+
+  // Print the name of Kokkos' default execution space.  We're using
+  // typeid here, so the name might get a bit mangled by the linker,
+  // but you should still be able to figure out what it is.
+  printf ("Hello World on Kokkos execution space %s\n",
+          typeid (Kokkos::DefaultExecutionSpace).name ());
+
+  // Run lambda on the default Kokkos execution space in parallel,
+  // with a parallel for loop count of 15.  The lambda's argument is
+  // an integer which is the parallel for's loop index.  As you learn
+  // about different kinds of parallelism, you will find out that
+  // there are other valid argument types as well.
+  //
+  // For a single level of parallelism, we prefer that you use the
+  // KOKKOS_LAMBDA macro.  If CUDA is disabled, this just turns into
+  // [=].  That captures variables from the surrounding scope by
+  // value.  Do NOT capture them by reference!  If CUDA is enabled,
+  // this macro may have a special definition that makes the lambda
+  // work correctly with CUDA.  Compare to the KOKKOS_INLINE_FUNCTION
+  // macro, which has a special meaning if CUDA is enabled.
+  //
+  // The following parallel_for would look like this if we were using
+  // OpenMP by itself, instead of Kokkos:
+  //
+  // #pragma omp parallel for
+  // for (int i = 0; i < 15; ++i) {
+  //   printf ("Hello from i = %i\n", i);
+  // }
+  //
+  // You may notice that the printed numbers do not print out in
+  // order.  Parallel for loops may execute in any order.
+  Kokkos::parallel_for (15, KOKKOS_LAMBDA (const int i) {
+      // printf works in a CUDA parallel kernel; std::ostream does not.
+      printf ("Hello from i = %i\n", i);
+    });
+
+  // You must call finalize() after you are done using Kokkos.
+  Kokkos::finalize ();
+}
+
diff --git a/lib/kokkos/example/tutorial/02_simple_reduce/CMakeLists.txt b/lib/kokkos/example/tutorial/02_simple_reduce/CMakeLists.txt
new file mode 100644
index 0000000000..7c78db840f
--- /dev/null
+++ b/lib/kokkos/example/tutorial/02_simple_reduce/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_02_simple_reduce
+  SOURCES simple_reduce.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/02_simple_reduce/Makefile b/lib/kokkos/example/tutorial/02_simple_reduce/Makefile
new file mode 100644
index 0000000000..78a9fed0cc
--- /dev/null
+++ b/lib/kokkos/example/tutorial/02_simple_reduce/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/02_simple_reduce/simple_reduce.cpp b/lib/kokkos/example/tutorial/02_simple_reduce/simple_reduce.cpp
new file mode 100644
index 0000000000..236618f7be
--- /dev/null
+++ b/lib/kokkos/example/tutorial/02_simple_reduce/simple_reduce.cpp
@@ -0,0 +1,101 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+
+//
+// First reduction (parallel_reduce) example:
+//   1. Start up Kokkos
+//   2. Execute a parallel_reduce loop in the default execution space,
+//      using a functor to define the loop body
+//   3. Shut down Kokkos
+//
+// Compare this example to 02_simple_reduce_lambda, which uses a C++11
+// lambda to define the loop body of the parallel_reduce.
+//
+
+// Reduction functor for computing the sum of squares.
+//
+// More advanced reduction examples will show how to control the
+// reduction's "join" operator.  If the join operator is not provided,
+// it defaults to binary operator+ (adding numbers together).
+struct squaresum {
+  // Specify the type of the reduction value with a "value_type"
+  // typedef.  In this case, the reduction value has type int.
+  typedef int value_type;
+
+  // The reduction functor's operator() looks a little different than
+  // the parallel_for functor's operator().  For the reduction, we
+  // pass in both the loop index i, and the intermediate reduction
+  // value lsum.  The latter MUST be passed in by nonconst reference.
+  // (If the reduction type is an array like int[], indicating an
+  // array reduction result, then the second argument is just int[].)
+  KOKKOS_INLINE_FUNCTION
+  void operator () (const int i, int& lsum) const {
+    lsum += i*i; // compute the sum of squares
+  }
+};
+
+int main (int argc, char* argv[]) {
+  Kokkos::initialize (argc, argv);
+  const int n = 10;
+
+  // Compute the sum of squares of integers from 0 to n-1, in
+  // parallel, using Kokkos.
+  int sum = 0;
+  Kokkos::parallel_reduce (n, squaresum (), sum);
+  printf ("Sum of squares of integers from 0 to %i, "
+          "computed in parallel, is %i\n", n - 1, sum);
+
+  // Compare to a sequential loop.
+  int seqSum = 0;
+  for (int i = 0; i < n; ++i) {
+    seqSum += i*i;
+  }
+  printf ("Sum of squares of integers from 0 to %i, "
+          "computed sequentially, is %i\n", n - 1, seqSum);
+  Kokkos::finalize ();
+  return (sum == seqSum) ? 0 : -1;
+}
+
diff --git a/lib/kokkos/example/tutorial/02_simple_reduce_lambda/CMakeLists.txt b/lib/kokkos/example/tutorial/02_simple_reduce_lambda/CMakeLists.txt
new file mode 100644
index 0000000000..e2e3a929f1
--- /dev/null
+++ b/lib/kokkos/example/tutorial/02_simple_reduce_lambda/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+IF (Kokkos_ENABLE_CXX11)
+  # This is a tutorial, not a test, so we don't ask CTest to run it.
+  TRIBITS_ADD_EXECUTABLE(
+    tutorial_02_simple_reduce_lambda
+    SOURCES simple_reduce_lambda.cpp
+    COMM serial mpi
+    )
+ENDIF ()
diff --git a/lib/kokkos/example/tutorial/02_simple_reduce_lambda/Makefile b/lib/kokkos/example/tutorial/02_simple_reduce_lambda/Makefile
new file mode 100644
index 0000000000..95ee2c47fe
--- /dev/null
+++ b/lib/kokkos/example/tutorial/02_simple_reduce_lambda/Makefile
@@ -0,0 +1,44 @@
+KOKKOS_PATH = ../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+KOKKOS_CUDA_OPTIONS = "enable_lambda"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/02_simple_reduce_lambda/simple_reduce_lambda.cpp b/lib/kokkos/example/tutorial/02_simple_reduce_lambda/simple_reduce_lambda.cpp
new file mode 100644
index 0000000000..a403633a8a
--- /dev/null
+++ b/lib/kokkos/example/tutorial/02_simple_reduce_lambda/simple_reduce_lambda.cpp
@@ -0,0 +1,86 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+
+//
+// First reduction (parallel_reduce) example:
+//   1. Start up Kokkos
+//   2. Execute a parallel_reduce loop in the default execution space,
+//      using a C++11 lambda to define the loop body
+//   3. Shut down Kokkos
+//
+// This example only builds if C++11 is enabled.  Compare this example
+// to 02_simple_reduce, which uses a functor to define the loop body
+// of the parallel_reduce.
+//
+
+int main (int argc, char* argv[]) {
+  Kokkos::initialize (argc, argv);
+  const int n = 10;
+
+  // Compute the sum of squares of integers from 0 to n-1, in
+  // parallel, using Kokkos.  This time, use a lambda instead of a
+  // functor.  The lambda takes the same arguments as the functor's
+  // operator().
+  int sum = 0;
+  // The KOKKOS_LAMBDA macro replaces the capture-by-value clause [=].
+  // It also handles any other syntax needed for CUDA.
+  Kokkos::parallel_reduce (n, KOKKOS_LAMBDA (const int i, int& lsum) {
+      lsum += i*i;
+    }, sum);
+  printf ("Sum of squares of integers from 0 to %i, "
+          "computed in parallel, is %i\n", n - 1, sum);
+
+  // Compare to a sequential loop.
+  int seqSum = 0;
+  for (int i = 0; i < n; ++i) {
+    seqSum += i*i;
+  }
+  printf ("Sum of squares of integers from 0 to %i, "
+          "computed sequentially, is %i\n", n - 1, seqSum);
+  Kokkos::finalize ();
+  return (sum == seqSum) ? 0 : -1;
+}
+
diff --git a/lib/kokkos/example/tutorial/03_simple_view/CMakeLists.txt b/lib/kokkos/example/tutorial/03_simple_view/CMakeLists.txt
new file mode 100644
index 0000000000..7475a99e49
--- /dev/null
+++ b/lib/kokkos/example/tutorial/03_simple_view/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_03_simple_view
+  SOURCES simple_view.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/03_simple_view/Makefile b/lib/kokkos/example/tutorial/03_simple_view/Makefile
new file mode 100644
index 0000000000..78a9fed0cc
--- /dev/null
+++ b/lib/kokkos/example/tutorial/03_simple_view/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/03_simple_view/simple_view.cpp b/lib/kokkos/example/tutorial/03_simple_view/simple_view.cpp
new file mode 100644
index 0000000000..dbbb9d867d
--- /dev/null
+++ b/lib/kokkos/example/tutorial/03_simple_view/simple_view.cpp
@@ -0,0 +1,142 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+//
+// First Kokkos::View (multidimensional array) example:
+//   1. Start up Kokkos
+//   2. Allocate a Kokkos::View
+//   3. Execute a parallel_for and a parallel_reduce over that View's data
+//   4. Shut down Kokkos
+//
+// Compare this example to 03_simple_view_lambda, which uses C++11
+// lambdas to define the loop bodies of the parallel_for and
+// parallel_reduce.
+//
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+
+// A Kokkos::View is an array of zero or more dimensions.  The number
+// of dimensions is specified at compile time, as part of the type of
+// the View.  This array has two dimensions.  The first one
+// (represented by the asterisk) is a run-time dimension, and the
+// second (represented by [3]) is a compile-time dimension.  Thus,
+// this View type is an N x 3 array of type double, where N is
+// specified at run time in the View's constructor.
+//
+// The first dimension of the View is the dimension over which it is
+// efficient for Kokkos to parallelize.
+typedef Kokkos::View<double*[3]> view_type;
+
+// parallel_for functor that fills the View given to its constructor.
+// The View must already have been allocated.
+struct InitView {
+  view_type a;
+
+  // Views have "view semantics."  This means that they behave like
+  // pointers, not like std::vector.  Their copy constructor and
+  // operator= only do shallow copies.  Thus, you can pass View
+  // objects around by "value"; they won't do a deep copy unless you
+  // explicitly ask for a deep copy.
+  InitView (view_type a_) :
+    a (a_)
+  {}
+
+  // Fill the View with some data.  The parallel_for loop will iterate
+  // over the View's first dimension N.
+  KOKKOS_INLINE_FUNCTION
+  void operator () (const int i) const {
+    // Acesss the View just like a Fortran array.  The layout depends
+    // on the View's memory space, so don't rely on the View's
+    // physical memory layout unless you know what you're doing.
+    a(i,0) = 1.0*i;
+    a(i,1) = 1.0*i*i;
+    a(i,2) = 1.0*i*i*i;
+  }
+};
+
+// Reduction functor that reads the View given to its constructor.
+struct ReduceFunctor {
+  view_type a;
+
+  // Constructor takes View by "value"; this does a shallow copy.
+  ReduceFunctor (view_type a_) : a (a_) {}
+
+  // If you write a functor to do a reduction, you must specify the
+  // type of the reduction result via a public 'value_type' typedef.
+  typedef double value_type;
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, double &lsum) const {
+    lsum += a(i,0)*a(i,1)/(a(i,2)+0.1);
+  }
+};
+
+int main (int argc, char* argv[]) {
+  Kokkos::initialize (argc, argv);
+  const int N = 10;
+
+  // Allocate the View.  The first dimension is a run-time parameter
+  // N.  We set N = 10 here.  The second dimension is a compile-time
+  // parameter, 3.  We don't specify it here because we already set it
+  // by declaring the type of the View.
+  //
+  // Views get initialized to zero by default.  This happens in
+  // parallel, using the View's memory space's default execution
+  // space.  Parallel initialization ensures first-touch allocation.
+  // There is a way to shut off default initialization.
+  //
+  // You may NOT allocate a View inside of a parallel_{for, reduce,
+  // scan}.  Treat View allocation as a "thread collective."
+  //
+  // The string "A" is just the label; it only matters for debugging.
+  // Different Views may have the same label.
+  view_type a ("A", N);
+
+  Kokkos::parallel_for (N, InitView (a));
+  double sum = 0;
+  Kokkos::parallel_reduce (N, ReduceFunctor (a), sum);
+  printf ("Result: %f\n", sum);
+  Kokkos::finalize ();
+}
+
diff --git a/lib/kokkos/example/tutorial/03_simple_view_lambda/CMakeLists.txt b/lib/kokkos/example/tutorial/03_simple_view_lambda/CMakeLists.txt
new file mode 100644
index 0000000000..601fe452a4
--- /dev/null
+++ b/lib/kokkos/example/tutorial/03_simple_view_lambda/CMakeLists.txt
@@ -0,0 +1,12 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+IF (Kokkos_ENABLE_CXX11)
+  # This is a tutorial, not a test, so we don't ask CTest to run it.
+  TRIBITS_ADD_EXECUTABLE(
+    tutorial_03_simple_view_lambda
+    SOURCES simple_view_lambda.cpp
+    COMM serial mpi
+    )
+ENDIF ()
diff --git a/lib/kokkos/example/tutorial/03_simple_view_lambda/Makefile b/lib/kokkos/example/tutorial/03_simple_view_lambda/Makefile
new file mode 100644
index 0000000000..95ee2c47fe
--- /dev/null
+++ b/lib/kokkos/example/tutorial/03_simple_view_lambda/Makefile
@@ -0,0 +1,44 @@
+KOKKOS_PATH = ../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+KOKKOS_CUDA_OPTIONS = "enable_lambda"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/03_simple_view_lambda/simple_view_lambda.cpp b/lib/kokkos/example/tutorial/03_simple_view_lambda/simple_view_lambda.cpp
new file mode 100644
index 0000000000..974af74776
--- /dev/null
+++ b/lib/kokkos/example/tutorial/03_simple_view_lambda/simple_view_lambda.cpp
@@ -0,0 +1,116 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+//
+// First Kokkos::View (multidimensional array) example:
+//   1. Start up Kokkos
+//   2. Allocate a Kokkos::View
+//   3. Execute a parallel_for and a parallel_reduce over that View's data
+//   4. Shut down Kokkos
+//
+// Compare this example to 03_simple_view, which uses functors to
+// define the loop bodies of the parallel_for and parallel_reduce.
+//
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+
+// A Kokkos::View is an array of zero or more dimensions.  The number
+// of dimensions is specified at compile time, as part of the type of
+// the View.  This array has two dimensions.  The first one
+// (represented by the asterisk) is a run-time dimension, and the
+// second (represented by [3]) is a compile-time dimension.  Thus,
+// this View type is an N x 3 array of type double, where N is
+// specified at run time in the View's constructor.
+//
+// The first dimension of the View is the dimension over which it is
+// efficient for Kokkos to parallelize.
+typedef Kokkos::View<double*[3]> view_type;
+
+int main (int argc, char* argv[]) {
+  Kokkos::initialize (argc, argv);
+
+  // Allocate the View.  The first dimension is a run-time parameter
+  // N.  We set N = 10 here.  The second dimension is a compile-time
+  // parameter, 3.  We don't specify it here because we already set it
+  // by declaring the type of the View.
+  //
+  // Views get initialized to zero by default.  This happens in
+  // parallel, using the View's memory space's default execution
+  // space.  Parallel initialization ensures first-touch allocation.
+  // There is a way to shut off default initialization.
+  //
+  // You may NOT allocate a View inside of a parallel_{for, reduce,
+  // scan}.  Treat View allocation as a "thread collective."
+  //
+  // The string "A" is just the label; it only matters for debugging.
+  // Different Views may have the same label.
+  view_type a ("A", 10);
+
+  // Fill the View with some data.  The parallel_for loop will iterate
+  // over the View's first dimension N.
+  //
+  // Note that the View is passed by value into the lambda.  The macro
+  // KOKKOS_LAMBDA includes the "capture by value" clause [=].  This
+  // tells the lambda to "capture all variables in the enclosing scope
+  // by value."  Views have "view semantics"; they behave like
+  // pointers, not like std::vector.  Passing them by value does a
+  // shallow copy.  A deep copy never happens unless you explicitly
+  // ask for one.
+  Kokkos::parallel_for (10, KOKKOS_LAMBDA (const int i) {
+    // Acesss the View just like a Fortran array.  The layout depends
+    // on the View's memory space, so don't rely on the View's
+    // physical memory layout unless you know what you're doing.
+    a(i,0) = 1.0*i;
+    a(i,1) = 1.0*i*i;
+    a(i,2) = 1.0*i*i*i;
+  });
+  // Reduction functor that reads the View given to its constructor.
+  double sum = 0;
+  Kokkos::parallel_reduce (10, KOKKOS_LAMBDA (const int i, double& lsum) {
+    lsum += a(i,0)*a(i,1)/(a(i,2)+0.1);
+  }, sum);
+  printf ("Result: %f\n", sum);
+  Kokkos::finalize ();
+}
+
diff --git a/lib/kokkos/example/tutorial/04_simple_memoryspaces/CMakeLists.txt b/lib/kokkos/example/tutorial/04_simple_memoryspaces/CMakeLists.txt
new file mode 100644
index 0000000000..09f209077a
--- /dev/null
+++ b/lib/kokkos/example/tutorial/04_simple_memoryspaces/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_04_simple_memoryspaces
+  SOURCES simple_memoryspaces.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/04_simple_memoryspaces/Makefile b/lib/kokkos/example/tutorial/04_simple_memoryspaces/Makefile
new file mode 100644
index 0000000000..78a9fed0cc
--- /dev/null
+++ b/lib/kokkos/example/tutorial/04_simple_memoryspaces/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/04_simple_memoryspaces/simple_memoryspaces.cpp b/lib/kokkos/example/tutorial/04_simple_memoryspaces/simple_memoryspaces.cpp
new file mode 100644
index 0000000000..c6a4bebfa5
--- /dev/null
+++ b/lib/kokkos/example/tutorial/04_simple_memoryspaces/simple_memoryspaces.cpp
@@ -0,0 +1,101 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+
+// The type of a two-dimensional N x 3 array of double.
+// It lives in Kokkos' default memory space.
+typedef Kokkos::View<double*[3]> view_type;
+
+// The "HostMirror" type corresponding to view_type above is also a
+// two-dimensional N x 3 array of double.  However, it lives in the
+// host memory space corresponding to view_type's memory space.  For
+// example, if view_type lives in CUDA device memory, host_view_type
+// lives in host (CPU) memory.  Furthermore, declaring host_view_type
+// as the host mirror of view_type means that host_view_type has the
+// same layout as view_type.  This makes it easier to copy between the
+// two Views.
+// Advanced issues: If a memory space is accessible from the host without
+// performance penalties then it is its own host_mirror_space. This is
+// the case for HostSpace, CudaUVMSpace and CudaHostPinnedSpace.
+
+typedef view_type::HostMirror host_view_type;
+
+struct ReduceFunctor {
+  view_type a;
+  ReduceFunctor (view_type a_) : a (a_) {}
+  typedef int value_type; //Specify type for reduction value, lsum
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i, int &lsum) const {
+    lsum += a(i,0)-a(i,1)+a(i,2);
+  }
+};
+
+int main() {
+  Kokkos::initialize();
+
+  view_type a ("A", 10);
+  // If view_type and host_mirror_type live in the same memory space,
+  // a "mirror view" is just an alias, and deep_copy does nothing.
+  // Otherwise, a mirror view of a device View lives in host memory,
+  // and deep_copy does a deep copy.
+  host_view_type h_a = Kokkos::create_mirror_view (a);
+
+  // The View h_a lives in host (CPU) memory, so it's legal to fill
+  // the view sequentially using ordinary code, like this.
+  for (int i = 0; i < 10; i++) {
+    for (int j = 0; j < 3; j++) {
+      h_a(i,j) = i*10 + j;
+    }
+  }
+  Kokkos::deep_copy (a, h_a); // Copy from host to device.
+
+  int sum = 0;
+  Kokkos::parallel_reduce (10, ReduceFunctor (a), sum);
+  printf ("Result is %i\n",sum);
+
+  Kokkos::finalize ();
+}
+
diff --git a/lib/kokkos/example/tutorial/05_simple_atomics/CMakeLists.txt b/lib/kokkos/example/tutorial/05_simple_atomics/CMakeLists.txt
new file mode 100644
index 0000000000..5a5790fb04
--- /dev/null
+++ b/lib/kokkos/example/tutorial/05_simple_atomics/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_05_simple_atomics
+  SOURCES simple_atomics.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/05_simple_atomics/Makefile b/lib/kokkos/example/tutorial/05_simple_atomics/Makefile
new file mode 100644
index 0000000000..78a9fed0cc
--- /dev/null
+++ b/lib/kokkos/example/tutorial/05_simple_atomics/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/05_simple_atomics/simple_atomics.cpp b/lib/kokkos/example/tutorial/05_simple_atomics/simple_atomics.cpp
new file mode 100644
index 0000000000..de9c219d5b
--- /dev/null
+++ b/lib/kokkos/example/tutorial/05_simple_atomics/simple_atomics.cpp
@@ -0,0 +1,137 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+
+// Type of a one-dimensional length-N array of int.
+typedef Kokkos::View<int*> view_type;
+typedef view_type::HostMirror host_view_type;
+// This is a "zero-dimensional" View, that is, a View of a single
+// value (an int, in this case).  Access the value using operator()
+// with no arguments: e.g., 'count()'.
+//
+// Zero-dimensional Views are useful for reduction results that stay
+// resident in device memory, as well as for irregularly updated
+// shared state.  We use it for the latter in this example.
+typedef Kokkos::View<int> count_type;
+typedef count_type::HostMirror host_count_type;
+
+
+// Functor for finding a list of primes in a given set of numbers.  If
+// run in parallel, the order of results is nondeterministic, because
+// hardware atomic updates do not guarantee an order of execution.
+struct findprimes {
+  view_type data;
+  view_type result;
+  count_type count;
+
+  findprimes (view_type data_, view_type result_, count_type count_) :
+    data (data_), result (result_), count (count_)
+  {}
+
+  // Test if data(i) is prime.  If it is, increment the count of
+  // primes (stored in the zero-dimensional View 'count') and add the
+  // value to the current list of primes 'result'.
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int i) const {
+    const int number = data(i); // the current number
+
+    // Test all numbers from 3 to ceiling(sqrt(data(i))), to see if
+    // they are factors of data(i).  It's not the most efficient prime
+    // test, but it works.
+    const int upper_bound = sqrt(1.0*number)+1;
+    bool is_prime = !(number%2 == 0);
+    int k = 3;
+    while (k < upper_bound && is_prime) {
+      is_prime = !(number%k == 0);
+      k += 2; // don't have to test even numbers
+    }
+
+    if (is_prime) {
+      // Use an atomic update both to update the current count of
+      // primes, and to find a place in the current list of primes for
+      // the new result.
+      //
+      // atomic_fetch_add results the _current_ count, but increments
+      // it (by 1 in this case).  The current count of primes indexes
+      // into the first unoccupied position of the 'result' array.
+      const int idx = Kokkos::atomic_fetch_add (&count(), 1);
+      result(idx) = number;
+    }
+  }
+
+};
+
+int main () {
+  Kokkos::initialize ();
+
+  srand (61391); // Set the random seed
+
+  int nnumbers = 100000;
+  view_type data ("RND", nnumbers);
+  view_type result ("Prime", nnumbers);
+  count_type count ("Count");
+
+  host_view_type h_data = Kokkos::create_mirror_view (data);
+  host_view_type h_result = Kokkos::create_mirror_view (result);
+  host_count_type h_count = Kokkos::create_mirror_view (count);
+
+  typedef view_type::size_type size_type;
+  // Fill the 'data' array on the host with random numbers.  We assume
+  // that they come from some process which is only implemented on the
+  // host, via some library.  (That's true in this case.)
+  for (size_type i = 0; i < data.dimension_0 (); ++i) {
+    h_data(i) = rand () % nnumbers;
+  }
+  Kokkos::deep_copy (data, h_data); // copy from host to device
+
+  Kokkos::parallel_for (data.dimension_0 (), findprimes (data, result, count));
+  Kokkos::deep_copy (h_count, count); // copy from device to host
+
+  printf ("Found %i prime numbers in %i random numbers\n", h_count(), nnumbers);
+  Kokkos::finalize ();
+}
+
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/CMakeLists.txt b/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/CMakeLists.txt
new file mode 100644
index 0000000000..2eb3a8f6c9
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_advancedviews_01_data_layouts
+  SOURCES data_layouts.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/Makefile b/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/data_layouts.cpp b/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/data_layouts.cpp
new file mode 100644
index 0000000000..8406c504c9
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/01_data_layouts/data_layouts.cpp
@@ -0,0 +1,171 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Timer.hpp>
+#include <cstdio>
+
+// These two View types are both 2-D arrays of double.  However, they
+// have different layouts in memory.  left_type has "layout left,"
+// which means "column major," the same as in Fortran, the BLAS, or
+// LAPACK.  right_type has "layout right," which means "row major,"
+// the same as in C, C++, or Java.
+typedef Kokkos::View<double**, Kokkos::LayoutLeft> left_type;
+typedef Kokkos::View<double**, Kokkos::LayoutRight> right_type;
+// This is a one-dimensional View, so the layout matters less.
+// However, it still has a layout!  Since its layout is not specified
+// explicitly in the type, its layout is a function of the memory
+// space.  For example, the default Cuda layout is LayoutLeft, and the
+// default Host layout is LayoutRight.
+typedef Kokkos::View<double*> view_type;
+
+// parallel_for functor that fills the given View with some data.  It
+// expects to access the View by rows in parallel: each call i of
+// operator() accesses a row.
+template<class ViewType>
+struct init_view {
+  ViewType a;
+  init_view (ViewType a_) : a (a_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const typename ViewType::size_type i) const {
+    // On CPUs this loop could be vectorized so j should do stride 1
+    // access on a for optimal performance. I.e. a should be LayoutRight.
+    // On GPUs threads should do coalesced loads and stores. That means
+    // that i should be the stride one access for optimal performance.
+    for (typename ViewType::size_type j = 0; j < a.dimension_1 (); ++j) {
+      a(i,j) = 1.0*a.dimension_0()*i + 1.0*j;
+    }
+  }
+};
+
+// Compute a contraction of v1 and v2 into a:
+//
+//   a(i) := sum_j (v1(i,j) * v2(j,i))
+//
+// Since the functor is templated on the ViewTypes itself it doesn't matter what
+// there layouts are. That means you can use different layouts on different
+// architectures.
+template<class ViewType1, class ViewType2>
+struct contraction {
+  view_type a;
+  typename ViewType1::const_type v1;
+  typename ViewType2::const_type v2;
+  contraction (view_type a_, ViewType1 v1_, ViewType2 v2_) :
+    a (a_), v1 (v1_), v2 (v2_)
+  {}
+
+  // As with the initialization functor the performance of this operator
+  // depends on the architecture and the chosen data layouts.
+  // On CPUs optimal would be to vectorize the inner loop, so j should be the
+  // stride 1 access. That means v1 should be LayoutRight and v2 LayoutLeft.
+  // In order to get coalesced access on GPUs where i corresponds closely to
+  // the thread Index, i must be the stride 1 dimension. That means v1 should be
+  // LayoutLeft and v2 LayoutRight.
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const view_type::size_type i) const {
+    for (view_type::size_type j = 0; j < v1.dimension_1 (); ++j) {
+      a(i) = v1(i,j)*v2(j,i);
+    }
+  }
+};
+
+// Compute a dot product. This is used for result verification.
+struct dot {
+  view_type a;
+  dot (view_type a_) : a (a_) {}
+  typedef double value_type; //Specify type for reduction target, lsum
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const view_type::size_type i, double &lsum) const {
+    lsum += a(i)*a(i);
+  }
+};
+
+int main (int narg, char* arg[]) {
+  // When initializing Kokkos, you may pass in command-line arguments,
+  // just like with MPI_Init().  Kokkos reserves the right to remove
+  // arguments from the list that start with '--kokkos-'.
+  Kokkos::initialize (narg, arg);
+
+  int size = 10000;
+  view_type a("A",size);
+
+  // Define two views with LayoutLeft and LayoutRight.
+  left_type l("L",size,10000);
+  right_type r("R",size,10000);
+
+  // Initialize the data in the views.
+  Kokkos::parallel_for(size,init_view<left_type>(l));
+  Kokkos::parallel_for(size,init_view<right_type>(r));
+  Kokkos::fence();
+
+  // Measure time to execute the contraction kernel when giving it a
+  // LayoutLeft view for v1 and a LayoutRight view for v2. This should be
+  // fast on GPUs and slow on CPUs
+  Kokkos::Timer time1;
+  Kokkos::parallel_for(size,contraction<left_type,right_type>(a,l,r));
+  Kokkos::fence();
+  double sec1 = time1.seconds();
+
+  double sum1 = 0;
+  Kokkos::parallel_reduce(size,dot(a),sum1);
+  Kokkos::fence();
+
+  // Measure time to execute the contraction kernel when giving it a
+  // LayoutRight view for v1 and a LayoutLeft view for v2. This should be
+  // fast on CPUs and slow on GPUs
+  Kokkos::Timer time2;
+  Kokkos::parallel_for(size,contraction<right_type,left_type>(a,r,l));
+  Kokkos::fence();
+  double sec2 = time2.seconds();
+
+  double sum2 = 0;
+  Kokkos::parallel_reduce(size,dot(a),sum2);
+
+  // Kokkos' reductions are deterministic.
+  // The results should always be equal.
+  printf("Result Left/Right %f Right/Left %f (equal result: %i)\n",sec1,sec2,sum2==sum1);
+
+  Kokkos::finalize();
+}
+
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/CMakeLists.txt b/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/CMakeLists.txt
new file mode 100644
index 0000000000..1963e544d7
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_advancedviews_02_memory_traits
+  SOURCES memory_traits.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/Makefile b/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/memory_traits.cpp b/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/memory_traits.cpp
new file mode 100644
index 0000000000..ddd28a97c3
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/02_memory_traits/memory_traits.cpp
@@ -0,0 +1,141 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Timer.hpp>
+#include <cstdio>
+#include <cstdlib>
+
+typedef Kokkos::View<double*> view_type;
+// Kokkos::Views have an MemoryTraits template parameter which
+// allows users to specify usage scenarios of a View.
+// Some of those act simply as hints, which can be used to insert
+// optimal load and store paths, others change the symantics of the
+// access. The trait Kokkos::Atomic is one of the latter. A view with
+// that MemoryTrait will perform any access atomicly (read, write, update).
+//
+// In this example we use a view with a usage hint for RandomAccess.
+// Kokkos::RandomAccess means that we expect to use this view
+// with indirect indexing.
+//
+// In CUDA, RandomAccess allows accesses through the texture
+// cache.  This only works if the View is read-only, which we enforce
+// through the first template parameter.
+//
+// Note that we are still talking about views of the data, its not a new allocation.
+// For example you can have an atomic view of a default view. While you even
+// could use both in the same kernel, this could lead to undefined behaviour because
+// one of your access paths is not atomic. Think of it in the same way as you think of
+// pointers to const data and pointers to non-const data (i.e. const double* and double*).
+// While these pointers can point to the same data you should not use them together if that
+// brakes the const guarantee of the first pointer.
+typedef Kokkos::View<const double*, Kokkos::MemoryTraits<Kokkos::RandomAccess> > view_type_rnd;
+typedef Kokkos::View<int**> idx_type;
+typedef idx_type::HostMirror idx_type_host;
+
+// We template this functor on the ViewTypes to show the effect of the RandomAccess trait.
+template<class DestType, class SrcType>
+struct localsum {
+  idx_type::const_type idx;
+  DestType dest;
+  SrcType src;
+  localsum (idx_type idx_, DestType dest_, SrcType src_) :
+    idx (idx_), dest (dest_), src (src_)
+  {}
+
+  // Calculate a local sum of values
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int i) const {
+    double tmp = 0.0;
+    for (int j = 0; j < (int) idx.dimension_1 (); ++j) {
+      // This is an indirect access on src
+      const double val = src(idx(i,j));
+      tmp += val*val + 0.5*(idx.dimension_0()*val -idx.dimension_1()*val);
+    }
+    dest(i) = tmp;
+  }
+};
+
+int main(int narg, char* arg[]) {
+  Kokkos::initialize (narg, arg);
+
+  int size = 1000000;
+
+  idx_type idx("Idx",size,64);
+  idx_type_host h_idx = Kokkos::create_mirror_view (idx);
+
+  view_type dest ("Dest", size);
+  view_type src ("Src", size);
+
+  srand(134231);
+
+  for (int i = 0; i < size; i++) {
+    for (view_type::size_type j = 0; j < h_idx.dimension_1 (); ++j) {
+      h_idx(i,j) = (size + i + (rand () % 500 - 250)) % size;
+    }
+  }
+
+  // Deep copy the initial data to the device
+  Kokkos::deep_copy(idx,h_idx);
+  // Run the first kernel to warmup caches
+  Kokkos::parallel_for(size,localsum<view_type,view_type_rnd>(idx,dest,src));
+  Kokkos::fence();
+
+  // Run the localsum functor using the RandomAccess trait. On CPUs there should
+  // not be any different in performance to not using the RandomAccess trait.
+  // On GPUs where can be a dramatic difference
+  Kokkos::Timer time1;
+  Kokkos::parallel_for(size,localsum<view_type,view_type_rnd>(idx,dest,src));
+  Kokkos::fence();
+  double sec1 = time1.seconds();
+
+  Kokkos::Timer time2;
+  Kokkos::parallel_for(size,localsum<view_type,view_type>(idx,dest,src));
+  Kokkos::fence();
+  double sec2 = time2.seconds();
+
+  printf("Time with Trait RandomAccess: %f with Plain: %f \n",sec1,sec2);
+
+  Kokkos::finalize();
+}
+
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/CMakeLists.txt b/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/CMakeLists.txt
new file mode 100644
index 0000000000..cbe394c78b
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_advancedviews_03_subviews
+  SOURCES subviews.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/Makefile b/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/subviews.cpp b/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/subviews.cpp
new file mode 100644
index 0000000000..c8001ebaa6
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/03_subviews/subviews.cpp
@@ -0,0 +1,190 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+// This example simulates one timestep of an explicit
+// finite-difference discretization of a time-dependent partial
+// differential equation (PDE).  It shows how to take subviews of the
+// mesh in order to represent particular boundaries or the interior of
+// the mesh.
+
+#include <Kokkos_Core.hpp>
+#include <impl/Kokkos_Timer.hpp>
+#include <cstdio>
+
+typedef Kokkos::View<double***, Kokkos::LayoutRight> mesh_type;
+
+// These View types represent subviews of the mesh.  Some of the Views
+// have layout LayoutStride, meaning that they have run-time "strides"
+// in each dimension which may differ from that dimension.  For
+// example, inner_mesh_type (which represents the interior of the
+// mesh) has to skip over the boundaries when computing its stride;
+// the dimensions of the interior mesh differ from these strides.  You
+// may safely always use a LayoutStride layout when taking a subview
+// of a LayoutRight or LayoutLeft subview, but strided accesses may
+// cost a bit more, especially for 1-D Views.
+typedef Kokkos::View<double**, Kokkos::LayoutStride> xz_plane_type;
+typedef Kokkos::View<double**, Kokkos::LayoutRight> yz_plane_type;
+typedef Kokkos::View<double**, Kokkos::LayoutStride> xy_plane_type;
+typedef Kokkos::View<double***, Kokkos::LayoutStride> inner_mesh_type;
+
+// Functor to set all entries of a boundary of the mesh to a constant
+// value.  The functor is templated on ViewType because different
+// boundaries may have different layouts.
+template<class ViewType>
+struct set_boundary {
+  ViewType a;
+  double value;
+
+  set_boundary (ViewType a_, double value_) :
+    a (a_), value (value_)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const typename ViewType::size_type i) const {
+    for (typename ViewType::size_type j = 0; j < a.dimension_1 (); ++j) {
+      a(i,j) = value;
+    }
+  }
+};
+
+// Functor to set all entries of a boundary of the mesh to a constant
+// value.  The functor is templated on ViewType because different
+// boundaries may have different layouts.
+template<class ViewType>
+struct set_inner {
+  ViewType a;
+  double value;
+
+  set_inner (ViewType a_, double value_) :
+    a (a_), value (value_)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator () (const typename ViewType::size_type i) const {
+    typedef typename ViewType::size_type size_type;
+    for (size_type j = 0; j < a.dimension_1 (); ++j) {
+      for (size_type k = 0; k < a.dimension_2 (); ++k) {
+        a(i,j,k) = value;
+      }
+    }
+  }
+};
+
+// Update the interior of the mesh.  This simulates one timestep of a
+// finite-difference method.
+template<class ViewType>
+struct update {
+  ViewType a;
+  const double dt;
+
+  update (ViewType a_, const double dt_) :
+    a (a_), dt (dt_)
+  {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (typename ViewType::size_type i) const {
+    typedef typename ViewType::size_type size_type;
+    i++;
+    for (size_type j = 1; j < a.dimension_1()-1; j++) {
+      for (size_type k = 1; k < a.dimension_2()-1; k++) {
+        a(i,j,k) += dt* (a(i,j,k+1) - a(i,j,k-1) +
+                         a(i,j+1,k) - a(i,j-1,k) +
+                         a(i+1,j,k) - a(i-1,j,k));
+      }
+    }
+  }
+};
+
+
+int main (int narg, char* arg[]) {
+  using Kokkos::ALL;
+  using Kokkos::pair;
+  using Kokkos::parallel_for;
+  using Kokkos::subview;
+  typedef mesh_type::size_type size_type;
+
+  Kokkos::initialize (narg, arg);
+
+  // The number of mesh points along each dimension of the mesh, not
+  // including boundaries.
+  const size_type size = 100;
+
+  // A is the full cubic 3-D mesh, including the boundaries.
+  mesh_type A ("A", size+2, size+2, size+2);
+  // Ai is the "inner" part of A, _not_ including the boundaries.
+  //
+  // A pair of indices in a particular dimension means the contiguous
+  // zero-based index range in that dimension, including the first
+  // entry of the pair but _not_ including the second entry.
+  inner_mesh_type Ai = subview(A, pair<size_type, size_type> (1, size+1),
+                                  pair<size_type, size_type> (1, size+1),
+                                  pair<size_type, size_type> (1, size+1));
+  // A has six boundaries, one for each face of the cube.
+  // Create a View of each of these boundaries.
+  // ALL() means "select all indices in that dimension."
+  xy_plane_type Zneg_halo = subview(A, ALL (), ALL (), 0);
+  xy_plane_type Zpos_halo = subview(A, ALL (), ALL (), 101);
+  xz_plane_type Yneg_halo = subview(A, ALL (), 0, ALL ());
+  xz_plane_type Ypos_halo = subview(A, ALL (), 101, ALL ());
+  yz_plane_type Xneg_halo = subview(A, 0, ALL (), ALL ());
+  yz_plane_type Xpos_halo = subview(A, 101, ALL (), ALL ());
+
+  // Set the boundaries to their initial conditions.
+  parallel_for (Zneg_halo.dimension_0 (), set_boundary<xy_plane_type> (Zneg_halo,  1));
+  parallel_for (Zpos_halo.dimension_0 (), set_boundary<xy_plane_type> (Zpos_halo, -1));
+  parallel_for (Yneg_halo.dimension_0 (), set_boundary<xz_plane_type> (Yneg_halo,  2));
+  parallel_for (Ypos_halo.dimension_0 (), set_boundary<xz_plane_type> (Ypos_halo, -2));
+  parallel_for (Xneg_halo.dimension_0 (), set_boundary<yz_plane_type> (Xneg_halo,  3));
+  parallel_for (Xpos_halo.dimension_0 (), set_boundary<yz_plane_type> (Xpos_halo, -3));
+
+  // Set the interior of the mesh to its initial condition.
+  parallel_for (Ai.dimension_0 (), set_inner<inner_mesh_type> (Ai, 0));
+
+  // Update the interior of the mesh.
+  // This simulates one timestep with dt = 0.1.
+  parallel_for (Ai.dimension_0 (), update<mesh_type> (A, 0.1));
+
+  printf ("Done\n");
+  Kokkos::finalize ();
+}
+
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/CMakeLists.txt b/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/CMakeLists.txt
new file mode 100644
index 0000000000..300dab128e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_advancedviews_04_dualviews
+  SOURCES dual_view.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/Makefile b/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/dual_view.cpp b/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/dual_view.cpp
new file mode 100644
index 0000000000..4905e4bf88
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/04_dualviews/dual_view.cpp
@@ -0,0 +1,218 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_DualView.hpp>
+#include <impl/Kokkos_Timer.hpp>
+#include <cstdio>
+#include <cstdlib>
+
+// DualView helps you manage data and computations that take place on
+// two different memory spaces.  Examples include CUDA device memory
+// and (CPU) host memory (currently implemented), or Intel Knights
+// Landing MCDRAM and DRAM (not yet implemented).  For example, if you
+// have ported only some parts of you application to run in CUDA,
+// DualView can help manage moving data between the parts of your
+// application that work best with CUDA, and the parts that work
+// better on the CPU.
+//
+// A DualView takes the same template parameters as a View, but
+// contains two Views: One that lives in the DualView's memory space,
+// and one that lives in that memory space's host mirror space.  If
+// both memory spaces are the same, then the two Views just alias one
+// another.  This means that you can use DualView all the time, even
+// when not running in a memory space like CUDA.  DualView's
+// operations to help you manage memory take almost no time in that
+// case.  This makes your code even more performance portable.
+
+typedef Kokkos::DualView<double*> view_type;
+typedef Kokkos::DualView<int**> idx_type;
+
+
+template<class ExecutionSpace>
+struct localsum {
+  // If the functor has a public 'execution_space' typedef, that defines
+  // the functor's execution space (where it runs in parallel).  This
+  // overrides Kokkos' default execution space.
+  typedef ExecutionSpace execution_space;
+
+  typedef typename Kokkos::Impl::if_c<Kokkos::Impl::is_same<ExecutionSpace,Kokkos::DefaultExecutionSpace>::value ,
+     idx_type::memory_space, idx_type::host_mirror_space>::type memory_space;
+
+  // Get the view types on the particular device for which the functor
+  // is instantiated.
+  //
+  // "const_data_type" is a typedef in View (and DualView) which is
+  // the const version of the first template parameter of the View.
+  // For example, the const_data_type version of double** is const
+  // double**.
+  Kokkos::View<idx_type::const_data_type, idx_type::array_layout, memory_space> idx;
+  // "scalar_array_type" is a typedef in ViewTraits (and DualView) which is the
+  // array version of the value(s) stored in the View.
+  Kokkos::View<view_type::scalar_array_type, view_type::array_layout, memory_space> dest;
+  Kokkos::View<view_type::const_data_type, view_type::array_layout,
+               memory_space, Kokkos::MemoryRandomAccess> src;
+
+  // Constructor takes DualViews, synchronizes them to the device,
+  // then marks them as modified on the device.
+  localsum (idx_type dv_idx, view_type dv_dest, view_type dv_src)
+  {
+    // Extract the view on the correct Device (i.e., the correct
+    // memory space) from the DualView.  DualView has a template
+    // method, view(), which is templated on the memory space.  If the
+    // DualView has a View from that memory space, view() returns the
+    // View in that space.
+    idx = dv_idx.view<memory_space> ();
+    dest = dv_dest.template view<memory_space> ();
+    src = dv_src.template view<memory_space> ();
+
+    // Synchronize the DualView to the correct Device.
+    //
+    // DualView's sync() method is templated on a memory space, and
+    // synchronizes the DualView in a one-way fashion to that memory
+    // space.  "Synchronizing" means copying, from the other memory
+    // space to the Device memory space.  sync() does _nothing_ if the
+    // Views on the two memory spaces are in sync.  DualView
+    // determines this by the user manually marking one side or the
+    // other as modified; see the modify() call below.
+
+    dv_idx.sync<memory_space> ();
+    dv_dest.template sync<memory_space> ();
+    dv_src.template sync<memory_space> ();
+
+    // Mark dest as modified on Device.
+    dv_dest.template modify<memory_space> ();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int i) const {
+    double tmp = 0.0;
+    for (int j = 0; j < (int) idx.dimension_1(); ++j) {
+      const double val = src(idx(i,j));
+      tmp += val*val + 0.5*(idx.dimension_0()*val -idx.dimension_1()*val);
+    }
+    dest(i) += tmp;
+  }
+};
+
+class ParticleType {
+  public:
+    double q;
+    double m;
+    double q_over_m;
+    KOKKOS_INLINE_FUNCTION
+    ParticleType(double q_ = -1, double m_ = 1):
+     q(q_), m(m_), q_over_m(q/m) {}
+protected:
+};
+
+  typedef Kokkos::DualView<ParticleType[10]> ParticleTypes;
+int main (int narg, char* arg[]) {
+  Kokkos::initialize (narg, arg);
+
+// If View is non-trivial constructible type then add braces so it is out of scope
+// before Kokkos::finalize() call
+{
+  ParticleTypes test("Test");
+  Kokkos::fence();
+  test.h_view(0) = ParticleType(-1e4,1);
+  Kokkos::fence();
+
+  int size = 1000000;
+
+  // Create DualViews. This will allocate on both the device and its
+  // host_mirror_device.
+  idx_type idx ("Idx",size,64);
+  view_type dest ("Dest",size);
+  view_type src ("Src",size);
+
+
+  srand (134231);
+
+  // Get a reference to the host view of idx directly (equivalent to
+  // idx.view<idx_type::host_mirror_space>() )
+  idx_type::t_host h_idx = idx.h_view;
+  for (int i = 0; i < size; ++i) {
+    for (view_type::size_type j = 0; j < h_idx.dimension_1 (); ++j) {
+      h_idx(i,j) = (size + i + (rand () % 500 - 250)) % size;
+    }
+  }
+
+  // Mark idx as modified on the host_mirror_space so that a
+  // sync to the device will actually move data.  The sync happens in
+  // the functor's constructor.
+  idx.modify<idx_type::host_mirror_space> ();
+
+  // Run on the device.  This will cause a sync of idx to the device,
+  // since it was marked as modified on the host.
+  Kokkos::Timer timer;
+  Kokkos::parallel_for(size,localsum<view_type::execution_space>(idx,dest,src));
+  Kokkos::fence();
+  double sec1_dev = timer.seconds();
+
+  timer.reset();
+  Kokkos::parallel_for(size,localsum<view_type::execution_space>(idx,dest,src));
+  Kokkos::fence();
+  double sec2_dev = timer.seconds();
+
+  // Run on the host's default execution space (could be the same as device).
+  // This will cause a sync back to the host of dest.  Note that if the Device is CUDA,
+  // the data layout will not be optimal on host, so performance is
+  // lower than what it would be for a pure host compilation.
+  timer.reset();
+  Kokkos::parallel_for(size,localsum<Kokkos::HostSpace::execution_space>(idx,dest,src));
+  Kokkos::fence();
+  double sec1_host = timer.seconds();
+
+  timer.reset();
+  Kokkos::parallel_for(size,localsum<Kokkos::HostSpace::execution_space>(idx,dest,src));
+  Kokkos::fence();
+  double sec2_host = timer.seconds();
+
+  printf("Device Time with Sync: %f without Sync: %f \n",sec1_dev,sec2_dev);
+  printf("Host   Time with Sync: %f without Sync: %f \n",sec1_host,sec2_host);
+}
+
+  Kokkos::finalize();
+}
+
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/CMakeLists.txt b/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/CMakeLists.txt
new file mode 100644
index 0000000000..f0ed569f9f
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+IF (Kokkos_ENABLE_Cuda_UVM)
+  # This is a tutorial, not a test, so we don't ask CTest to run it.
+  TRIBITS_ADD_EXECUTABLE(
+    tutorial_advancedviews_05_nvidia_uvm
+    SOURCES uvm_example.cpp
+    COMM serial mpi
+    DEPLIBS kokkoscontainers kokkoscore
+    )
+ENDIF ()
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/Makefile b/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/uvm_example.cpp b/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/uvm_example.cpp
new file mode 100644
index 0000000000..cf5326b687
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/05_NVIDIA_UVM/uvm_example.cpp
@@ -0,0 +1,134 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_DualView.hpp>
+#include <impl/Kokkos_Timer.hpp>
+#include <cstdio>
+#include <cstdlib>
+
+typedef Kokkos::View<double*> view_type;
+typedef Kokkos::View<int**> idx_type;
+
+
+template<class Device>
+struct localsum {
+  // Define the execution space for the functor (overrides the DefaultExecutionSpace)
+  typedef Device execution_space;
+
+  // Get the view types on the particular device the functor is instantiated for
+  idx_type::const_type idx;
+  view_type dest;
+  Kokkos::View<view_type::const_data_type, view_type::array_layout, view_type::execution_space, Kokkos::MemoryRandomAccess > src;
+
+  localsum(idx_type idx_, view_type dest_,
+      view_type src_):idx(idx_),dest(dest_),src(src_) {
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i) const {
+    double tmp = 0.0;
+    for(int j = 0; j < idx.dimension_1(); j++) {
+      const double val = src(idx(i,j));
+      tmp += val*val + 0.5*(idx.dimension_0()*val -idx.dimension_1()*val);
+    }
+    dest(i) += tmp;
+  }
+};
+
+int main(int narg, char* arg[]) {
+  Kokkos::initialize(narg,arg);
+
+  int size = 1000000;
+
+  // Create Views
+  idx_type idx("Idx",size,64);
+  view_type dest("Dest",size);
+  view_type src("Src",size);
+
+  srand(134231);
+
+  // When using UVM Cuda views can be accessed on the Host directly
+  for(int i=0; i<size; i++) {
+    for(int j=0; j<idx.dimension_1(); j++)
+      idx(i,j) = (size + i + (rand()%500 - 250))%size;
+  }
+
+  Kokkos::fence();
+  // Run on the device
+  // This will cause a sync of idx to the device since it was modified on the host
+  Kokkos::Timer timer;
+  Kokkos::parallel_for(size,localsum<view_type::execution_space>(idx,dest,src));
+  Kokkos::fence();
+  double sec1_dev = timer.seconds();
+
+  // No data transfer will happen now, since nothing is accessed on the host
+  timer.reset();
+  Kokkos::parallel_for(size,localsum<view_type::execution_space>(idx,dest,src));
+  Kokkos::fence();
+  double sec2_dev = timer.seconds();
+
+  // Run on the host
+  // This will cause a sync back to the host of dest which was changed on the device
+  // Compare runtime here with the dual_view example: dest will be copied back in 4k blocks
+  // when they are accessed the first time during the parallel_for. Due to the latency of a memcpy
+  // this gives lower effective bandwidth when doing a manual copy via dual views
+  timer.reset();
+  Kokkos::parallel_for(size,localsum<Kokkos::HostSpace::execution_space>(idx,dest,src));
+  Kokkos::fence();
+  double sec1_host = timer.seconds();
+
+  // No data transfers will happen now
+  timer.reset();
+  Kokkos::parallel_for(size,localsum<Kokkos::HostSpace::execution_space>(idx,dest,src));
+  Kokkos::fence();
+  double sec2_host = timer.seconds();
+
+
+
+  printf("Device Time with Sync: %lf without Sync: %lf \n",sec1_dev,sec2_dev);
+  printf("Host   Time with Sync: %lf without Sync: %lf \n",sec1_host,sec2_host);
+
+  Kokkos::finalize();
+}
+
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/06_AtomicViews/Makefile b/lib/kokkos/example/tutorial/Advanced_Views/06_AtomicViews/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/06_AtomicViews/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/07_Overlapping_DeepCopy/Makefile b/lib/kokkos/example/tutorial/Advanced_Views/07_Overlapping_DeepCopy/Makefile
new file mode 100644
index 0000000000..60a514f4d5
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/07_Overlapping_DeepCopy/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3 --default-stream per-thread 
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/07_Overlapping_DeepCopy/overlapping_deepcopy.cpp b/lib/kokkos/example/tutorial/Advanced_Views/07_Overlapping_DeepCopy/overlapping_deepcopy.cpp
new file mode 100644
index 0000000000..5da3bf76c9
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/07_Overlapping_DeepCopy/overlapping_deepcopy.cpp
@@ -0,0 +1,148 @@
+/*
+//@HEADER
+// ************************************************************************
+//
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+//
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+//
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+//
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+#include <typeinfo>
+#include <cmath>
+#include <impl/Kokkos_Timer.hpp>
+
+struct FillDevice {
+  double value;
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace> a;
+  FillDevice(const double& val, const Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace>& d_a):
+     value(val),a(d_a){}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i) const {
+    a(i) = value;
+  }
+};
+
+struct ComputeADevice {
+  int iter;
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace> a;
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace> b;
+  ComputeADevice(const int& iter_,
+                 const Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace>& d_a,
+                 const Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace>& d_b):
+     iter(iter_),a(d_a),b(d_b){}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i) const {
+    for(int j=1;j<iter;j++) {
+      a(i) += std::pow(b(i),1.0+1.0/iter);
+    }
+  }
+};
+
+struct ComputeAHost {
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaHostPinnedSpace> a;
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaHostPinnedSpace> b;
+  ComputeAHost(  const Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaHostPinnedSpace>& d_a,
+                 const Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaHostPinnedSpace>& d_b):
+     a(d_a),b(d_b){}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i) const {
+    a(i) += b(i);
+  }
+};
+
+struct MergeDevice {
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace> a;
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace> b;
+  MergeDevice(
+                 const Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace>& d_a,
+                 const Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace>& d_b):
+     a(d_a),b(d_b){}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (const int& i) const {
+    a(i) += b(i);
+  }
+};
+
+int main(int argc, char * argv[]) {
+  int size = 100000000;
+  Kokkos::initialize();
+  int synch = atoi(argv[1]);
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace> d_a("Device A",size);
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace> d_b("Device B",size);
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaSpace> d_tmp("Device tmp",size);
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaHostPinnedSpace> h_a("Host A",size);
+  Kokkos::View<double*,Kokkos::LayoutLeft,Kokkos::CudaHostPinnedSpace> h_b("Host B",size);
+
+  Kokkos::parallel_for(Kokkos::RangePolicy<Kokkos::Cuda>(0,size),FillDevice(0.0,d_a));
+  Kokkos::parallel_for(Kokkos::RangePolicy<Kokkos::Cuda>(0,size),FillDevice(1.3513,d_b));
+  Kokkos::fence();
+  Kokkos::Timer timer;
+  Kokkos::parallel_for(Kokkos::RangePolicy<Kokkos::Cuda>(0,size),ComputeADevice(20,d_a,d_b));
+
+  if(synch==1)
+    Kokkos::deep_copy(Kokkos::OpenMP(),h_b,d_b);
+  if(synch==2)
+    Kokkos::deep_copy(h_b,d_b);
+
+
+  Kokkos::parallel_for(Kokkos::RangePolicy<Kokkos::OpenMP>(0,size),[=] (const int& i) {
+    h_a(i) = 0.0;
+  });
+  Kokkos::parallel_for(Kokkos::RangePolicy<Kokkos::OpenMP>(0,size),ComputeAHost(h_a,h_b));
+  Kokkos::OpenMP::fence();
+  if(synch==1)
+    Kokkos::deep_copy(Kokkos::OpenMP(), d_tmp,h_a);
+  if(synch==2)
+    Kokkos::deep_copy(d_tmp,h_a);
+  Kokkos::fence();
+
+  std::cout << "Time " << timer.seconds() << std::endl;
+  Kokkos::parallel_for(Kokkos::RangePolicy<Kokkos::Cuda>(0,size),MergeDevice(d_a,d_tmp));
+
+  Kokkos::deep_copy(h_a,d_a);
+  std::cout << "h_a(0): " << h_a(0) << " ( Correct: 27.4154 )" << std::endl;
+  Kokkos::finalize();
+}
+
+
+
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/CMakeLists.txt b/lib/kokkos/example/tutorial/Advanced_Views/CMakeLists.txt
new file mode 100644
index 0000000000..f4f1addc55
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/CMakeLists.txt
@@ -0,0 +1,9 @@
+
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(01_data_layouts)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(02_memory_traits)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(03_subviews)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(04_dualviews)
+
+IF (Kokkos_ENABLE_Cuda_UVM)
+  TRIBITS_ADD_EXAMPLE_DIRECTORIES(05_NVIDIA_UVM)
+ENDIF ()
diff --git a/lib/kokkos/example/tutorial/Advanced_Views/Makefile b/lib/kokkos/example/tutorial/Advanced_Views/Makefile
new file mode 100644
index 0000000000..19053b61b0
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Advanced_Views/Makefile
@@ -0,0 +1,84 @@
+default:
+	cd ./01_data_layouts; \
+	make -j 4
+	cd ./02_memory_traits; \
+	make -j 4
+	cd ./03_subviews; \
+	make -j 4
+	cd ./04_dualviews; \
+	make -j 4
+	cd ./05_NVIDIA_UVM; \
+	make -j 4
+	cd ./06_AtomicViews; \
+	make -j 4
+
+openmp:
+	cd ./01_data_layouts; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./02_memory_traits; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./03_subviews; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./04_dualviews; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./05_NVIDIA_UVM; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./06_AtomicViews; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+
+pthreads:
+	cd ./01_data_layouts; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./02_memory_traits; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./03_subviews; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./04_dualviews; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./05_NVIDIA_UVM; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./06_AtomicViews; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+
+serial:
+	cd ./01_data_layouts; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./02_memory_traits; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./03_subviews; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./04_dualviews; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./05_NVIDIA_UVM; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./06_AtomicViews; \
+	make -j 4 KOKKOS_DEVICES=Serial
+
+cuda:
+	cd ./01_data_layouts; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./02_memory_traits; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./03_subviews; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./04_dualviews; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./05_NVIDIA_UVM; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./06_AtomicViews; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+
+clean:
+	cd ./01_data_layouts; \
+	make clean
+	cd ./02_memory_traits; \
+	make clean
+	cd ./03_subviews; \
+	make clean
+	cd ./04_dualviews; \
+	make clean
+	cd ./05_NVIDIA_UVM; \
+	make clean
+	cd ./06_AtomicViews; \
+	make clean
+
diff --git a/lib/kokkos/example/tutorial/Algorithms/01_random_numbers/Makefile b/lib/kokkos/example/tutorial/Algorithms/01_random_numbers/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Algorithms/01_random_numbers/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Algorithms/01_random_numbers/random_numbers.cpp b/lib/kokkos/example/tutorial/Algorithms/01_random_numbers/random_numbers.cpp
new file mode 100644
index 0000000000..3e6175a756
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Algorithms/01_random_numbers/random_numbers.cpp
@@ -0,0 +1,152 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Random.hpp>
+#include <Kokkos_DualView.hpp>
+#include <impl/Kokkos_Timer.hpp>
+#include <cstdlib>
+
+typedef Kokkos::HostSpace::execution_space DefaultHostType;
+
+// Kokkos provides two different random number generators with a 64 bit and a 1024 bit state.
+// These generators are based on Vigna, Sebastiano (2014). "An experimental exploration of Marsaglia's xorshift generators, scrambled"
+// See: http://arxiv.org/abs/1402.6246
+// The generators can be used fully independently on each thread and have been tested to
+// produce good statistics for both inter and intra thread numbers.
+// Note that within a kernel NO random number operations are (team) collective operations.
+// Everything can be called within branches. This is a difference to the curand library where
+// certain operations are required to be called by all threads in a block.
+//
+// In Kokkos you are required to create a pool of generator states, so that threads can
+// grep their own. On CPU architectures the pool size is equal to the thread number,
+// on CUDA about 128k states are generated (enough to give every potentially simultaneously
+// running thread its own state). With a kernel a thread is required to aquire a state from the
+// pool and later return it.
+// On CPUs the Random number generator is deterministic if using the same number of threads.
+// On GPUs (i.e. using the CUDA backend it is not deterministic because threads aquire states via
+// atomics.
+
+// A Functor for generating uint64_t random numbers templated on the GeneratorPool type
+template<class GeneratorPool>
+struct generate_random {
+
+  // The GeneratorPool
+  GeneratorPool rand_pool;
+
+  // Output View for the random numbers
+  Kokkos::View<uint64_t*> vals;
+  int samples;
+
+  // Initialize all members
+  generate_random(Kokkos::View<uint64_t*> vals_,
+                       GeneratorPool rand_pool_,
+                       int samples_):
+                       vals(vals_),rand_pool(rand_pool_),samples(samples_) {}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() (int i) const {
+    // Get a random number state from the pool for the active thread
+    typename GeneratorPool::generator_type rand_gen = rand_pool.get_state();
+
+    // Draw samples numbers from the pool as urand64 between 0 and rand_pool.MAX_URAND64
+    // Note there are function calls to get other type of scalars, and also to specify
+    // Ranges or get a normal distributed float.
+    for(int k = 0;k<samples;k++)
+      vals(i*samples+k) = rand_gen.urand64();
+
+    // Give the state back, which will allow another thread to aquire it
+    rand_pool.free_state(rand_gen);
+  }
+};
+
+
+
+
+int main(int argc, char* args[]) {
+  if (argc != 3){
+	printf("Please pass two integers on the command line\n");
+  }
+  else {
+
+  // Initialize Kokkos
+  Kokkos::initialize(argc,args);
+  int size = atoi(args[1]);
+  int samples = atoi(args[2]);
+
+  // Create two random number generator pools one for 64bit states and one for 1024 bit states
+  // Both take an 64 bit unsigned integer seed to initialize a Random_XorShift64 generator which
+  // is used to fill the generators of the pool.
+  Kokkos::Random_XorShift64_Pool<> rand_pool64(5374857);
+  Kokkos::Random_XorShift1024_Pool<> rand_pool1024(5374857);
+  Kokkos::DualView<uint64_t*> vals("Vals",size*samples);
+
+  // Run some performance comparisons
+  Kokkos::Timer timer;
+  Kokkos::parallel_for(size,generate_random<Kokkos::Random_XorShift64_Pool<> >(vals.d_view,rand_pool64,samples));
+  Kokkos::fence();
+
+  timer.reset();
+  Kokkos::parallel_for(size,generate_random<Kokkos::Random_XorShift64_Pool<> >(vals.d_view,rand_pool64,samples));
+  Kokkos::fence();
+  double time_64 = timer.seconds();
+
+  Kokkos::parallel_for(size,generate_random<Kokkos::Random_XorShift1024_Pool<> >(vals.d_view,rand_pool1024,samples));
+  Kokkos::fence();
+
+  timer.reset();
+  Kokkos::parallel_for(size,generate_random<Kokkos::Random_XorShift1024_Pool<> >(vals.d_view,rand_pool1024,samples));
+  Kokkos::fence();
+  double time_1024 = timer.seconds();
+
+  printf("#Time XorShift64*:   %lf %lf\n",time_64,1.0e-9*samples*size/time_64 );
+  printf("#Time XorShift1024*: %lf %lf\n",time_1024,1.0e-9*samples*size/time_1024 );
+
+  Kokkos::deep_copy(vals.h_view,vals.d_view);
+
+  Kokkos::finalize();
+  }
+  return 0;
+}
+
+
diff --git a/lib/kokkos/example/tutorial/Algorithms/Makefile b/lib/kokkos/example/tutorial/Algorithms/Makefile
new file mode 100644
index 0000000000..edc2a36024
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Algorithms/Makefile
@@ -0,0 +1,24 @@
+default:
+	cd ./01_random_numbers; \
+	make -j 4
+
+openmp:
+	cd ./01_random_numbers; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+
+pthreads:
+	cd ./01_random_numbers; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+
+serial:
+	cd ./01_random_numbers; \
+	make -j 4 KOKKOS_DEVICES=Serial
+
+cuda:
+	cd ./01_random_numbers; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+
+clean:
+	cd ./01_random_numbers; \
+	make clean
+
diff --git a/lib/kokkos/example/tutorial/CMakeLists.txt b/lib/kokkos/example/tutorial/CMakeLists.txt
new file mode 100644
index 0000000000..d1fd4c0ae9
--- /dev/null
+++ b/lib/kokkos/example/tutorial/CMakeLists.txt
@@ -0,0 +1,17 @@
+
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(01_hello_world)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(02_simple_reduce)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(03_simple_view)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(04_simple_memoryspaces)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(05_simple_atomics)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(Advanced_Views)
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(Hierarchical_Parallelism)
+
+IF (Kokkos_ENABLE_CXX11)
+  TRIBITS_ADD_EXAMPLE_DIRECTORIES(01_hello_world_lambda)
+  TRIBITS_ADD_EXAMPLE_DIRECTORIES(02_simple_reduce_lambda)
+  TRIBITS_ADD_EXAMPLE_DIRECTORIES(03_simple_view_lambda)
+ENDIF ()
+
+
+
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/CMakeLists.txt b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/CMakeLists.txt
new file mode 100644
index 0000000000..2d8a514a45
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_hierarchicalparallelism_01_thread_teams
+  SOURCES thread_teams.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/Makefile b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/thread_teams.cpp b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/thread_teams.cpp
new file mode 100644
index 0000000000..f2de0809a7
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams/thread_teams.cpp
@@ -0,0 +1,94 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+
+// Using default execution space define a TeamPolicy and its member_type
+// The member_type is what the operator of a functor or Lambda gets, for
+// a simple RangePolicy the member_type is simply an integer
+// For a TeamPolicy its a much richer object, since it provides all information
+// to identify a thread uniquely and some team related function calls such as a
+// barrier (which will be used in a subsequent example).
+// A ThreadTeam consists of 1 to n threads where the maxmimum value of n is
+// determined by the hardware. On a dual socket CPU machine with 8 cores per socket
+// the maximum size of a team is 8. The number of teams (i.e. the league_size) is
+// not limited by physical constraints. Its a pure logical number.
+
+typedef Kokkos::TeamPolicy<>              team_policy ;
+typedef team_policy::member_type team_member ;
+
+// Define a functor which can be launched using the TeamPolicy
+struct hello_world {
+  typedef int value_type; //Specify value type for reduction target, sum
+
+  // This is a reduction operator which now takes as first argument the
+  // TeamPolicy member_type. Every member of the team contributes to the
+  // total sum.
+  // It is helpful to think of this operator as a parallel region for a team
+  // (i.e. every team member is active and will execute the code).
+  KOKKOS_INLINE_FUNCTION
+  void operator() ( const team_member & thread, int& sum) const {
+    sum+=1;
+    // The TeamPolicy<>::member_type provides functions to query the multi
+    // dimensional index of a thread as well as the number of thread-teams and the size
+    // of each team.
+    printf("Hello World: %i %i // %i %i\n",thread.league_rank(),thread.team_rank(),thread.league_size(),thread.team_size());
+  }
+};
+
+int main(int narg, char* args[]) {
+  Kokkos::initialize(narg,args);
+
+  // Launch 12 teams of the maximum number of threads per team
+  const team_policy policy( 12 , team_policy::team_size_max( hello_world() ) );
+  
+  int sum = 0;
+  Kokkos::parallel_reduce( policy , hello_world() , sum );
+
+  // The result will be 12*team_policy::team_size_max( hello_world())
+  printf("Result %i\n",sum);
+
+  Kokkos::finalize();
+}
+
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/CMakeLists.txt b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/CMakeLists.txt
new file mode 100644
index 0000000000..ec7f1e1159
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/CMakeLists.txt
@@ -0,0 +1,13 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+IF (Kokkos_ENABLE_CXX11)
+  # This is a tutorial, not a test, so we don't ask CTest to run it.
+  TRIBITS_ADD_EXECUTABLE(
+    tutorial_hierarchical_01_thread_teams_lambda
+    SOURCES thread_teams_lambda.cpp
+    COMM serial mpi
+    )
+ENDIF ()
+
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/Makefile b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/Makefile
new file mode 100644
index 0000000000..965b72b4e9
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/Makefile
@@ -0,0 +1,44 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+KOKKOS_CUDA_OPTIONS = "enable_lambda"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/thread_teams_lambda.cpp b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/thread_teams_lambda.cpp
new file mode 100644
index 0000000000..565dd22e82
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/01_thread_teams_lambda/thread_teams_lambda.cpp
@@ -0,0 +1,94 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+
+// Demonstrate a parallel reduction using thread teams (TeamPolicy).
+//
+// A thread team consists of 1 to n threads.  The hardware determines
+// the maxmimum value of n. On a dual-socket CPU machine with 8 cores
+// per socket, the maximum size of a team is 8. The number of teams
+// (the league_size) is not limited by physical constraints (up to
+// some reasonable bound, which eventually depends upon the hardware
+// and programming model implementation).
+
+int main (int narg, char* args[]) {
+  using Kokkos::parallel_reduce;
+  typedef Kokkos::TeamPolicy<>               team_policy;
+  typedef typename team_policy::member_type  team_member;
+
+  Kokkos::initialize (narg, args);
+
+  // Set up a policy that launches 12 teams, with the maximum number
+  // of threads per team.
+
+  const team_policy policy (12, Kokkos::AUTO);
+
+  // This is a reduction with a team policy.  The team policy changes
+  // the first argument of the lambda.  Rather than an integer index
+  // (as with RangePolicy), it's now TeamPolicy::member_type.  This
+  // object provides all information to identify a thread uniquely.
+  // It also provides some team-related function calls such as a team
+  // barrier (which a subsequent example will use).
+  //
+  // Every member of the team contributes to the total sum.  It is
+  // helpful to think of the lambda's body as a "team parallel
+  // region."  That is, every team member is active and will execute
+  // the body of the lambda.
+  int sum = 0;
+  parallel_reduce (policy, KOKKOS_LAMBDA (const team_member& thread, int& lsum) {
+      lsum += 1;
+      // TeamPolicy<>::member_type provides functions to query the
+      // multidimensional index of a thread, as well as the number of
+      // thread teams and the size of each team.
+      printf ("Hello World: %i %i // %i %i\n", thread.league_rank (),
+              thread.team_rank (), thread.league_size (), thread.team_size ());
+    }, sum);
+
+  // The result will be 12*team_policy::team_size_max([=]{})
+  printf ("Result %i\n",sum);
+
+  Kokkos::finalize ();
+}
+
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/CMakeLists.txt b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/CMakeLists.txt
new file mode 100644
index 0000000000..e660405345
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_hierarchicalparallelism_02_nested_parallel_for
+  SOURCES nested_parallel_for.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/Makefile b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/nested_parallel_for.cpp b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/nested_parallel_for.cpp
new file mode 100644
index 0000000000..4357b4fa1a
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/02_nested_parallel_for/nested_parallel_for.cpp
@@ -0,0 +1,89 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <cstdio>
+
+// See 01_thread_teams for an explanation of a basic TeamPolicy
+typedef Kokkos::TeamPolicy<>              team_policy ;
+typedef typename team_policy::member_type team_member ;
+
+struct hello_world {
+  typedef int value_type; //Specify value type for reduction target, sum
+  KOKKOS_INLINE_FUNCTION
+  void operator() ( const team_member & thread, int& sum) const {
+    sum+=1;
+    // When using the TeamPolicy Kokkos allows for nested parallel loops.
+    // All three Kokkos parallel patterns are allowed (for, reduce, scan) and they
+    // largely follow the same syntax as on the global level.
+    // The execution policy for the Thread level nesting (the Vector level is in the next
+    // tutorial example) is Kokkos::TeamThreadRange. This means the loop will be executed
+    // by all members of the team and the loop count will be split between threads of the
+    // team. Its arguments are the team_member, and a loop count.
+    // Not every thread will do the same amount of iterations. On a GPU for example with
+    // a team_size() larger than 31 only the first 31 threads would actually do anything.
+    // On a CPU with 8 threads 7 would execute 4 loop iterations, and 1 thread would do
+    // 3. Note also that the mode of splitting the count is architecture dependent similar
+    // to what the RangePolicy on a global level does.
+    // The call itself is not guaranteed to be synchronous. Also keep in mind that the
+    // operator using a team_policy acts like a parallel region for the team. That means
+    // that everything outside of the nested parallel_for is also executed by all threads
+    // of the team.
+    Kokkos::parallel_for(Kokkos::TeamThreadRange(thread,31), [&] (const int& i) {
+       printf("Hello World: (%i , %i) executed loop %i \n",thread.league_rank(),thread.team_rank(),i);
+    });
+  }
+};
+
+int main(int narg, char* args[]) {
+  Kokkos::initialize(narg,args);
+
+  // Launch 3 teams of the maximum number of threads per team
+  const team_policy policy( 3 , team_policy::team_size_max( hello_world() ) );
+  
+  int sum = 0;
+  Kokkos::parallel_reduce( policy , hello_world() , sum );
+  printf("Result %i\n",sum);
+
+  Kokkos::finalize();
+}
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/CMakeLists.txt b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/CMakeLists.txt
new file mode 100644
index 0000000000..ea6b0b1e42
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/CMakeLists.txt
@@ -0,0 +1,16 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+
+IF(Kokkos_ENABLE_CXX11)
+
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_hierarchicalparallelism_03_vectorization
+  SOURCES vectorization.cpp
+  COMM serial mpi
+  )
+
+ENDIF()
+
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/Makefile b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/vectorization.cpp b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/vectorization.cpp
new file mode 100644
index 0000000000..99d5958edf
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/03_vectorization/vectorization.cpp
@@ -0,0 +1,162 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_Random.hpp>
+#include <cstdio>
+
+#ifdef KOKKOS_HAVE_CXX11
+
+// The TeamPolicy actually supports 3D parallelism: Teams, Threads, Vector
+// Kokkos::parallel_{for/reduce/scan} calls can be completely free nested.
+// The execution policies for the nested layers are TeamThreadRange and
+// ThreadVectorRange.
+// The only restriction on nesting is that a given level can only be nested in a
+// higher one. e.g. a ThreadVectorRange can be nested inside a TeamPolicy operator
+// and inside a TeamThreadRange, but you can not nest a ThreadVectorRange or a
+// TeamThreadRange inside another ThreadVectorRange.
+// As with the 2D execution of TeamPolicy the operator has to be considered as
+// a parallel region even with respect to VectorLanes. That means even outside
+// a TeamThread or VectorThread loop all threads of a team and all vector lanes
+// of a thread execute every line of the operator as long as there are no restricitons
+// on them.
+// Code lines can be restricted using Kokkos::single to either execute once PerThread
+// or execute once PerTeam.
+typedef typename Kokkos::TeamPolicy<>::member_type team_member ;
+
+struct SomeCorrelation {
+  typedef int value_type; //Specify value type for reduction target, sum
+  typedef Kokkos::DefaultExecutionSpace::scratch_memory_space shared_space;
+  typedef Kokkos::View<int*,shared_space,Kokkos::MemoryUnmanaged> shared_1d_int;
+
+  Kokkos::View<const int***,Kokkos::LayoutRight> data;
+  Kokkos::View<int> gsum;
+
+  SomeCorrelation(Kokkos::View<int***,Kokkos::LayoutRight> data_in,
+                  Kokkos::View<int> sum):data(data_in),gsum(sum){}
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() ( const team_member & thread) const {
+    int i = thread.league_rank();
+
+    // Allocate a shared array for the team.
+    shared_1d_int count(thread.team_shmem(),data.dimension_1());
+
+    // With each team run a parallel_for with its threads
+    Kokkos::parallel_for(Kokkos::TeamThreadRange(thread,data.dimension_1()), [=] (const int& j) {
+      int tsum;
+      // Run a vector loop reduction over the inner dimension of data
+      // Count how many values are multiples of 4
+      // Every vector lane gets the same reduction value (tsum) back, it is broadcast to all vector lanes
+      Kokkos::parallel_reduce(Kokkos::ThreadVectorRange(thread,data.dimension_2()), [=] (const int& k, int & vsum) {
+        vsum+= (data(i,j,k) % 4 == 0)?1:0;
+      },tsum);
+
+      // Make sure only one vector lane adds the reduction value to the shared array, i.e. execute
+      // the next line only once PerThread
+      Kokkos::single(Kokkos::PerThread(thread),[=] () {
+        count(j) = tsum;
+      });
+    });
+
+    // Wait for all threads to finish the parallel_for so that all shared memory writes are done
+    thread.team_barrier();
+
+    // Check with one vector lane from each thread how many consecutive
+    // data segments have the same number of values divisible by 4
+    // The team reduction value is again broadcast to every team member (and every vector lane)
+    int team_sum = 0;
+    Kokkos::parallel_reduce(Kokkos::TeamThreadRange(thread, data.dimension_1()-1), [=] (const int& j, int& thread_sum) {
+      // It is not valid to directly add to thread_sum
+      // Use a single function with broadcast instead
+      // team_sum will be used as input to the operator (i.e. it is used to initialize sum)
+      // the end value of sum will be broadcast to all vector lanes in the thread.
+      Kokkos::single(Kokkos::PerThread(thread),[=] (int& sum) {
+        if(count(j)==count(j+1)) sum++;
+      },thread_sum);
+    },team_sum);
+
+    // Add with one thread and vectorlane of the team the team_sum to the global value
+    Kokkos::single(Kokkos::PerTeam(thread),[=] () {
+      Kokkos::atomic_add(&gsum(),team_sum);
+    });
+  }
+
+  // The functor needs to define how much shared memory it requests given a team_size.
+  size_t team_shmem_size( int team_size ) const {
+    return shared_1d_int::shmem_size(data.dimension_1());
+  }
+};
+
+int main(int narg, char* args[]) {
+  Kokkos::initialize(narg,args);
+
+  // Produce some 3D random data (see Algorithms/01_random_numbers for more info)
+  Kokkos::View<int***,Kokkos::LayoutRight> data("Data",512,512,32);
+  Kokkos::Random_XorShift64_Pool<> rand_pool64(5374857);
+  Kokkos::fill_random(data,rand_pool64,100);
+
+  // A global value to put the result in
+  Kokkos::View<int> gsum("Sum");
+
+  // Each team handles a slice of the data
+  // Set up TeamPolicy with 512 teams with maximum number of threads per team and 16 vector lanes.
+  // Kokkos::AUTO will determine the number of threads
+  // The maximum vector length is hardware dependent but can always be smaller than the hardware allows.
+  // The vector length must be a power of 2.
+
+  const Kokkos::TeamPolicy<> policy( 512 , Kokkos::AUTO , 16);
+
+  Kokkos::parallel_for( policy , SomeCorrelation(data,gsum) );
+
+  Kokkos::fence();
+
+  // Copy result value back
+  int sum = 0;
+  Kokkos::deep_copy(sum,gsum);
+  printf("Result %i\n",sum);
+
+  Kokkos::finalize();
+}
+
+#endif //KOKKOS_HAVE_CXX11
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/CMakeLists.txt b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/CMakeLists.txt
new file mode 100644
index 0000000000..15ad5d7803
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+
+# This is a tutorial, not a test, so we don't ask CTest to run it.
+TRIBITS_ADD_EXECUTABLE(
+  tutorial_hierarchicalparallelism_04_team_scan
+  SOURCES team_scan.cpp
+  COMM serial mpi
+  )
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/Makefile b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/Makefile
new file mode 100644
index 0000000000..12ad36b31e
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/Makefile
@@ -0,0 +1,43 @@
+KOKKOS_PATH = ../../../..
+SRC = $(wildcard *.cpp)
+
+default: build
+	echo "Start Build"
+
+ifneq (,$(findstring Cuda,$(KOKKOS_DEVICES)))
+CXX = ../../../../config/nvcc_wrapper
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS = 
+EXE = $(SRC:.cpp=.cuda)
+KOKKOS_DEVICES = "Cuda,OpenMP"
+KOKKOS_ARCH = "SNB,Kepler35"
+else
+CXX = g++
+CXXFLAGS = -O3
+LINK = ${CXX}
+LINKFLAGS =  
+EXE = $(SRC:.cpp=.host)
+KOKKOS_DEVICES = "OpenMP"
+KOKKOS_ARCH = "SNB"
+endif
+
+DEPFLAGS = -M
+
+OBJ = $(SRC:.cpp=.o)
+LIB =
+
+include $(KOKKOS_PATH)/Makefile.kokkos
+
+build: $(EXE)
+
+$(EXE): $(OBJ) $(KOKKOS_LINK_DEPENDS)
+	$(LINK) $(KOKKOS_LDFLAGS) $(LINKFLAGS) $(EXTRA_PATH) $(OBJ) $(KOKKOS_LIBS) $(LIB) -o $(EXE)
+
+clean: kokkos-clean 
+	rm -f *.o *.cuda *.host
+
+# Compilation rules
+
+%.o:%.cpp $(KOKKOS_CPP_DEPENDS)
+	$(CXX) $(KOKKOS_CPPFLAGS) $(KOKKOS_CXXFLAGS) $(CXXFLAGS) $(EXTRA_INC) -c $<
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/team_scan.cpp b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/team_scan.cpp
new file mode 100644
index 0000000000..c12b11d04d
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/04_team_scan/team_scan.cpp
@@ -0,0 +1,141 @@
+/*
+//@HEADER
+// ************************************************************************
+// 
+//                        Kokkos v. 2.0
+//              Copyright (2014) Sandia Corporation
+// 
+// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
+// the U.S. Government retains certain rights in this software.
+// 
+// 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.
+//
+// 3. Neither the name of the Corporation nor the names of the
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "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 SANDIA CORPORATION OR THE
+// 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.
+//
+// Questions? Contact  H. Carter Edwards (hcedwar@sandia.gov)
+// 
+// ************************************************************************
+//@HEADER
+*/
+
+#include <Kokkos_Core.hpp>
+#include <Kokkos_DualView.hpp>
+#include <impl/Kokkos_Timer.hpp>
+#include <cstdio>
+#include <cstdlib>
+
+typedef Kokkos::DefaultExecutionSpace       Device ;
+typedef Kokkos::HostSpace::execution_space  Host ;
+
+typedef Kokkos::TeamPolicy< Device >      team_policy ;
+typedef team_policy::member_type team_member ;
+
+static const int TEAM_SIZE = 16 ;
+
+struct find_2_tuples {
+  int chunk_size;
+  Kokkos::View<const int*> data;
+  Kokkos::View<int**> histogram;
+
+  find_2_tuples(int chunk_size_, Kokkos::DualView<int*> data_,
+                Kokkos::DualView<int**> histogram_):chunk_size(chunk_size_),
+                data(data_.d_view),histogram(histogram_.d_view) {
+      data_.sync<Device>();
+      histogram_.sync<Device>();
+      histogram_.modify<Device>();
+  }
+
+  KOKKOS_INLINE_FUNCTION
+  void operator() ( const team_member & dev) const {
+    Kokkos::View<int**,Kokkos::MemoryUnmanaged> l_histogram(dev.team_shmem(),TEAM_SIZE,TEAM_SIZE);
+    Kokkos::View<int*,Kokkos::MemoryUnmanaged> l_data(dev.team_shmem(),chunk_size+1);
+
+    const int i = dev.league_rank() * chunk_size;
+    for(int j = dev.team_rank(); j<chunk_size+1; j+=dev.team_size())
+      l_data(j) = data(i+j);
+
+    for(int k = dev.team_rank(); k < TEAM_SIZE; k+=dev.team_size())
+      for(int l = 0; l < TEAM_SIZE; l++)
+        l_histogram(k,l) = 0;
+    dev.team_barrier();
+
+    for(int j = 0; j<chunk_size; j++) {
+      for(int k = dev.team_rank(); k < TEAM_SIZE; k+=dev.team_size())
+        for(int l = 0; l < TEAM_SIZE; l++) {
+          if((l_data(j) == k) && (l_data(j+1)==l))
+            l_histogram(k,l)++;
+        }
+    }
+
+    for(int k = dev.team_rank(); k < TEAM_SIZE; k+=dev.team_size())
+      for(int l = 0; l < TEAM_SIZE; l++) {
+        Kokkos::atomic_fetch_add(&histogram(k,l),l_histogram(k,l));
+      }
+    dev.team_barrier();
+  }
+  size_t team_shmem_size( int team_size ) const { return sizeof(int)*(chunk_size+2 + team_size * team_size ); }
+};
+
+int main(int narg, char* args[]) {
+  Kokkos::initialize(narg,args);
+  
+  int chunk_size = 1024;
+  int nchunks = 100000; //1024*1024;
+  Kokkos::DualView<int*> data("data",nchunks*chunk_size+1);
+
+  srand(1231093);
+
+  for(int i = 0; i < (int) data.dimension_0(); i++) {
+    data.h_view(i) = rand()%TEAM_SIZE;
+  }
+  data.modify<Host>();
+  data.sync<Device>();
+
+  Kokkos::DualView<int**> histogram("histogram",TEAM_SIZE,TEAM_SIZE);
+
+
+  Kokkos::Timer timer;
+  // threads/team is automatically limited to maximum supported by the device.
+  Kokkos::parallel_for( team_policy( nchunks , TEAM_SIZE )
+                      , find_2_tuples(chunk_size,data,histogram) );
+  Kokkos::fence();
+  double time = timer.seconds();
+
+  histogram.sync<Host>();
+
+  printf("Time: %f \n\n",time);
+  int sum = 0;
+  for(int k=0; k<TEAM_SIZE; k++) {
+    for(int l=0; l<TEAM_SIZE; l++) {
+      printf("%i ",histogram.h_view(k,l));
+      sum += histogram.h_view(k,l);
+    }
+    printf("\n");
+  }
+  printf("Result: %i %i\n",sum,chunk_size*nchunks);
+  Kokkos::finalize();
+}
+
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/CMakeLists.txt b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/CMakeLists.txt
new file mode 100644
index 0000000000..e03d7aeb90
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/CMakeLists.txt
@@ -0,0 +1,8 @@
+
+TRIBITS_ADD_EXAMPLE_DIRECTORIES(01_thread_teams)
+
+IF (Kokkos_ENABLE_CXX11)
+  TRIBITS_ADD_EXAMPLE_DIRECTORIES(01_thread_teams_lambda)
+  TRIBITS_ADD_EXAMPLE_DIRECTORIES(02_nested_parallel_for)
+  TRIBITS_ADD_EXAMPLE_DIRECTORIES(03_vectorization)
+ENDIF ()
diff --git a/lib/kokkos/example/tutorial/Hierarchical_Parallelism/Makefile b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/Makefile
new file mode 100644
index 0000000000..9d6fff7981
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Hierarchical_Parallelism/Makefile
@@ -0,0 +1,72 @@
+default:
+	cd ./01_thread_teams; \
+	make -j 4
+	cd ./01_thread_teams_lambda; \
+	make -j 4
+	cd ./02_nested_parallel_for; \
+	make -j 4
+	cd ./03_vectorization; \
+	make -j 4
+	cd ./04_team_scan; \
+	make -j 4
+
+openmp:
+	cd ./01_thread_teams; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./01_thread_teams_lambda; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./02_nested_parallel_for; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./03_vectorization; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./04_team_scan; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+
+pthreads:
+	cd ./01_thread_teams; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./01_thread_teams_lambda; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./02_nested_parallel_for; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./03_vectorization; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./04_team_scan; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+
+serial:
+	cd ./01_thread_teams; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./01_thread_teams_lambda; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./02_nested_parallel_for; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./03_vectorization; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./04_team_scan; \
+	make -j 4 KOKKOS_DEVICES=Serial
+
+cuda:
+	cd ./01_thread_teams; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./01_thread_teams_lambda; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./02_nested_parallel_for; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./03_vectorization; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./04_team_scan; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+
+clean:
+	cd ./01_thread_teams; \
+	make clean
+	cd ./01_thread_teams_lambda; \
+	make clean
+	cd ./02_nested_parallel_for; \
+	make clean
+	cd ./03_vectorization; \
+	make clean
+	cd ./04_team_scan; \
+	make clean
+
diff --git a/lib/kokkos/example/tutorial/Makefile b/lib/kokkos/example/tutorial/Makefile
new file mode 100644
index 0000000000..300d98ab44
--- /dev/null
+++ b/lib/kokkos/example/tutorial/Makefile
@@ -0,0 +1,144 @@
+default:
+	cd ./01_hello_world; \
+	make -j 4
+	cd ./01_hello_world_lambda; \
+	make -j 4
+	cd ./02_simple_reduce; \
+	make -j 4
+	cd ./02_simple_reduce_lambda; \
+	make -j 4
+	cd ./03_simple_view; \
+	make -j 4
+	cd ./03_simple_view_lambda; \
+	make -j 4
+	cd ./04_simple_memoryspaces; \
+	make -j 4
+	cd ./05_simple_atomics; \
+	make -j 4
+	cd ./Advanced_Views; \
+	make -j 4
+	cd ./Algorithms; \
+	make -j 4
+	cd ./Hierarchical_Parallelism; \
+	make -j 4
+
+openmp:
+	cd ./01_hello_world; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./01_hello_world_lambda; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./02_simple_reduce; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./02_simple_reduce_lambda; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./03_simple_view; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./03_simple_view_lambda; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./04_simple_memoryspaces; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./05_simple_atomics; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./Advanced_Views; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./Algorithms; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+	cd ./Hierarchical_Parallelism; \
+	make -j 4 KOKKOS_DEVICES=OpenMP
+
+pthreads:
+	cd ./01_hello_world; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./01_hello_world_lambda; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./02_simple_reduce; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./02_simple_reduce_lambda; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./03_simple_view; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./03_simple_view_lambda; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./04_simple_memoryspaces; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./05_simple_atomics; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./Advanced_Views; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./Algorithms; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+	cd ./Hierarchical_Parallelism; \
+	make -j 4 KOKKOS_DEVICES=Pthreads
+
+serial:
+	cd ./01_hello_world; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./01_hello_world_lambda; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./02_simple_reduce; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./02_simple_reduce_lambda; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./03_simple_view; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./03_simple_view_lambda; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./04_simple_memoryspaces; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./05_simple_atomics; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./Advanced_Views; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./Algorithms; \
+	make -j 4 KOKKOS_DEVICES=Serial
+	cd ./Hierarchical_Parallelism; \
+	make -j 4 KOKKOS_DEVICES=Serial
+
+cuda:
+	cd ./01_hello_world; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./01_hello_world_lambda; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./02_simple_reduce; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./02_simple_reduce_lambda; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./03_simple_view; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./03_simple_view_lambda; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./04_simple_memoryspaces; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./05_simple_atomics; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./Advanced_Views; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./Algorithms; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+	cd ./Hierarchical_Parallelism; \
+	make -j 4 KOKKOS_DEVICES=Cuda,Serial
+
+clean:
+	cd ./01_hello_world; \
+	make clean
+	cd ./01_hello_world_lambda; \
+	make clean
+	cd ./02_simple_reduce; \
+	make clean
+	cd ./02_simple_reduce_lambda; \
+	make clean
+	cd ./03_simple_view; \
+	make clean
+	cd ./03_simple_view_lambda; \
+	make clean
+	cd ./04_simple_memoryspaces; \
+	make clean
+	cd ./05_simple_atomics; \
+	make clean
+	cd ./Advanced_Views; \
+	make clean
+	cd ./Algorithms; \
+	make clean
+	cd ./Hierarchical_Parallelism; \
+	make clean
+
diff --git a/lib/kokkos/example/tutorial/README b/lib/kokkos/example/tutorial/README
new file mode 100644
index 0000000000..4ba0b3a5d9
--- /dev/null
+++ b/lib/kokkos/example/tutorial/README
@@ -0,0 +1,17 @@
+Build the examples by typing in each directory: 
+make -j 16
+
+To specify a target device:
+make openmp -j 16
+make pthreads -j 16
+make serial -j 16
+make cuda -j 16
+
+The lambda variants can not be build with CUDA=yes at the moment, since
+CUDA does not support lambdas from the host. 
+Some of the advanced topics try to highlight performance impacts by timing 
+different variants of doing the same thing.
+Also some of the advanced topics (in particular hierarchical parallelism)
+require C++11 even with out using host side lambdas. CUDA 6.5 can be used 
+to compile those. 
+
diff --git a/lib/kokkos/generate_makefile.bash b/lib/kokkos/generate_makefile.bash
new file mode 100755
index 0000000000..86f136da96
--- /dev/null
+++ b/lib/kokkos/generate_makefile.bash
@@ -0,0 +1,336 @@
+#!/bin/bash
+
+KOKKOS_DEVICES=""
+
+while [[ $# > 0 ]]
+do
+key="$1"
+
+case $key in
+    --kokkos-path*)
+    KOKKOS_PATH="${key#*=}"
+    ;;
+    --prefix*)
+    PREFIX="${key#*=}"
+    ;;
+    --with-cuda)
+    KOKKOS_DEVICES="${KOKKOS_DEVICES},Cuda"
+    CUDA_PATH_NVCC=`which nvcc`
+    CUDA_PATH=${CUDA_PATH_NVCC%/bin/nvcc}
+    ;;
+    # Catch this before '--with-cuda*'
+    --with-cuda-options*)
+    KOKKOS_CUDA_OPT="${key#*=}"
+    ;;
+    --with-cuda*)
+    KOKKOS_DEVICES="${KOKKOS_DEVICES},Cuda"
+    CUDA_PATH="${key#*=}"
+    ;;
+    --with-openmp)
+    KOKKOS_DEVICES="${KOKKOS_DEVICES},OpenMP"
+    ;;
+    --with-pthread)
+    KOKKOS_DEVICES="${KOKKOS_DEVICES},Pthread"
+    ;;
+    --with-serial)
+    KOKKOS_DEVICES="${KOKKOS_DEVICES},Serial"
+    ;;
+    --with-qthread*)
+    KOKKOS_DEVICES="${KOKKOS_DEVICES},Qthread"
+    QTHREAD_PATH="${key#*=}"
+    ;;
+    --with-devices*)
+    DEVICES="${key#*=}"
+    KOKKOS_DEVICES="${KOKKOS_DEVICES},${DEVICES}"
+    ;;
+    --with-gtest*)
+    GTEST_PATH="${key#*=}"
+    ;;
+    --with-hwloc*)
+    HWLOC_PATH="${key#*=}"
+    ;;
+    --arch*)
+    KOKKOS_ARCH="${key#*=}"
+    ;;
+    --cxxflags*)
+    CXXFLAGS="${key#*=}"
+    ;;
+    --ldflags*)
+    LDFLAGS="${key#*=}"
+    ;;
+    --debug|-dbg)
+    KOKKOS_DEBUG=yes
+    ;;
+    --compiler*)
+    COMPILER="${key#*=}"
+    ;;
+    --with-options*)
+    KOKKOS_OPT="${key#*=}"
+    ;;
+    --help)
+    echo "Kokkos configure options:"
+    echo "--kokkos-path=/Path/To/Kokkos: Path to the Kokkos root directory"
+    echo "--prefix=/Install/Path:        Path to where the Kokkos library should be installed"
+    echo ""
+    echo "--with-cuda[=/Path/To/Cuda]:      enable Cuda and set path to Cuda Toolkit"
+    echo "--with-openmp:                    enable OpenMP backend"
+    echo "--with-pthread:                   enable Pthreads backend"
+    echo "--with-serial:                    enable Serial backend"
+    echo "--with-qthread=/Path/To/Qthread:  enable Qthread backend"
+    echo "--with-devices:                   explicitly add a set of backends"
+    echo ""
+    echo "--arch=[OPTIONS]:            set target architectures. Options are:"
+    echo "                               SNB = Intel Sandy/Ivy Bridge CPUs"
+    echo "                               HSW = Intel Haswell CPUs"
+    echo "                               KNC = Intel Knights Corner Xeon Phi"
+    echo "                               KNL = Intel Knights Landing Xeon Phi"
+    echo "                               Kepler30  = NVIDIA Kepler generation CC 3.0"
+    echo "                               Kepler35  = NVIDIA Kepler generation CC 3.5"
+    echo "                               Kepler37  = NVIDIA Kepler generation CC 3.7"
+    echo "                               Maxwell50 = NVIDIA Maxwell generation CC 5.0"
+    echo "                               Power8 = IBM Power 8 CPUs"
+    echo ""
+    echo "--compiler=/Path/To/Compiler set the compiler"
+    echo "--debug,-dbg:                enable Debugging"
+    echo "--cxxflags=[FLAGS]           overwrite CXXFLAGS for library build and test build"
+    echo "                               This will still set certain required flags via"
+    echo "                               KOKKOS_CXXFLAGS (such as -fopenmp, --std=c++11, etc.)"
+    echo "--ldflags=[FLAGS]            overwrite LDFLAGS for library build and test build"
+    echo "                               This will still set certain required flags via"
+    echo "                               KOKKOS_LDFLAGS (such as -fopenmp, -lpthread, etc.)"
+    echo "--with-gtest=/Path/To/Gtest: set path to gtest (used in unit and performance tests"
+    echo "--with-hwloc=/Path/To/Hwloc: set path to hwloc"
+    echo "--with-options=[OPTIONS]:    additional options to Kokkos:"
+    echo "                               aggressive_vectorization = add ivdep on loops"
+    echo "--with-cuda-options=[OPTIONS]: additional options to CUDA:"
+    echo "                               force_uvm, use_ldg, enable_lambda, rdc"
+    exit 0
+    ;;
+    *)
+    echo "warning: ignoring unknown option $key"
+    ;;
+esac
+shift
+done
+
+# If KOKKOS_PATH undefined, assume parent dir of this
+# script is the KOKKOS_PATH
+if [ -z "$KOKKOS_PATH" ]; then
+    KOKKOS_PATH=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
+else
+    # Ensure KOKKOS_PATH is abs path
+    KOKKOS_PATH=$( cd $KOKKOS_PATH && pwd )
+fi
+
+if [ "${KOKKOS_PATH}"  = "${PWD}" ] || [ "${KOKKOS_PATH}"  = "${PWD}/" ]; then
+echo "Running generate_makefile.sh in the Kokkos root directory is not allowed"
+exit 
+fi
+
+KOKKOS_OPTIONS="KOKKOS_PATH=${KOKKOS_PATH}"
+
+if [ ${#COMPILER} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} CXX=${COMPILER}"
+fi
+if [ ${#PREFIX} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} PREFIX=${PREFIX}"
+fi
+if [ ${#KOKKOS_DEVICES} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} KOKKOS_DEVICES=${KOKKOS_DEVICES}"
+fi
+if [ ${#KOKKOS_ARCH} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} KOKKOS_ARCH=${KOKKOS_ARCH}"
+fi
+if [ ${#KOKKOS_DEBUG} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} KOKKOS_DEBUG=${KOKKOS_DEBUG}"
+fi
+if [ ${#CUDA_PATH} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} CUDA_PATH=${CUDA_PATH}"
+fi
+if [ ${#CXXFLAGS} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} CXXFLAGS=\"${CXXFLAGS}\""
+fi
+if [ ${#LDFLAGS} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} LDFLAGS=\"${LDFLAGS}\""
+fi
+if [ ${#GTEST_PATH} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} GTEST_PATH=${GTEST_PATH}"
+else
+GTEST_PATH=${KOKKOS_PATH}/tpls/gtest
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} GTEST_PATH=${GTEST_PATH}"
+fi
+if [ ${#HWLOC_PATH} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} HWLOC_PATH=${HWLOC_PATH} KOKKOS_USE_TPLS=hwloc"
+fi
+if [ ${#QTHREAD_PATH} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} QTHREAD_PATH=${QTHREAD_PATH}"
+fi
+if [ ${#KOKKOS_OPT} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} KOKKOS_OPTIONS=${KOKKOS_OPT}"
+fi
+if [ ${#KOKKOS_CUDA_OPT} -gt 0 ]; then
+KOKKOS_OPTIONS="${KOKKOS_OPTIONS} KOKKOS_CUDA_OPTIONS=${KOKKOS_CUDA_OPT}"
+fi
+mkdir core
+mkdir core/unit_test
+mkdir core/perf_test
+mkdir containers
+mkdir containers/unit_tests
+mkdir containers/performance_tests
+mkdir algorithms
+mkdir algorithms/unit_tests
+mkdir algorithms/performance_tests
+mkdir example
+mkdir example/fixture
+mkdir example/feint
+mkdir example/fenl
+
+if [ ${#KOKKOS_ENABLE_EXAMPLE_ICHOL} -gt 0 ]; then
+mkdir example/ichol
+fi
+
+# Generate subdirectory makefiles.
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > core/unit_test/Makefile
+echo "" >> core/unit_test/Makefile
+echo "all:" >> core/unit_test/Makefile
+echo -e "\tmake -j -f ${KOKKOS_PATH}/core/unit_test/Makefile ${KOKKOS_OPTIONS}" >> core/unit_test/Makefile
+echo "" >> core/unit_test/Makefile
+echo "test: all" >> core/unit_test/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/core/unit_test/Makefile ${KOKKOS_OPTIONS} test" >> core/unit_test/Makefile
+echo "" >> core/unit_test/Makefile
+echo "clean:" >> core/unit_test/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/core/unit_test/Makefile ${KOKKOS_OPTIONS} clean" >> core/unit_test/Makefile
+
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > core/perf_test/Makefile
+echo "" >> core/perf_test/Makefile
+echo "all:" >> core/perf_test/Makefile
+echo -e "\tmake -j -f ${KOKKOS_PATH}/core/perf_test/Makefile ${KOKKOS_OPTIONS}" >> core/perf_test/Makefile
+echo "" >> core/perf_test/Makefile
+echo "test: all" >> core/perf_test/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/core/perf_test/Makefile ${KOKKOS_OPTIONS} test" >> core/perf_test/Makefile
+echo "" >> core/perf_test/Makefile
+echo "clean:" >> core/perf_test/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/core/perf_test/Makefile ${KOKKOS_OPTIONS} clean" >> core/perf_test/Makefile
+
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > containers/unit_tests/Makefile
+echo "" >> containers/unit_tests/Makefile
+echo "all:" >> containers/unit_tests/Makefile
+echo -e "\tmake -j -f ${KOKKOS_PATH}/containers/unit_tests/Makefile ${KOKKOS_OPTIONS}" >> containers/unit_tests/Makefile
+echo "" >> containers/unit_tests/Makefile
+echo "test: all" >> containers/unit_tests/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/containers/unit_tests/Makefile ${KOKKOS_OPTIONS} test" >> containers/unit_tests/Makefile
+echo "" >> containers/unit_tests/Makefile
+echo "clean:" >> containers/unit_tests/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/containers/unit_tests/Makefile ${KOKKOS_OPTIONS} clean" >> containers/unit_tests/Makefile
+
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > containers/performance_tests/Makefile
+echo "" >> containers/performance_tests/Makefile
+echo "all:" >> containers/performance_tests/Makefile
+echo -e "\tmake -j -f ${KOKKOS_PATH}/containers/performance_tests/Makefile ${KOKKOS_OPTIONS}" >> containers/performance_tests/Makefile
+echo "" >> containers/performance_tests/Makefile
+echo "test: all" >> containers/performance_tests/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/containers/performance_tests/Makefile ${KOKKOS_OPTIONS} test" >> containers/performance_tests/Makefile
+echo "" >> containers/performance_tests/Makefile
+echo "clean:" >> containers/performance_tests/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/containers/performance_tests/Makefile ${KOKKOS_OPTIONS} clean" >> containers/performance_tests/Makefile
+
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > algorithms/unit_tests/Makefile
+echo "" >> algorithms/unit_tests/Makefile
+echo "all:" >> algorithms/unit_tests/Makefile
+echo -e "\tmake -j -f ${KOKKOS_PATH}/algorithms/unit_tests/Makefile ${KOKKOS_OPTIONS}" >> algorithms/unit_tests/Makefile
+echo "" >> algorithms/unit_tests/Makefile
+echo "test: all" >> algorithms/unit_tests/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/algorithms/unit_tests/Makefile ${KOKKOS_OPTIONS} test" >> algorithms/unit_tests/Makefile
+echo "" >> algorithms/unit_tests/Makefile
+echo "clean:" >> algorithms/unit_tests/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/algorithms/unit_tests/Makefile ${KOKKOS_OPTIONS} clean" >> algorithms/unit_tests/Makefile
+
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > example/fixture/Makefile
+echo "" >> example/fixture/Makefile
+echo "all:" >> example/fixture/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/fixture/Makefile ${KOKKOS_OPTIONS}" >> example/fixture/Makefile
+echo "" >> example/fixture/Makefile
+echo "test: all" >> example/fixture/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/fixture/Makefile ${KOKKOS_OPTIONS} test" >> example/fixture/Makefile
+echo "" >> example/fixture/Makefile
+echo "clean:" >> example/fixture/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/fixture/Makefile ${KOKKOS_OPTIONS} clean" >> example/fixture/Makefile
+
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > example/feint/Makefile
+echo "" >> example/feint/Makefile
+echo "all:" >> example/feint/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/feint/Makefile ${KOKKOS_OPTIONS}" >> example/feint/Makefile
+echo "" >> example/feint/Makefile
+echo "test: all" >> example/feint/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/feint/Makefile ${KOKKOS_OPTIONS} test" >> example/feint/Makefile
+echo "" >> example/feint/Makefile
+echo "clean:" >> example/feint/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/feint/Makefile ${KOKKOS_OPTIONS} clean" >> example/feint/Makefile
+
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > example/fenl/Makefile
+echo "" >> example/fenl/Makefile
+echo "all:" >> example/fenl/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/fenl/Makefile ${KOKKOS_OPTIONS}" >> example/fenl/Makefile
+echo "" >> example/fenl/Makefile
+echo "test: all" >> example/fenl/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/fenl/Makefile ${KOKKOS_OPTIONS} test" >> example/fenl/Makefile
+echo "" >> example/fenl/Makefile
+echo "clean:" >> example/fenl/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/fenl/Makefile ${KOKKOS_OPTIONS} clean" >> example/fenl/Makefile
+
+if [ ${#KOKKOS_ENABLE_EXAMPLE_ICHOL} -gt 0 ]; then
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > example/ichol/Makefile
+echo "" >> example/ichol/Makefile
+echo "all:" >> example/ichol/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/ichol/Makefile ${KOKKOS_OPTIONS}" >> example/ichol/Makefile
+echo "" >> example/ichol/Makefile
+echo "test: all" >> example/ichol/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/ichol/Makefile ${KOKKOS_OPTIONS} test" >> example/ichol/Makefile
+echo "" >> example/ichol/Makefile
+echo "clean:" >> example/ichol/Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/example/ichol/Makefile ${KOKKOS_OPTIONS} clean" >> example/ichol/Makefile
+fi
+
+# Generate top level directory makefile.
+echo "Generating Makefiles with options " ${KOKKOS_OPTIONS}
+echo "KOKKOS_OPTIONS=${KOKKOS_OPTIONS}" > Makefile
+echo "" >> Makefile
+echo "lib:" >> Makefile
+echo -e "\tcd core; \\" >> Makefile
+echo -e "\tmake -j -f ${KOKKOS_PATH}/core/src/Makefile ${KOKKOS_OPTIONS}" >> Makefile
+echo "" >> Makefile
+echo "install: lib" >> Makefile
+echo -e "\tcd core; \\" >> Makefile
+echo -e "\tmake -j -f ${KOKKOS_PATH}/core/src/Makefile ${KOKKOS_OPTIONS} install" >> Makefile
+echo "" >> Makefile
+echo "build-test:" >> Makefile
+echo -e "\tmake -C core/unit_test" >> Makefile
+echo -e "\tmake -C core/perf_test" >> Makefile
+echo -e "\tmake -C containers/unit_tests" >> Makefile
+echo -e "\tmake -C containers/performance_tests" >> Makefile
+echo -e "\tmake -C algorithms/unit_tests" >> Makefile
+echo -e "\tmake -C example/fixture" >> Makefile
+echo -e "\tmake -C example/feint" >> Makefile
+echo -e "\tmake -C example/fenl" >> Makefile
+echo "" >> Makefile
+echo "test: build-test" >> Makefile
+echo -e "\tmake -C core/unit_test test" >> Makefile
+echo -e "\tmake -C core/perf_test test" >> Makefile
+echo -e "\tmake -C containers/unit_tests test" >> Makefile
+echo -e "\tmake -C containers/performance_tests test" >> Makefile
+echo -e "\tmake -C algorithms/unit_tests test" >> Makefile
+echo -e "\tmake -C example/fixture test" >> Makefile
+echo -e "\tmake -C example/feint test" >> Makefile
+echo -e "\tmake -C example/fenl test" >> Makefile
+echo "" >> Makefile
+echo "clean:" >> Makefile
+echo -e "\tmake -C core/unit_test clean" >> Makefile
+echo -e "\tmake -C core/perf_test clean" >> Makefile
+echo -e "\tmake -C containers/unit_tests clean" >> Makefile
+echo -e "\tmake -C containers/performance_tests clean" >> Makefile
+echo -e "\tmake -C algorithms/unit_tests clean" >> Makefile
+echo -e "\tmake -C example/fixture clean" >> Makefile
+echo -e "\tmake -C example/feint clean" >> Makefile
+echo -e "\tmake -C example/fenl clean" >> Makefile
+echo -e "\tcd core; \\" >> Makefile
+echo -e "\tmake -f ${KOKKOS_PATH}/core/src/Makefile ${KOKKOS_OPTIONS} clean" >> Makefile
diff --git a/lib/kokkos/tpls/gtest/gtest/LICENSE b/lib/kokkos/tpls/gtest/gtest/LICENSE
new file mode 100644
index 0000000000..1941a11f8c
--- /dev/null
+++ b/lib/kokkos/tpls/gtest/gtest/LICENSE
@@ -0,0 +1,28 @@
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * 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.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+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.
diff --git a/lib/kokkos/tpls/gtest/gtest/README b/lib/kokkos/tpls/gtest/gtest/README
new file mode 100644
index 0000000000..82964ecc32
--- /dev/null
+++ b/lib/kokkos/tpls/gtest/gtest/README
@@ -0,0 +1,13 @@
+This is a fused source version of gtest 1.7.0. All that should be necessary to
+start using gtest in your package is to declare the dependency and include
+gtest/gtest.h.
+
+However, because some of the packages that are developed in Sierra do not use a
+fused source version of gtest we need to make it possible for them to build with
+this version as well as with their native build. To facilitate this we have
+created symlinks for the other gtest headers that they use to the fused source
+gtest.h. This will make it possible for them find the headers while still using
+the fuse source version. This should not have any ill effects since the header is
+protected and allows for only using the non-gtest.h headers in their files.
+
+
diff --git a/lib/kokkos/tpls/gtest/gtest/gtest-all.cc b/lib/kokkos/tpls/gtest/gtest/gtest-all.cc
new file mode 100644
index 0000000000..538c78db93
--- /dev/null
+++ b/lib/kokkos/tpls/gtest/gtest/gtest-all.cc
@@ -0,0 +1,9594 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// Google C++ Testing Framework (Google Test)
+//
+// Sometimes it's desirable to build Google Test by compiling a single file.
+// This file serves this purpose.
+
+// This line ensures that gtest.h can be compiled on its own, even
+// when it's fused.
+#include "gtest/gtest.h"
+
+// The following lines pull in the real gtest *.cc files.
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Utilities for testing Google Test itself and code that uses Google Test
+// (e.g. frameworks built on top of Google Test).
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+
+namespace testing {
+
+// This helper class can be used to mock out Google Test failure reporting
+// so that we can test Google Test or code that builds on Google Test.
+//
+// An object of this class appends a TestPartResult object to the
+// TestPartResultArray object given in the constructor whenever a Google Test
+// failure is reported. It can either intercept only failures that are
+// generated in the same thread that created this object or it can intercept
+// all generated failures. The scope of this mock object can be controlled with
+// the second argument to the two arguments constructor.
+class GTEST_API_ ScopedFakeTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  // The two possible mocking modes of this object.
+  enum InterceptMode {
+    INTERCEPT_ONLY_CURRENT_THREAD,  // Intercepts only thread local failures.
+    INTERCEPT_ALL_THREADS           // Intercepts all failures.
+  };
+
+  // The c'tor sets this object as the test part result reporter used
+  // by Google Test.  The 'result' parameter specifies where to report the
+  // results. This reporter will only catch failures generated in the current
+  // thread. DEPRECATED
+  explicit ScopedFakeTestPartResultReporter(TestPartResultArray* result);
+
+  // Same as above, but you can choose the interception scope of this object.
+  ScopedFakeTestPartResultReporter(InterceptMode intercept_mode,
+                                   TestPartResultArray* result);
+
+  // The d'tor restores the previous test part result reporter.
+  virtual ~ScopedFakeTestPartResultReporter();
+
+  // Appends the TestPartResult object to the TestPartResultArray
+  // received in the constructor.
+  //
+  // This method is from the TestPartResultReporterInterface
+  // interface.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+ private:
+  void Init();
+
+  const InterceptMode intercept_mode_;
+  TestPartResultReporterInterface* old_reporter_;
+  TestPartResultArray* const result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedFakeTestPartResultReporter);
+};
+
+namespace internal {
+
+// A helper class for implementing EXPECT_FATAL_FAILURE() and
+// EXPECT_NONFATAL_FAILURE().  Its destructor verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+class GTEST_API_ SingleFailureChecker {
+ public:
+  // The constructor remembers the arguments.
+  SingleFailureChecker(const TestPartResultArray* results,
+                       TestPartResult::Type type,
+                       const string& substr);
+  ~SingleFailureChecker();
+ private:
+  const TestPartResultArray* const results_;
+  const TestPartResult::Type type_;
+  const string substr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+// A set of macros for testing Google Test assertions or code that's expected
+// to generate Google Test fatal failures.  It verifies that the given
+// statement will cause exactly one fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_FATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_FATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - 'statement' cannot reference local non-static variables or
+//     non-static members of the current object.
+//   - 'statement' cannot return a value.
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  The AcceptsMacroThatExpandsToUnprotectedComma test in
+// gtest_unittest.cc will fail to compile if we do that.
+#define EXPECT_FATAL_FAILURE(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_FATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do { \
+    class GTestExpectFatalFailureHelper {\
+     public:\
+      static void Execute() { statement; }\
+    };\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kFatalFailure, (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ALL_THREADS, &gtest_failures);\
+      GTestExpectFatalFailureHelper::Execute();\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+// A macro for testing Google Test assertions or code that's expected to
+// generate Google Test non-fatal failures.  It asserts that the given
+// statement will cause exactly one non-fatal Google Test failure with 'substr'
+// being part of the failure message.
+//
+// There are two different versions of this macro. EXPECT_NONFATAL_FAILURE only
+// affects and considers failures generated in the current thread and
+// EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS does the same but for all threads.
+//
+// 'statement' is allowed to reference local variables and members of
+// the current object.
+//
+// The verification of the assertion is done correctly even when the statement
+// throws an exception or aborts the current function.
+//
+// Known restrictions:
+//   - You cannot stream a failure message to this macro.
+//
+// Note that even though the implementations of the following two
+// macros are much alike, we cannot refactor them to use a common
+// helper macro, due to some peculiarity in how the preprocessor
+// works.  If we do that, the code won't compile when the user gives
+// EXPECT_NONFATAL_FAILURE() a statement that contains a macro that
+// expands to code containing an unprotected comma.  The
+// AcceptsMacroThatExpandsToUnprotectedComma test in gtest_unittest.cc
+// catches that.
+//
+// For the same reason, we have to write
+//   if (::testing::internal::AlwaysTrue()) { statement; }
+// instead of
+//   GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+// to avoid an MSVC warning on unreachable code.
+#define EXPECT_NONFATAL_FAILURE(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter:: \
+          INTERCEPT_ONLY_CURRENT_THREAD, &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#define EXPECT_NONFATAL_FAILURE_ON_ALL_THREADS(statement, substr) \
+  do {\
+    ::testing::TestPartResultArray gtest_failures;\
+    ::testing::internal::SingleFailureChecker gtest_checker(\
+        &gtest_failures, ::testing::TestPartResult::kNonFatalFailure, \
+        (substr));\
+    {\
+      ::testing::ScopedFakeTestPartResultReporter gtest_reporter(\
+          ::testing::ScopedFakeTestPartResultReporter::INTERCEPT_ALL_THREADS, \
+          &gtest_failures);\
+      if (::testing::internal::AlwaysTrue()) { statement; }\
+    }\
+  } while (::testing::internal::AlwaysFalse())
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_SPI_H_
+
+#include <ctype.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <limits>
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <vector>
+
+#if GTEST_OS_LINUX
+
+// TODO(kenton@google.com): Use autoconf to detect availability of
+// gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+# include <fcntl.h>  // NOLINT
+# include <limits.h>  // NOLINT
+# include <sched.h>  // NOLINT
+// Declares vsnprintf().  This header is not available on Windows.
+# include <strings.h>  // NOLINT
+# include <sys/mman.h>  // NOLINT
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+# include <string>
+
+#elif GTEST_OS_SYMBIAN
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+#elif GTEST_OS_ZOS
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h>  // NOLINT
+
+// On z/OS we additionally need strings.h for strcasecmp.
+# include <strings.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS_MOBILE  // We are on Windows CE.
+
+# include <windows.h>  // NOLINT
+
+#elif GTEST_OS_WINDOWS  // We are on Windows proper.
+
+# include <io.h>  // NOLINT
+# include <sys/timeb.h>  // NOLINT
+# include <sys/types.h>  // NOLINT
+# include <sys/stat.h>  // NOLINT
+
+# if GTEST_OS_WINDOWS_MINGW
+// MinGW has gettimeofday() but not _ftime64().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+// TODO(kenton@google.com): There are other ways to get the time on
+//   Windows, like GetTickCount() or GetSystemTimeAsFileTime().  MinGW
+//   supports these.  consider using them instead.
+#  define GTEST_HAS_GETTIMEOFDAY_ 1
+#  include <sys/time.h>  // NOLINT
+# endif  // GTEST_OS_WINDOWS_MINGW
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <windows.h>  // NOLINT
+
+#else
+
+// Assume other platforms have gettimeofday().
+// TODO(kenton@google.com): Use autoconf to detect availability of
+//   gettimeofday().
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+
+// cpplint thinks that the header is already included, so we want to
+// silence it.
+# include <sys/time.h>  // NOLINT
+# include <unistd.h>  // NOLINT
+
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+
+// Utility functions and classes used by the Google C++ testing framework.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// This file contains purely Google Test's internal implementation.  Please
+// DO NOT #INCLUDE IT IN A USER PROGRAM.
+
+#ifndef GTEST_SRC_GTEST_INTERNAL_INL_H_
+#define GTEST_SRC_GTEST_INTERNAL_INL_H_
+
+// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
+// part of Google Test's implementation; otherwise it's undefined.
+#if !GTEST_IMPLEMENTATION_
+// A user is trying to include this from his code - just say no.
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
+#endif  // GTEST_IMPLEMENTATION_
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#endif  // !_WIN32_WCE
+#include <stddef.h>
+#include <stdlib.h>  // For strtoll/_strtoul64/malloc/free.
+#include <string.h>  // For memmove.
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h>  // NOLINT
+# include <netdb.h>  // NOLINT
+#endif
+
+#if GTEST_OS_WINDOWS
+# include <windows.h>  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+
+namespace testing {
+
+// Declares the flags.
+//
+// We don't want the users to modify this flag in the code, but want
+// Google Test's own unit tests to be able to access it. Therefore we
+// declare it here as opposed to in gtest.h.
+GTEST_DECLARE_bool_(death_test_use_fork);
+
+namespace internal {
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+GTEST_API_ extern const TypeId kTestTypeIdInGoogleTest;
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kAlsoRunDisabledTestsFlag[] = "also_run_disabled_tests";
+const char kBreakOnFailureFlag[] = "break_on_failure";
+const char kCatchExceptionsFlag[] = "catch_exceptions";
+const char kColorFlag[] = "color";
+const char kFilterFlag[] = "filter";
+const char kListTestsFlag[] = "list_tests";
+const char kOutputFlag[] = "output";
+const char kPrintTimeFlag[] = "print_time";
+const char kRandomSeedFlag[] = "random_seed";
+const char kRepeatFlag[] = "repeat";
+const char kShuffleFlag[] = "shuffle";
+const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
+const char kThrowOnFailureFlag[] = "throw_on_failure";
+
+// A valid random seed must be in [1, kMaxRandomSeed].
+const int kMaxRandomSeed = 99999;
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+GTEST_API_ extern bool g_help_flag;
+
+// Returns the current time in milliseconds.
+GTEST_API_ TimeInMillis GetTimeInMillis();
+
+// Returns true iff Google Test should use colors in the output.
+GTEST_API_ bool ShouldUseColor(bool stdout_is_tty);
+
+// Formats the given time in milliseconds as seconds.
+GTEST_API_ std::string FormatTimeInMillisAsSeconds(TimeInMillis ms);
+
+// Converts the given time in milliseconds to a date string in the ISO 8601
+// format, without the timezone information.  N.B.: due to the use the
+// non-reentrant localtime() function, this function is not thread safe.  Do
+// not use it in any code that can be called from multiple threads.
+GTEST_API_ std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms);
+
+// Parses a string for an Int32 flag, in the form of "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+GTEST_API_ bool ParseInt32Flag(
+    const char* str, const char* flag, Int32* value);
+
+// Returns a random seed in range [1, kMaxRandomSeed] based on the
+// given --gtest_random_seed flag value.
+inline int GetRandomSeedFromFlag(Int32 random_seed_flag) {
+  const unsigned int raw_seed = (random_seed_flag == 0) ?
+      static_cast<unsigned int>(GetTimeInMillis()) :
+      static_cast<unsigned int>(random_seed_flag);
+
+  // Normalizes the actual seed to range [1, kMaxRandomSeed] such that
+  // it's easy to type.
+  const int normalized_seed =
+      static_cast<int>((raw_seed - 1U) %
+                       static_cast<unsigned int>(kMaxRandomSeed)) + 1;
+  return normalized_seed;
+}
+
+// Returns the first valid random seed after 'seed'.  The behavior is
+// undefined if 'seed' is invalid.  The seed after kMaxRandomSeed is
+// considered to be 1.
+inline int GetNextRandomSeed(int seed) {
+  GTEST_CHECK_(1 <= seed && seed <= kMaxRandomSeed)
+      << "Invalid random seed " << seed << " - must be in [1, "
+      << kMaxRandomSeed << "].";
+  const int next_seed = seed + 1;
+  return (next_seed > kMaxRandomSeed) ? 1 : next_seed;
+}
+
+// This class saves the values of all Google Test flags in its c'tor, and
+// restores them in its d'tor.
+class GTestFlagSaver {
+ public:
+  // The c'tor.
+  GTestFlagSaver() {
+    also_run_disabled_tests_ = GTEST_FLAG(also_run_disabled_tests);
+    break_on_failure_ = GTEST_FLAG(break_on_failure);
+    catch_exceptions_ = GTEST_FLAG(catch_exceptions);
+    color_ = GTEST_FLAG(color);
+    death_test_style_ = GTEST_FLAG(death_test_style);
+    death_test_use_fork_ = GTEST_FLAG(death_test_use_fork);
+    filter_ = GTEST_FLAG(filter);
+    internal_run_death_test_ = GTEST_FLAG(internal_run_death_test);
+    list_tests_ = GTEST_FLAG(list_tests);
+    output_ = GTEST_FLAG(output);
+    print_time_ = GTEST_FLAG(print_time);
+    random_seed_ = GTEST_FLAG(random_seed);
+    repeat_ = GTEST_FLAG(repeat);
+    shuffle_ = GTEST_FLAG(shuffle);
+    stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+    stream_result_to_ = GTEST_FLAG(stream_result_to);
+    throw_on_failure_ = GTEST_FLAG(throw_on_failure);
+  }
+
+  // The d'tor is not virtual.  DO NOT INHERIT FROM THIS CLASS.
+  ~GTestFlagSaver() {
+    GTEST_FLAG(also_run_disabled_tests) = also_run_disabled_tests_;
+    GTEST_FLAG(break_on_failure) = break_on_failure_;
+    GTEST_FLAG(catch_exceptions) = catch_exceptions_;
+    GTEST_FLAG(color) = color_;
+    GTEST_FLAG(death_test_style) = death_test_style_;
+    GTEST_FLAG(death_test_use_fork) = death_test_use_fork_;
+    GTEST_FLAG(filter) = filter_;
+    GTEST_FLAG(internal_run_death_test) = internal_run_death_test_;
+    GTEST_FLAG(list_tests) = list_tests_;
+    GTEST_FLAG(output) = output_;
+    GTEST_FLAG(print_time) = print_time_;
+    GTEST_FLAG(random_seed) = random_seed_;
+    GTEST_FLAG(repeat) = repeat_;
+    GTEST_FLAG(shuffle) = shuffle_;
+    GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+    GTEST_FLAG(stream_result_to) = stream_result_to_;
+    GTEST_FLAG(throw_on_failure) = throw_on_failure_;
+  }
+
+ private:
+  // Fields for saving the original values of flags.
+  bool also_run_disabled_tests_;
+  bool break_on_failure_;
+  bool catch_exceptions_;
+  std::string color_;
+  std::string death_test_style_;
+  bool death_test_use_fork_;
+  std::string filter_;
+  std::string internal_run_death_test_;
+  bool list_tests_;
+  std::string output_;
+  bool print_time_;
+  internal::Int32 random_seed_;
+  internal::Int32 repeat_;
+  bool shuffle_;
+  internal::Int32 stack_trace_depth_;
+  std::string stream_result_to_;
+  bool throw_on_failure_;
+} GTEST_ATTRIBUTE_UNUSED_;
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+GTEST_API_ std::string CodePointToUtf8(UInt32 code_point);
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+GTEST_API_ std::string WideStringToUtf8(const wchar_t* str, int num_chars);
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded();
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (e.g., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+GTEST_API_ bool ShouldShard(const char* total_shards_str,
+                            const char* shard_index_str,
+                            bool in_subprocess_for_death_test);
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error and
+// and aborts.
+GTEST_API_ Int32 Int32FromEnvOrDie(const char* env_var, Int32 default_val);
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+GTEST_API_ bool ShouldRunTestOnShard(
+    int total_shards, int shard_index, int test_id);
+
+// STL container utilities.
+
+// Returns the number of elements in the given container that satisfy
+// the given predicate.
+template <class Container, typename Predicate>
+inline int CountIf(const Container& c, Predicate predicate) {
+  // Implemented as an explicit loop since std::count_if() in libCstd on
+  // Solaris has a non-standard signature.
+  int count = 0;
+  for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+    if (predicate(*it))
+      ++count;
+  }
+  return count;
+}
+
+// Applies a function/functor to each element in the container.
+template <class Container, typename Functor>
+void ForEach(const Container& c, Functor functor) {
+  std::for_each(c.begin(), c.end(), functor);
+}
+
+// Returns the i-th element of the vector, or default_value if i is not
+// in range [0, v.size()).
+template <typename E>
+inline E GetElementOr(const std::vector<E>& v, int i, E default_value) {
+  return (i < 0 || i >= static_cast<int>(v.size())) ? default_value : v[i];
+}
+
+// Performs an in-place shuffle of a range of the vector's elements.
+// 'begin' and 'end' are element indices as an STL-style range;
+// i.e. [begin, end) are shuffled, where 'end' == size() means to
+// shuffle to the end of the vector.
+template <typename E>
+void ShuffleRange(internal::Random* random, int begin, int end,
+                  std::vector<E>* v) {
+  const int size = static_cast<int>(v->size());
+  GTEST_CHECK_(0 <= begin && begin <= size)
+      << "Invalid shuffle range start " << begin << ": must be in range [0, "
+      << size << "].";
+  GTEST_CHECK_(begin <= end && end <= size)
+      << "Invalid shuffle range finish " << end << ": must be in range ["
+      << begin << ", " << size << "].";
+
+  // Fisher-Yates shuffle, from
+  // http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
+  for (int range_width = end - begin; range_width >= 2; range_width--) {
+    const int last_in_range = begin + range_width - 1;
+    const int selected = begin + random->Generate(range_width);
+    std::swap((*v)[selected], (*v)[last_in_range]);
+  }
+}
+
+// Performs an in-place shuffle of the vector's elements.
+template <typename E>
+inline void Shuffle(internal::Random* random, std::vector<E>* v) {
+  ShuffleRange(random, 0, static_cast<int>(v->size()), v);
+}
+
+// A function for deleting an object.  Handy for being used as a
+// functor.
+template <typename T>
+static void Delete(T* x) {
+  delete x;
+}
+
+// A predicate that checks the key of a TestProperty against a known key.
+//
+// TestPropertyKeyIs is copyable.
+class TestPropertyKeyIs {
+ public:
+  // Constructor.
+  //
+  // TestPropertyKeyIs has NO default constructor.
+  explicit TestPropertyKeyIs(const std::string& key) : key_(key) {}
+
+  // Returns true iff the test name of test property matches on key_.
+  bool operator()(const TestProperty& test_property) const {
+    return test_property.key() == key_;
+  }
+
+ private:
+  std::string key_;
+};
+
+// Class UnitTestOptions.
+//
+// This class contains functions for processing options the user
+// specifies when running the tests.  It has only static members.
+//
+// In most cases, the user can specify an option using either an
+// environment variable or a command line flag.  E.g. you can set the
+// test filter using either GTEST_FILTER or --gtest_filter.  If both
+// the variable and the flag are present, the latter overrides the
+// former.
+class GTEST_API_ UnitTestOptions {
+ public:
+  // Functions for processing the gtest_output flag.
+
+  // Returns the output format, or "" for normal printed output.
+  static std::string GetOutputFormat();
+
+  // Returns the absolute path of the requested output file, or the
+  // default (test_detail.xml in the original working directory) if
+  // none was explicitly specified.
+  static std::string GetAbsolutePathToOutputFile();
+
+  // Functions for processing the gtest_filter flag.
+
+  // Returns true iff the wildcard pattern matches the string.  The
+  // first ':' or '\0' character in pattern marks the end of it.
+  //
+  // This recursive algorithm isn't very efficient, but is clear and
+  // works well enough for matching test names, which are short.
+  static bool PatternMatchesString(const char *pattern, const char *str);
+
+  // Returns true iff the user-specified filter matches the test case
+  // name and the test name.
+  static bool FilterMatchesTest(const std::string &test_case_name,
+                                const std::string &test_name);
+
+#if GTEST_OS_WINDOWS
+  // Function for supporting the gtest_catch_exception flag.
+
+  // Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+  // given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+  // This function is useful as an __except condition.
+  static int GTestShouldProcessSEH(DWORD exception_code);
+#endif  // GTEST_OS_WINDOWS
+
+  // Returns true if "name" matches the ':' separated list of glob-style
+  // filters in "filter".
+  static bool MatchesFilter(const std::string& name, const char* filter);
+};
+
+// Returns the current application's name, removing directory path if that
+// is present.  Used by UnitTestOptions::GetOutputFile.
+GTEST_API_ FilePath GetCurrentExecutableName();
+
+// The role interface for getting the OS stack trace as a string.
+class OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetterInterface() {}
+  virtual ~OsStackTraceGetterInterface() {}
+
+  // Returns the current OS stack trace as an std::string.  Parameters:
+  //
+  //   max_depth  - the maximum number of stack frames to be included
+  //                in the trace.
+  //   skip_count - the number of top frames to be skipped; doesn't count
+  //                against max_depth.
+  virtual string CurrentStackTrace(int max_depth, int skip_count) = 0;
+
+  // UponLeavingGTest() should be called immediately before Google Test calls
+  // user code. It saves some information about the current stack that
+  // CurrentStackTrace() will use to find and hide Google Test stack frames.
+  virtual void UponLeavingGTest() = 0;
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
+};
+
+// A working implementation of the OsStackTraceGetterInterface interface.
+class OsStackTraceGetter : public OsStackTraceGetterInterface {
+ public:
+  OsStackTraceGetter() : caller_frame_(NULL) {}
+
+  virtual string CurrentStackTrace(int max_depth, int skip_count)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // This string is inserted in place of stack frames that are part of
+  // Google Test's implementation.
+  static const char* const kElidedFramesMarker;
+
+ private:
+  Mutex mutex_;  // protects all internal state
+
+  // We save the stack frame below the frame that calls user code.
+  // We do this because the address of the frame immediately below
+  // the user code changes between the call to UponLeavingGTest()
+  // and any calls to CurrentStackTrace() from within the user code.
+  void* caller_frame_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
+};
+
+// Information about a Google Test trace point.
+struct TraceInfo {
+  const char* file;
+  int line;
+  std::string message;
+};
+
+// This is the default global test part result reporter used in UnitTestImpl.
+// This class should only be used by UnitTestImpl.
+class DefaultGlobalTestPartResultReporter
+  : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultGlobalTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. Reports the test part
+  // result in the current test.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultGlobalTestPartResultReporter);
+};
+
+// This is the default per thread test part result reporter used in
+// UnitTestImpl. This class should only be used by UnitTestImpl.
+class DefaultPerThreadTestPartResultReporter
+    : public TestPartResultReporterInterface {
+ public:
+  explicit DefaultPerThreadTestPartResultReporter(UnitTestImpl* unit_test);
+  // Implements the TestPartResultReporterInterface. The implementation just
+  // delegates to the current global test part result reporter of *unit_test_.
+  virtual void ReportTestPartResult(const TestPartResult& result);
+
+ private:
+  UnitTestImpl* const unit_test_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DefaultPerThreadTestPartResultReporter);
+};
+
+// The private implementation of the UnitTest class.  We don't protect
+// the methods under a mutex, as this class is not accessible by a
+// user and the UnitTest class that delegates work to this class does
+// proper locking.
+class GTEST_API_ UnitTestImpl {
+ public:
+  explicit UnitTestImpl(UnitTest* parent);
+  virtual ~UnitTestImpl();
+
+  // There are two different ways to register your own TestPartResultReporter.
+  // You can register your own repoter to listen either only for test results
+  // from the current thread or for results from all threads.
+  // By default, each per-thread test result repoter just passes a new
+  // TestPartResult to the global test result reporter, which registers the
+  // test part result for the currently running test.
+
+  // Returns the global test part result reporter.
+  TestPartResultReporterInterface* GetGlobalTestPartResultReporter();
+
+  // Sets the global test part result reporter.
+  void SetGlobalTestPartResultReporter(
+      TestPartResultReporterInterface* reporter);
+
+  // Returns the test part result reporter for the current thread.
+  TestPartResultReporterInterface* GetTestPartResultReporterForCurrentThread();
+
+  // Sets the test part result reporter for the current thread.
+  void SetTestPartResultReporterForCurrentThread(
+      TestPartResultReporterInterface* reporter);
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const { return start_timestamp_; }
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const {
+    return failed_test_case_count() > 0 || ad_hoc_test_result()->Failed();
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[i];
+  }
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i) {
+    const int index = GetElementOr(test_case_indices_, i, -1);
+    return index < 0 ? NULL : test_cases_[index];
+  }
+
+  // Provides access to the event listener list.
+  TestEventListeners* listeners() { return &listeners_; }
+
+  // Returns the TestResult for the test that's currently running, or
+  // the TestResult for the ad hoc test if no test is running.
+  TestResult* current_test_result();
+
+  // Returns the TestResult for the ad hoc test.
+  const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
+
+  // Sets the OS stack trace getter.
+  //
+  // Does nothing if the input and the current OS stack trace getter
+  // are the same; otherwise, deletes the old getter and makes the
+  // input the current getter.
+  void set_os_stack_trace_getter(OsStackTraceGetterInterface* getter);
+
+  // Returns the current OS stack trace getter if it is not NULL;
+  // otherwise, creates an OsStackTraceGetter, makes it the current
+  // getter, and returns it.
+  OsStackTraceGetterInterface* os_stack_trace_getter();
+
+  // Returns the current OS stack trace as an std::string.
+  //
+  // The maximum number of stack frames to be included is specified by
+  // the gtest_stack_trace_depth flag.  The skip_count parameter
+  // specifies the number of top frames to be skipped, which doesn't
+  // count against the number of frames to be included.
+  //
+  // For example, if Foo() calls Bar(), which in turn calls
+  // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+  // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+  std::string CurrentOsStackTraceExceptTop(int skip_count) GTEST_NO_INLINE_;
+
+  // Finds and returns a TestCase with the given name.  If one doesn't
+  // exist, creates one and returns it.
+  //
+  // Arguments:
+  //
+  //   test_case_name: name of the test case
+  //   type_param:     the name of the test's type parameter, or NULL if
+  //                   this is not a typed or a type-parameterized test.
+  //   set_up_tc:      pointer to the function that sets up the test case
+  //   tear_down_tc:   pointer to the function that tears down the test case
+  TestCase* GetTestCase(const char* test_case_name,
+                        const char* type_param,
+                        Test::SetUpTestCaseFunc set_up_tc,
+                        Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Adds a TestInfo to the unit test.
+  //
+  // Arguments:
+  //
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  //   test_info:    the TestInfo object
+  void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc,
+                   TestInfo* test_info) {
+    // In order to support thread-safe death tests, we need to
+    // remember the original working directory when the test program
+    // was first invoked.  We cannot do this in RUN_ALL_TESTS(), as
+    // the user may have changed the current directory before calling
+    // RUN_ALL_TESTS().  Therefore we capture the current directory in
+    // AddTestInfo(), which is called to register a TEST or TEST_F
+    // before main() is reached.
+    if (original_working_dir_.IsEmpty()) {
+      original_working_dir_.Set(FilePath::GetCurrentDir());
+      GTEST_CHECK_(!original_working_dir_.IsEmpty())
+          << "Failed to get the current working directory.";
+    }
+
+    GetTestCase(test_info->test_case_name(),
+                test_info->type_param(),
+                set_up_tc,
+                tear_down_tc)->AddTestInfo(test_info);
+  }
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry() {
+    return parameterized_test_registry_;
+  }
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Sets the TestCase object for the test that's currently running.
+  void set_current_test_case(TestCase* a_current_test_case) {
+    current_test_case_ = a_current_test_case;
+  }
+
+  // Sets the TestInfo object for the test that's currently running.  If
+  // current_test_info is NULL, the assertion results will be stored in
+  // ad_hoc_test_result_.
+  void set_current_test_info(TestInfo* a_current_test_info) {
+    current_test_info_ = a_current_test_info;
+  }
+
+  // Registers all parameterized tests defined using TEST_P and
+  // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+  // combination. This method can be called more then once; it has guards
+  // protecting from registering the tests more then once.  If
+  // value-parameterized tests are disabled, RegisterParameterizedTests is
+  // present but does nothing.
+  void RegisterParameterizedTests();
+
+  // Runs all tests in this UnitTest object, prints the result, and
+  // returns true if all tests are successful.  If any exception is
+  // thrown during a test, this test is considered to be failed, but
+  // the rest of the tests will still be run.
+  bool RunAllTests();
+
+  // Clears the results of all tests, except the ad hoc tests.
+  void ClearNonAdHocTestResult() {
+    ForEach(test_cases_, TestCase::ClearTestCaseResult);
+  }
+
+  // Clears the results of ad-hoc test assertions.
+  void ClearAdHocTestResult() {
+    ad_hoc_test_result_.Clear();
+  }
+
+  // Adds a TestProperty to the current TestResult object when invoked in a
+  // context of a test or a test case, or to the global property set. If the
+  // result already contains a property with the same key, the value will be
+  // updated.
+  void RecordProperty(const TestProperty& test_property);
+
+  enum ReactionToSharding {
+    HONOR_SHARDING_PROTOCOL,
+    IGNORE_SHARDING_PROTOCOL
+  };
+
+  // Matches the full name of each test against the user-specified
+  // filter to decide whether the test should run, then records the
+  // result in each TestCase and TestInfo object.
+  // If shard_tests == HONOR_SHARDING_PROTOCOL, further filters tests
+  // based on sharding variables in the environment.
+  // Returns the number of tests that should run.
+  int FilterTests(ReactionToSharding shard_tests);
+
+  // Prints the names of the tests matching the user-specified filter flag.
+  void ListTestsMatchingFilter();
+
+  const TestCase* current_test_case() const { return current_test_case_; }
+  TestInfo* current_test_info() { return current_test_info_; }
+  const TestInfo* current_test_info() const { return current_test_info_; }
+
+  // Returns the vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*>& environments() { return environments_; }
+
+  // Getters for the per-thread Google Test trace stack.
+  std::vector<TraceInfo>& gtest_trace_stack() {
+    return *(gtest_trace_stack_.pointer());
+  }
+  const std::vector<TraceInfo>& gtest_trace_stack() const {
+    return gtest_trace_stack_.get();
+  }
+
+#if GTEST_HAS_DEATH_TEST
+  void InitDeathTestSubprocessControlInfo() {
+    internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+  }
+  // Returns a pointer to the parsed --gtest_internal_run_death_test
+  // flag, or NULL if that flag was not specified.
+  // This information is useful only in a death test child process.
+  // Must not be called before a call to InitGoogleTest.
+  const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
+    return internal_run_death_test_flag_.get();
+  }
+
+  // Returns a pointer to the current death test factory.
+  internal::DeathTestFactory* death_test_factory() {
+    return death_test_factory_.get();
+  }
+
+  void SuppressTestEventsIfInSubprocess();
+
+  friend class ReplaceDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // Initializes the event listener performing XML output as specified by
+  // UnitTestOptions. Must not be called before InitGoogleTest.
+  void ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+  // Initializes the event listener for streaming test results to a socket.
+  // Must not be called before InitGoogleTest.
+  void ConfigureStreamingOutput();
+#endif
+
+  // Performs initialization dependent upon flag values obtained in
+  // ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+  // ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+  // this function is also called from RunAllTests.  Since this function can be
+  // called more than once, it has to be idempotent.
+  void PostFlagParsingInit();
+
+  // Gets the random seed used at the start of the current test iteration.
+  int random_seed() const { return random_seed_; }
+
+  // Gets the random number generator.
+  internal::Random* random() { return &random_; }
+
+  // Shuffles all test cases, and the tests within each test case,
+  // making sure that death tests are still run first.
+  void ShuffleTests();
+
+  // Restores the test cases and tests to their order before the first shuffle.
+  void UnshuffleTests();
+
+  // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+  // UnitTest::Run() starts.
+  bool catch_exceptions() const { return catch_exceptions_; }
+
+ private:
+  friend class ::testing::UnitTest;
+
+  // Used by UnitTest::Run() to capture the state of
+  // GTEST_FLAG(catch_exceptions) at the moment it starts.
+  void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
+  // The UnitTest object that owns this implementation object.
+  UnitTest* const parent_;
+
+  // The working directory when the first TEST() or TEST_F() was
+  // executed.
+  internal::FilePath original_working_dir_;
+
+  // The default test part result reporters.
+  DefaultGlobalTestPartResultReporter default_global_test_part_result_reporter_;
+  DefaultPerThreadTestPartResultReporter
+      default_per_thread_test_part_result_reporter_;
+
+  // Points to (but doesn't own) the global test part result reporter.
+  TestPartResultReporterInterface* global_test_part_result_repoter_;
+
+  // Protects read and write access to global_test_part_result_reporter_.
+  internal::Mutex global_test_part_result_reporter_mutex_;
+
+  // Points to (but doesn't own) the per-thread test part result reporter.
+  internal::ThreadLocal<TestPartResultReporterInterface*>
+      per_thread_test_part_result_reporter_;
+
+  // The vector of environments that need to be set-up/torn-down
+  // before/after the tests are run.
+  std::vector<Environment*> environments_;
+
+  // The vector of TestCases in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestCase*> test_cases_;
+
+  // Provides a level of indirection for the test case list to allow
+  // easy shuffling and restoring the test case order.  The i-th
+  // element of this vector is the index of the i-th test case in the
+  // shuffled order.
+  std::vector<int> test_case_indices_;
+
+#if GTEST_HAS_PARAM_TEST
+  // ParameterizedTestRegistry object used to register value-parameterized
+  // tests.
+  internal::ParameterizedTestCaseRegistry parameterized_test_registry_;
+
+  // Indicates whether RegisterParameterizedTests() has been called already.
+  bool parameterized_tests_registered_;
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Index of the last death test case registered.  Initially -1.
+  int last_death_test_case_;
+
+  // This points to the TestCase for the currently running test.  It
+  // changes as Google Test goes through one test case after another.
+  // When no test is running, this is set to NULL and Google Test
+  // stores assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestCase* current_test_case_;
+
+  // This points to the TestInfo for the currently running test.  It
+  // changes as Google Test goes through one test after another.  When
+  // no test is running, this is set to NULL and Google Test stores
+  // assertion results in ad_hoc_test_result_.  Initially NULL.
+  TestInfo* current_test_info_;
+
+  // Normally, a user only writes assertions inside a TEST or TEST_F,
+  // or inside a function called by a TEST or TEST_F.  Since Google
+  // Test keeps track of which test is current running, it can
+  // associate such an assertion with the test it belongs to.
+  //
+  // If an assertion is encountered when no TEST or TEST_F is running,
+  // Google Test attributes the assertion result to an imaginary "ad hoc"
+  // test, and records the result in ad_hoc_test_result_.
+  TestResult ad_hoc_test_result_;
+
+  // The list of event listeners that can be used to track events inside
+  // Google Test.
+  TestEventListeners listeners_;
+
+  // The OS stack trace getter.  Will be deleted when the UnitTest
+  // object is destructed.  By default, an OsStackTraceGetter is used,
+  // but the user can set this field to use a custom getter if that is
+  // desired.
+  OsStackTraceGetterInterface* os_stack_trace_getter_;
+
+  // True iff PostFlagParsingInit() has been called.
+  bool post_flag_parse_init_performed_;
+
+  // The random number seed used at the beginning of the test run.
+  int random_seed_;
+
+  // Our random number generator.
+  internal::Random random_;
+
+  // The time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp_;
+
+  // How long the test took to run, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+#if GTEST_HAS_DEATH_TEST
+  // The decomposed components of the gtest_internal_run_death_test flag,
+  // parsed when RUN_ALL_TESTS is called.
+  internal::scoped_ptr<InternalRunDeathTestFlag> internal_run_death_test_flag_;
+  internal::scoped_ptr<internal::DeathTestFactory> death_test_factory_;
+#endif  // GTEST_HAS_DEATH_TEST
+
+  // A per-thread stack of traces created by the SCOPED_TRACE() macro.
+  internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+
+  // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+  // starts.
+  bool catch_exceptions_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
+};  // class UnitTestImpl
+
+// Convenience function for accessing the global UnitTest
+// implementation object.
+inline UnitTestImpl* GetUnitTestImpl() {
+  return UnitTest::GetInstance()->impl();
+}
+
+#if GTEST_USES_SIMPLE_RE
+
+// Internal helper functions for implementing the simple regular
+// expression matcher.
+GTEST_API_ bool IsInSet(char ch, const char* str);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
+GTEST_API_ bool IsRepeat(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
+GTEST_API_ bool IsValidEscape(char ch);
+GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
+GTEST_API_ bool ValidateRegex(const char* regex);
+GTEST_API_ bool MatchRegexAtHead(const char* regex, const char* str);
+GTEST_API_ bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char ch, char repeat, const char* regex, const char* str);
+GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+
+#endif  // GTEST_USES_SIMPLE_RE
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
+GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
+
+#if GTEST_HAS_DEATH_TEST
+
+// Returns the message describing the last system error, regardless of the
+// platform.
+GTEST_API_ std::string GetLastErrnoDescription();
+
+# if GTEST_OS_WINDOWS
+// Provides leak-safe Windows kernel handle ownership.
+class AutoHandle {
+ public:
+  AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
+  explicit AutoHandle(HANDLE handle) : handle_(handle) {}
+
+  ~AutoHandle() { Reset(); }
+
+  HANDLE Get() const { return handle_; }
+  void Reset() { Reset(INVALID_HANDLE_VALUE); }
+  void Reset(HANDLE handle) {
+    if (handle != handle_) {
+      if (handle_ != INVALID_HANDLE_VALUE)
+        ::CloseHandle(handle_);
+      handle_ = handle;
+    }
+  }
+
+ private:
+  HANDLE handle_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
+};
+# endif  // GTEST_OS_WINDOWS
+
+// Attempts to parse a string into a positive integer pointed to by the
+// number parameter.  Returns true if that is possible.
+// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use
+// it here.
+template <typename Integer>
+bool ParseNaturalNumber(const ::std::string& str, Integer* number) {
+  // Fail fast if the given string does not begin with a digit;
+  // this bypasses strtoXXX's "optional leading whitespace and plus
+  // or minus sign" semantics, which are undesirable here.
+  if (str.empty() || !IsDigit(str[0])) {
+    return false;
+  }
+  errno = 0;
+
+  char* end;
+  // BiggestConvertible is the largest integer type that system-provided
+  // string-to-number conversion routines can return.
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  // MSVC and C++ Builder define __int64 instead of the standard long long.
+  typedef unsigned __int64 BiggestConvertible;
+  const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
+
+# else
+
+  typedef unsigned long long BiggestConvertible;  // NOLINT
+  const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
+
+# endif  // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+  const bool parse_success = *end == '\0' && errno == 0;
+
+  // TODO(vladl@google.com): Convert this to compile time assertion when it is
+  // available.
+  GTEST_CHECK_(sizeof(Integer) <= sizeof(parsed));
+
+  const Integer result = static_cast<Integer>(parsed);
+  if (parse_success && static_cast<BiggestConvertible>(result) == parsed) {
+    *number = result;
+    return true;
+  }
+  return false;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// TestResult contains some private methods that should be hidden from
+// Google Test user but are required for testing. This class allow our tests
+// to access them.
+//
+// This class is supplied only for the purpose of testing Google Test's own
+// constructs. Do not use it in user tests, either directly or indirectly.
+class TestResultAccessor {
+ public:
+  static void RecordProperty(TestResult* test_result,
+                             const std::string& xml_element,
+                             const TestProperty& property) {
+    test_result->RecordProperty(xml_element, property);
+  }
+
+  static void ClearTestPartResults(TestResult* test_result) {
+    test_result->ClearTestPartResults();
+  }
+
+  static const std::vector<testing::TestPartResult>& test_part_results(
+      const TestResult& test_result) {
+    return test_result.test_part_results();
+  }
+};
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+  // Abstract base class for writing strings to a socket.
+  class AbstractSocketWriter {
+   public:
+    virtual ~AbstractSocketWriter() {}
+
+    // Sends a string to the socket.
+    virtual void Send(const string& message) = 0;
+
+    // Closes the socket.
+    virtual void CloseConnection() {}
+
+    // Sends a string and a newline to the socket.
+    void SendLn(const string& message) {
+      Send(message + "\n");
+    }
+  };
+
+  // Concrete class for actually writing strings to a socket.
+  class SocketWriter : public AbstractSocketWriter {
+   public:
+    SocketWriter(const string& host, const string& port)
+        : sockfd_(-1), host_name_(host), port_num_(port) {
+      MakeConnection();
+    }
+
+    virtual ~SocketWriter() {
+      if (sockfd_ != -1)
+        CloseConnection();
+    }
+
+    // Sends a string to the socket.
+    virtual void Send(const string& message) {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "Send() can be called only when there is a connection.";
+
+      const int len = static_cast<int>(message.length());
+      if (write(sockfd_, message.c_str(), len) != len) {
+        GTEST_LOG_(WARNING)
+            << "stream_result_to: failed to stream to "
+            << host_name_ << ":" << port_num_;
+      }
+    }
+
+   private:
+    // Creates a client socket and connects to the server.
+    void MakeConnection();
+
+    // Closes the socket.
+    void CloseConnection() {
+      GTEST_CHECK_(sockfd_ != -1)
+          << "CloseConnection() can be called only when there is a connection.";
+
+      close(sockfd_);
+      sockfd_ = -1;
+    }
+
+    int sockfd_;  // socket file descriptor
+    const string host_name_;
+    const string port_num_;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SocketWriter);
+  };  // class SocketWriter
+
+  // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+  static string UrlEncode(const char* str);
+
+  StreamingListener(const string& host, const string& port)
+      : socket_writer_(new SocketWriter(host, port)) { Start(); }
+
+  explicit StreamingListener(AbstractSocketWriter* socket_writer)
+      : socket_writer_(socket_writer) { Start(); }
+
+  void OnTestProgramStart(const UnitTest& /* unit_test */) {
+    SendLn("event=TestProgramStart");
+  }
+
+  void OnTestProgramEnd(const UnitTest& unit_test) {
+    // Note that Google Test current only report elapsed time for each
+    // test iteration, not for the entire test program.
+    SendLn("event=TestProgramEnd&passed=" + FormatBool(unit_test.Passed()));
+
+    // Notify the streaming server to stop.
+    socket_writer_->CloseConnection();
+  }
+
+  void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+    SendLn("event=TestIterationStart&iteration=" +
+           StreamableToString(iteration));
+  }
+
+  void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+    SendLn("event=TestIterationEnd&passed=" +
+           FormatBool(unit_test.Passed()) + "&elapsed_time=" +
+           StreamableToString(unit_test.elapsed_time()) + "ms");
+  }
+
+  void OnTestCaseStart(const TestCase& test_case) {
+    SendLn(std::string("event=TestCaseStart&name=") + test_case.name());
+  }
+
+  void OnTestCaseEnd(const TestCase& test_case) {
+    SendLn("event=TestCaseEnd&passed=" + FormatBool(test_case.Passed())
+           + "&elapsed_time=" + StreamableToString(test_case.elapsed_time())
+           + "ms");
+  }
+
+  void OnTestStart(const TestInfo& test_info) {
+    SendLn(std::string("event=TestStart&name=") + test_info.name());
+  }
+
+  void OnTestEnd(const TestInfo& test_info) {
+    SendLn("event=TestEnd&passed=" +
+           FormatBool((test_info.result())->Passed()) +
+           "&elapsed_time=" +
+           StreamableToString((test_info.result())->elapsed_time()) + "ms");
+  }
+
+  void OnTestPartResult(const TestPartResult& test_part_result) {
+    const char* file_name = test_part_result.file_name();
+    if (file_name == NULL)
+      file_name = "";
+    SendLn("event=TestPartResult&file=" + UrlEncode(file_name) +
+           "&line=" + StreamableToString(test_part_result.line_number()) +
+           "&message=" + UrlEncode(test_part_result.message()));
+  }
+
+ private:
+  // Sends the given message and a newline to the socket.
+  void SendLn(const string& message) { socket_writer_->SendLn(message); }
+
+  // Called at the start of streaming to notify the receiver what
+  // protocol we are using.
+  void Start() { SendLn("gtest_streaming_protocol_version=1.0"); }
+
+  string FormatBool(bool value) { return value ? "1" : "0"; }
+
+  const scoped_ptr<AbstractSocketWriter> socket_writer_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+};  // class StreamingListener
+
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_SRC_GTEST_INTERNAL_INL_H_
+#undef GTEST_IMPLEMENTATION_
+
+#if GTEST_OS_WINDOWS
+# define vsnprintf _vsnprintf
+#endif  // GTEST_OS_WINDOWS
+
+namespace testing {
+
+using internal::CountIf;
+using internal::ForEach;
+using internal::GetElementOr;
+using internal::Shuffle;
+
+// Constants.
+
+// A test whose test case name or test name matches this filter is
+// disabled and not run.
+static const char kDisableTestFilter[] = "DISABLED_*:*/DISABLED_*";
+
+// A test case whose name matches this filter is considered a death
+// test case and will be run before test cases whose name doesn't
+// match this filter.
+static const char kDeathTestCaseFilter[] = "*DeathTest:*DeathTest/*";
+
+// A test filter that matches everything.
+static const char kUniversalFilter[] = "*";
+
+// The default output file for XML output.
+static const char kDefaultOutputFile[] = "test_detail.xml";
+
+// The environment variable name for the test shard index.
+static const char kTestShardIndex[] = "GTEST_SHARD_INDEX";
+// The environment variable name for the total number of test shards.
+static const char kTestTotalShards[] = "GTEST_TOTAL_SHARDS";
+// The environment variable name for the test shard status file.
+static const char kTestShardStatusFile[] = "GTEST_SHARD_STATUS_FILE";
+
+namespace internal {
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+const char kStackTraceMarker[] = "\nStack trace:\n";
+
+// g_help_flag is true iff the --help flag or an equivalent form is
+// specified on the command line.
+bool g_help_flag = false;
+
+}  // namespace internal
+
+static const char* GetDefaultFilter() {
+  return kUniversalFilter;
+}
+
+GTEST_DEFINE_bool_(
+    also_run_disabled_tests,
+    internal::BoolFromGTestEnv("also_run_disabled_tests", false),
+    "Run disabled tests too, in addition to the tests normally being run.");
+
+GTEST_DEFINE_bool_(
+    break_on_failure,
+    internal::BoolFromGTestEnv("break_on_failure", false),
+    "True iff a failed assertion should be a debugger break-point.");
+
+GTEST_DEFINE_bool_(
+    catch_exceptions,
+    internal::BoolFromGTestEnv("catch_exceptions", true),
+    "True iff " GTEST_NAME_
+    " should catch exceptions and treat them as test failures.");
+
+GTEST_DEFINE_string_(
+    color,
+    internal::StringFromGTestEnv("color", "auto"),
+    "Whether to use colors in the output.  Valid values: yes, no, "
+    "and auto.  'auto' means to use colors if the output is "
+    "being sent to a terminal and the TERM environment variable "
+    "is set to a terminal type that supports colors.");
+
+GTEST_DEFINE_string_(
+    filter,
+    internal::StringFromGTestEnv("filter", GetDefaultFilter()),
+    "A colon-separated list of glob (not regex) patterns "
+    "for filtering the tests to run, optionally followed by a "
+    "'-' and a : separated list of negative patterns (tests to "
+    "exclude).  A test is run if it matches one of the positive "
+    "patterns and does not match any of the negative patterns.");
+
+GTEST_DEFINE_bool_(list_tests, false,
+                   "List all tests without running them.");
+
+GTEST_DEFINE_string_(
+    output,
+    internal::StringFromGTestEnv("output", ""),
+    "A format (currently must be \"xml\"), optionally followed "
+    "by a colon and an output file name or directory. A directory "
+    "is indicated by a trailing pathname separator. "
+    "Examples: \"xml:filename.xml\", \"xml::directoryname/\". "
+    "If a directory is specified, output files will be created "
+    "within that directory, with file-names based on the test "
+    "executable's name and, if necessary, made unique by adding "
+    "digits.");
+
+GTEST_DEFINE_bool_(
+    print_time,
+    internal::BoolFromGTestEnv("print_time", true),
+    "True iff " GTEST_NAME_
+    " should display elapsed time in text output.");
+
+GTEST_DEFINE_int32_(
+    random_seed,
+    internal::Int32FromGTestEnv("random_seed", 0),
+    "Random number seed to use when shuffling test orders.  Must be in range "
+    "[1, 99999], or 0 to use a seed based on the current time.");
+
+GTEST_DEFINE_int32_(
+    repeat,
+    internal::Int32FromGTestEnv("repeat", 1),
+    "How many times to repeat each test.  Specify a negative number "
+    "for repeating forever.  Useful for shaking out flaky tests.");
+
+GTEST_DEFINE_bool_(
+    show_internal_stack_frames, false,
+    "True iff " GTEST_NAME_ " should include internal stack frames when "
+    "printing test failure stack traces.");
+
+GTEST_DEFINE_bool_(
+    shuffle,
+    internal::BoolFromGTestEnv("shuffle", false),
+    "True iff " GTEST_NAME_
+    " should randomize tests' order on every run.");
+
+GTEST_DEFINE_int32_(
+    stack_trace_depth,
+    internal::Int32FromGTestEnv("stack_trace_depth", kMaxStackTraceDepth),
+    "The maximum number of stack frames to print when an "
+    "assertion fails.  The valid range is 0 through 100, inclusive.");
+
+GTEST_DEFINE_string_(
+    stream_result_to,
+    internal::StringFromGTestEnv("stream_result_to", ""),
+    "This flag specifies the host name and the port number on which to stream "
+    "test results. Example: \"localhost:555\". The flag is effective only on "
+    "Linux.");
+
+GTEST_DEFINE_bool_(
+    throw_on_failure,
+    internal::BoolFromGTestEnv("throw_on_failure", false),
+    "When this flag is specified, a failed assertion will throw an exception "
+    "if exceptions are enabled or exit the program with a non-zero code "
+    "otherwise.");
+
+namespace internal {
+
+// Generates a random number from [0, range), using a Linear
+// Congruential Generator (LCG).  Crashes if 'range' is 0 or greater
+// than kMaxRange.
+UInt32 Random::Generate(UInt32 range) {
+  // These constants are the same as are used in glibc's rand(3).
+  state_ = (1103515245U*state_ + 12345U) % kMaxRange;
+
+  GTEST_CHECK_(range > 0)
+      << "Cannot generate a number in the range [0, 0).";
+  GTEST_CHECK_(range <= kMaxRange)
+      << "Generation of a number in [0, " << range << ") was requested, "
+      << "but this can only generate numbers in [0, " << kMaxRange << ").";
+
+  // Converting via modulus introduces a bit of downward bias, but
+  // it's simple, and a linear congruential generator isn't too good
+  // to begin with.
+  return state_ % range;
+}
+
+// GTestIsInitialized() returns true iff the user has initialized
+// Google Test.  Useful for catching the user mistake of not initializing
+// Google Test before calling RUN_ALL_TESTS().
+//
+// A user must call testing::InitGoogleTest() to initialize Google
+// Test.  g_init_gtest_count is set to the number of times
+// InitGoogleTest() has been called.  We don't protect this variable
+// under a mutex as it is only accessed in the main thread.
+GTEST_API_ int g_init_gtest_count = 0;
+static bool GTestIsInitialized() { return g_init_gtest_count != 0; }
+
+// Iterates over a vector of TestCases, keeping a running sum of the
+// results of calling a given int-returning method on each.
+// Returns the sum.
+static int SumOverTestCaseList(const std::vector<TestCase*>& case_list,
+                               int (TestCase::*method)() const) {
+  int sum = 0;
+  for (size_t i = 0; i < case_list.size(); i++) {
+    sum += (case_list[i]->*method)();
+  }
+  return sum;
+}
+
+// Returns true iff the test case passed.
+static bool TestCasePassed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Passed();
+}
+
+// Returns true iff the test case failed.
+static bool TestCaseFailed(const TestCase* test_case) {
+  return test_case->should_run() && test_case->Failed();
+}
+
+// Returns true iff test_case contains at least one test that should
+// run.
+static bool ShouldRunTestCase(const TestCase* test_case) {
+  return test_case->should_run();
+}
+
+// AssertHelper constructor.
+AssertHelper::AssertHelper(TestPartResult::Type type,
+                           const char* file,
+                           int line,
+                           const char* message)
+    : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+  delete data_;
+}
+
+// Message assignment, for assertion streaming support.
+void AssertHelper::operator=(const Message& message) const {
+  UnitTest::GetInstance()->
+    AddTestPartResult(data_->type, data_->file, data_->line,
+                      AppendUserMessage(data_->message, message),
+                      UnitTest::GetInstance()->impl()
+                      ->CurrentOsStackTraceExceptTop(1)
+                      // Skips the stack frame for this function itself.
+                      );  // NOLINT
+}
+
+// Mutex for linked pointers.
+GTEST_API_ GTEST_DEFINE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// Application pathname gotten in InitGoogleTest.
+std::string g_executable_path;
+
+// Returns the current application's name, removing directory path if that
+// is present.
+FilePath GetCurrentExecutableName() {
+  FilePath result;
+
+#if GTEST_OS_WINDOWS
+  result.Set(FilePath(g_executable_path).RemoveExtension("exe"));
+#else
+  result.Set(FilePath(g_executable_path));
+#endif  // GTEST_OS_WINDOWS
+
+  return result.RemoveDirectoryName();
+}
+
+// Functions for processing the gtest_output flag.
+
+// Returns the output format, or "" for normal printed output.
+std::string UnitTestOptions::GetOutputFormat() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL) return std::string("");
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  return (colon == NULL) ?
+      std::string(gtest_output_flag) :
+      std::string(gtest_output_flag, colon - gtest_output_flag);
+}
+
+// Returns the name of the requested output file, or the default if none
+// was explicitly specified.
+std::string UnitTestOptions::GetAbsolutePathToOutputFile() {
+  const char* const gtest_output_flag = GTEST_FLAG(output).c_str();
+  if (gtest_output_flag == NULL)
+    return "";
+
+  const char* const colon = strchr(gtest_output_flag, ':');
+  if (colon == NULL)
+    return internal::FilePath::ConcatPaths(
+        internal::FilePath(
+            UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(kDefaultOutputFile)).string();
+
+  internal::FilePath output_name(colon + 1);
+  if (!output_name.IsAbsolutePath())
+    // TODO(wan@google.com): on Windows \some\path is not an absolute
+    // path (as its meaning depends on the current drive), yet the
+    // following logic for turning it into an absolute path is wrong.
+    // Fix it.
+    output_name = internal::FilePath::ConcatPaths(
+        internal::FilePath(UnitTest::GetInstance()->original_working_dir()),
+        internal::FilePath(colon + 1));
+
+  if (!output_name.IsDirectory())
+    return output_name.string();
+
+  internal::FilePath result(internal::FilePath::GenerateUniqueFileName(
+      output_name, internal::GetCurrentExecutableName(),
+      GetOutputFormat().c_str()));
+  return result.string();
+}
+
+// Returns true iff the wildcard pattern matches the string.  The
+// first ':' or '\0' character in pattern marks the end of it.
+//
+// This recursive algorithm isn't very efficient, but is clear and
+// works well enough for matching test names, which are short.
+bool UnitTestOptions::PatternMatchesString(const char *pattern,
+                                           const char *str) {
+  switch (*pattern) {
+    case '\0':
+    case ':':  // Either ':' or '\0' marks the end of the pattern.
+      return *str == '\0';
+    case '?':  // Matches any single character.
+      return *str != '\0' && PatternMatchesString(pattern + 1, str + 1);
+    case '*':  // Matches any string (possibly empty) of characters.
+      return (*str != '\0' && PatternMatchesString(pattern, str + 1)) ||
+          PatternMatchesString(pattern + 1, str);
+    default:  // Non-special character.  Matches itself.
+      return *pattern == *str &&
+          PatternMatchesString(pattern + 1, str + 1);
+  }
+}
+
+bool UnitTestOptions::MatchesFilter(
+    const std::string& name, const char* filter) {
+  const char *cur_pattern = filter;
+  for (;;) {
+    if (PatternMatchesString(cur_pattern, name.c_str())) {
+      return true;
+    }
+
+    // Finds the next pattern in the filter.
+    cur_pattern = strchr(cur_pattern, ':');
+
+    // Returns if no more pattern can be found.
+    if (cur_pattern == NULL) {
+      return false;
+    }
+
+    // Skips the pattern separater (the ':' character).
+    cur_pattern++;
+  }
+}
+
+// Returns true iff the user-specified filter matches the test case
+// name and the test name.
+bool UnitTestOptions::FilterMatchesTest(const std::string &test_case_name,
+                                        const std::string &test_name) {
+  const std::string& full_name = test_case_name + "." + test_name.c_str();
+
+  // Split --gtest_filter at '-', if there is one, to separate into
+  // positive filter and negative filter portions
+  const char* const p = GTEST_FLAG(filter).c_str();
+  const char* const dash = strchr(p, '-');
+  std::string positive;
+  std::string negative;
+  if (dash == NULL) {
+    positive = GTEST_FLAG(filter).c_str();  // Whole string is a positive filter
+    negative = "";
+  } else {
+    positive = std::string(p, dash);   // Everything up to the dash
+    negative = std::string(dash + 1);  // Everything after the dash
+    if (positive.empty()) {
+      // Treat '-test1' as the same as '*-test1'
+      positive = kUniversalFilter;
+    }
+  }
+
+  // A filter is a colon-separated list of patterns.  It matches a
+  // test if any pattern in it matches the test.
+  return (MatchesFilter(full_name, positive.c_str()) &&
+          !MatchesFilter(full_name, negative.c_str()));
+}
+
+#if GTEST_HAS_SEH
+// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
+// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
+// This function is useful as an __except condition.
+int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
+  // Google Test should handle a SEH exception if:
+  //   1. the user wants it to, AND
+  //   2. this is not a breakpoint exception, AND
+  //   3. this is not a C++ exception (VC++ implements them via SEH,
+  //      apparently).
+  //
+  // SEH exception code for C++ exceptions.
+  // (see http://support.microsoft.com/kb/185294 for more information).
+  const DWORD kCxxExceptionCode = 0xe06d7363;
+
+  bool should_handle = true;
+
+  if (!GTEST_FLAG(catch_exceptions))
+    should_handle = false;
+  else if (exception_code == EXCEPTION_BREAKPOINT)
+    should_handle = false;
+  else if (exception_code == kCxxExceptionCode)
+    should_handle = false;
+
+  return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
+#endif  // GTEST_HAS_SEH
+
+}  // namespace internal
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results. Intercepts only failures from the current thread.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    TestPartResultArray* result)
+    : intercept_mode_(INTERCEPT_ONLY_CURRENT_THREAD),
+      result_(result) {
+  Init();
+}
+
+// The c'tor sets this object as the test part result reporter used by
+// Google Test.  The 'result' parameter specifies where to report the
+// results.
+ScopedFakeTestPartResultReporter::ScopedFakeTestPartResultReporter(
+    InterceptMode intercept_mode, TestPartResultArray* result)
+    : intercept_mode_(intercept_mode),
+      result_(result) {
+  Init();
+}
+
+void ScopedFakeTestPartResultReporter::Init() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    old_reporter_ = impl->GetGlobalTestPartResultReporter();
+    impl->SetGlobalTestPartResultReporter(this);
+  } else {
+    old_reporter_ = impl->GetTestPartResultReporterForCurrentThread();
+    impl->SetTestPartResultReporterForCurrentThread(this);
+  }
+}
+
+// The d'tor restores the test part result reporter used by Google Test
+// before.
+ScopedFakeTestPartResultReporter::~ScopedFakeTestPartResultReporter() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  if (intercept_mode_ == INTERCEPT_ALL_THREADS) {
+    impl->SetGlobalTestPartResultReporter(old_reporter_);
+  } else {
+    impl->SetTestPartResultReporterForCurrentThread(old_reporter_);
+  }
+}
+
+// Increments the test part result count and remembers the result.
+// This method is from the TestPartResultReporterInterface interface.
+void ScopedFakeTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  result_->Append(result);
+}
+
+namespace internal {
+
+// Returns the type ID of ::testing::Test.  We should always call this
+// instead of GetTypeId< ::testing::Test>() to get the type ID of
+// testing::Test.  This is to work around a suspected linker bug when
+// using Google Test as a framework on Mac OS X.  The bug causes
+// GetTypeId< ::testing::Test>() to return different values depending
+// on whether the call is from the Google Test framework itself or
+// from user test code.  GetTestTypeId() is guaranteed to always
+// return the same value, as it always calls GetTypeId<>() from the
+// gtest.cc, which is within the Google Test framework.
+TypeId GetTestTypeId() {
+  return GetTypeId<Test>();
+}
+
+// The value of GetTestTypeId() as seen from within the Google Test
+// library.  This is solely for testing GetTestTypeId().
+extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId();
+
+// This predicate-formatter checks that 'results' contains a test part
+// failure of the given type and that the failure message contains the
+// given substring.
+AssertionResult HasOneFailure(const char* /* results_expr */,
+                              const char* /* type_expr */,
+                              const char* /* substr_expr */,
+                              const TestPartResultArray& results,
+                              TestPartResult::Type type,
+                              const string& substr) {
+  const std::string expected(type == TestPartResult::kFatalFailure ?
+                        "1 fatal failure" :
+                        "1 non-fatal failure");
+  Message msg;
+  if (results.size() != 1) {
+    msg << "Expected: " << expected << "\n"
+        << "  Actual: " << results.size() << " failures";
+    for (int i = 0; i < results.size(); i++) {
+      msg << "\n" << results.GetTestPartResult(i);
+    }
+    return AssertionFailure() << msg;
+  }
+
+  const TestPartResult& r = results.GetTestPartResult(0);
+  if (r.type() != type) {
+    return AssertionFailure() << "Expected: " << expected << "\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  if (strstr(r.message(), substr.c_str()) == NULL) {
+    return AssertionFailure() << "Expected: " << expected << " containing \""
+                              << substr << "\"\n"
+                              << "  Actual:\n"
+                              << r;
+  }
+
+  return AssertionSuccess();
+}
+
+// The constructor of SingleFailureChecker remembers where to look up
+// test part results, what type of failure we expect, and what
+// substring the failure message should contain.
+SingleFailureChecker:: SingleFailureChecker(
+    const TestPartResultArray* results,
+    TestPartResult::Type type,
+    const string& substr)
+    : results_(results),
+      type_(type),
+      substr_(substr) {}
+
+// The destructor of SingleFailureChecker verifies that the given
+// TestPartResultArray contains exactly one failure that has the given
+// type and contains the given substring.  If that's not the case, a
+// non-fatal failure will be generated.
+SingleFailureChecker::~SingleFailureChecker() {
+  EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
+}
+
+DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->current_test_result()->AddTestPartResult(result);
+  unit_test_->listeners()->repeater()->OnTestPartResult(result);
+}
+
+DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
+    UnitTestImpl* unit_test) : unit_test_(unit_test) {}
+
+void DefaultPerThreadTestPartResultReporter::ReportTestPartResult(
+    const TestPartResult& result) {
+  unit_test_->GetGlobalTestPartResultReporter()->ReportTestPartResult(result);
+}
+
+// Returns the global test part result reporter.
+TestPartResultReporterInterface*
+UnitTestImpl::GetGlobalTestPartResultReporter() {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  return global_test_part_result_repoter_;
+}
+
+// Sets the global test part result reporter.
+void UnitTestImpl::SetGlobalTestPartResultReporter(
+    TestPartResultReporterInterface* reporter) {
+  internal::MutexLock lock(&global_test_part_result_reporter_mutex_);
+  global_test_part_result_repoter_ = reporter;
+}
+
+// Returns the test part result reporter for the current thread.
+TestPartResultReporterInterface*
+UnitTestImpl::GetTestPartResultReporterForCurrentThread() {
+  return per_thread_test_part_result_reporter_.get();
+}
+
+// Sets the test part result reporter for the current thread.
+void UnitTestImpl::SetTestPartResultReporterForCurrentThread(
+    TestPartResultReporterInterface* reporter) {
+  per_thread_test_part_result_reporter_.set(reporter);
+}
+
+// Gets the number of successful test cases.
+int UnitTestImpl::successful_test_case_count() const {
+  return CountIf(test_cases_, TestCasePassed);
+}
+
+// Gets the number of failed test cases.
+int UnitTestImpl::failed_test_case_count() const {
+  return CountIf(test_cases_, TestCaseFailed);
+}
+
+// Gets the number of all test cases.
+int UnitTestImpl::total_test_case_count() const {
+  return static_cast<int>(test_cases_.size());
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTestImpl::test_case_to_run_count() const {
+  return CountIf(test_cases_, ShouldRunTestCase);
+}
+
+// Gets the number of successful tests.
+int UnitTestImpl::successful_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::successful_test_count);
+}
+
+// Gets the number of failed tests.
+int UnitTestImpl::failed_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::failed_test_count);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTestImpl::reportable_disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_,
+                             &TestCase::reportable_disabled_test_count);
+}
+
+// Gets the number of disabled tests.
+int UnitTestImpl::disabled_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::disabled_test_count);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTestImpl::reportable_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::reportable_test_count);
+}
+
+// Gets the number of all tests.
+int UnitTestImpl::total_test_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::total_test_count);
+}
+
+// Gets the number of tests that should run.
+int UnitTestImpl::test_to_run_count() const {
+  return SumOverTestCaseList(test_cases_, &TestCase::test_to_run_count);
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// CurrentOsStackTraceExceptTop(1), Foo() will be included in the
+// trace but Bar() and CurrentOsStackTraceExceptTop() won't.
+std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
+  (void)skip_count;
+  return "";
+}
+
+// Returns the current time in milliseconds.
+TimeInMillis GetTimeInMillis() {
+#if GTEST_OS_WINDOWS_MOBILE || defined(__BORLANDC__)
+  // Difference between 1970-01-01 and 1601-01-01 in milliseconds.
+  // http://analogous.blogspot.com/2005/04/epoch.html
+  const TimeInMillis kJavaEpochToWinFileTimeDelta =
+    static_cast<TimeInMillis>(116444736UL) * 100000UL;
+  const DWORD kTenthMicrosInMilliSecond = 10000;
+
+  SYSTEMTIME now_systime;
+  FILETIME now_filetime;
+  ULARGE_INTEGER now_int64;
+  // TODO(kenton@google.com): Shouldn't this just use
+  //   GetSystemTimeAsFileTime()?
+  GetSystemTime(&now_systime);
+  if (SystemTimeToFileTime(&now_systime, &now_filetime)) {
+    now_int64.LowPart = now_filetime.dwLowDateTime;
+    now_int64.HighPart = now_filetime.dwHighDateTime;
+    now_int64.QuadPart = (now_int64.QuadPart / kTenthMicrosInMilliSecond) -
+      kJavaEpochToWinFileTimeDelta;
+    return now_int64.QuadPart;
+  }
+  return 0;
+#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
+  __timeb64 now;
+
+# ifdef _MSC_VER
+
+  // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
+  // (deprecated function) there.
+  // TODO(kenton@google.com): Use GetTickCount()?  Or use
+  //   SystemTimeToFileTime()
+#  pragma warning(push)          // Saves the current warning state.
+#  pragma warning(disable:4996)  // Temporarily disables warning 4996.
+  _ftime64(&now);
+#  pragma warning(pop)           // Restores the warning state.
+# else
+
+  _ftime64(&now);
+
+# endif  // _MSC_VER
+
+  return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
+#elif GTEST_HAS_GETTIMEOFDAY_
+  struct timeval now;
+  gettimeofday(&now, NULL);
+  return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
+#else
+# error "Don't know how to get the current time on your system."
+#endif
+}
+
+// Utilities
+
+// class String.
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Creates a UTF-16 wide string from the given ANSI string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the wide string, or NULL if the
+// input is NULL.
+LPCWSTR String::AnsiToUtf16(const char* ansi) {
+  if (!ansi) return NULL;
+  const int length = strlen(ansi);
+  const int unicode_length =
+      MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                          NULL, 0);
+  WCHAR* unicode = new WCHAR[unicode_length + 1];
+  MultiByteToWideChar(CP_ACP, 0, ansi, length,
+                      unicode, unicode_length);
+  unicode[unicode_length] = 0;
+  return unicode;
+}
+
+// Creates an ANSI string from the given wide string, allocating
+// memory using new. The caller is responsible for deleting the return
+// value using delete[]. Returns the ANSI string, or NULL if the
+// input is NULL.
+const char* String::Utf16ToAnsi(LPCWSTR utf16_str)  {
+  if (!utf16_str) return NULL;
+  const int ansi_length =
+      WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                          NULL, 0, NULL, NULL);
+  char* ansi = new char[ansi_length + 1];
+  WideCharToMultiByte(CP_ACP, 0, utf16_str, -1,
+                      ansi, ansi_length, NULL, NULL);
+  ansi[ansi_length] = 0;
+  return ansi;
+}
+
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Compares two C strings.  Returns true iff they have the same content.
+//
+// Unlike strcmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CStringEquals(const char * lhs, const char * rhs) {
+  if ( lhs == NULL ) return rhs == NULL;
+
+  if ( rhs == NULL ) return false;
+
+  return strcmp(lhs, rhs) == 0;
+}
+
+#if GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+// Converts an array of wide chars to a narrow string using the UTF-8
+// encoding, and streams the result to the given Message object.
+static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
+                                     Message* msg) {
+  for (size_t i = 0; i != length; ) {  // NOLINT
+    if (wstr[i] != L'\0') {
+      *msg << WideStringToUtf8(wstr + i, static_cast<int>(length - i));
+      while (i != length && wstr[i] != L'\0')
+        i++;
+    } else {
+      *msg << '\0';
+      i++;
+    }
+  }
+}
+
+#endif  // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
+
+}  // namespace internal
+
+// Constructs an empty Message.
+// We allocate the stringstream separately because otherwise each use of
+// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
+// stack frame leading to huge stack frames in some cases; gcc does not reuse
+// the stack space.
+Message::Message() : ss_(new ::std::stringstream) {
+  // By default, we want there to be enough precision when printing
+  // a double to a Message.
+  *ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+}
+
+// These two overloads allow streaming a wide C string to a Message
+// using the UTF-8 encoding.
+Message& Message::operator <<(const wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+Message& Message::operator <<(wchar_t* wide_c_str) {
+  return *this << internal::String::ShowWideCString(wide_c_str);
+}
+
+#if GTEST_HAS_STD_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::std::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+// Converts the given wide string to a narrow string using the UTF-8
+// encoding, and streams the result to this Message object.
+Message& Message::operator <<(const ::wstring& wstr) {
+  internal::StreamWideCharsToMessage(wstr.c_str(), wstr.length(), this);
+  return *this;
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Gets the text streamed to this object so far as an std::string.
+// Each '\0' character in the buffer is replaced with "\\0".
+std::string Message::GetString() const {
+  return internal::StringStreamToString(ss_.get());
+}
+
+// AssertionResult constructors.
+// Used in EXPECT_TRUE/FALSE(assertion_result).
+AssertionResult::AssertionResult(const AssertionResult& other)
+    : success_(other.success_),
+      message_(other.message_.get() != NULL ?
+               new ::std::string(*other.message_) :
+               static_cast< ::std::string*>(NULL)) {
+}
+
+// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+AssertionResult AssertionResult::operator!() const {
+  AssertionResult negation(!success_);
+  if (message_.get() != NULL)
+    negation << *message_;
+  return negation;
+}
+
+// Makes a successful assertion result.
+AssertionResult AssertionSuccess() {
+  return AssertionResult(true);
+}
+
+// Makes a failed assertion result.
+AssertionResult AssertionFailure() {
+  return AssertionResult(false);
+}
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << message.
+AssertionResult AssertionFailure(const Message& message) {
+  return AssertionFailure() << message;
+}
+
+namespace internal {
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+AssertionResult EqFailure(const char* expected_expression,
+                          const char* actual_expression,
+                          const std::string& expected_value,
+                          const std::string& actual_value,
+                          bool ignoring_case) {
+  Message msg;
+  msg << "Value of: " << actual_expression;
+  if (actual_value != actual_expression) {
+    msg << "\n  Actual: " << actual_value;
+  }
+
+  msg << "\nExpected: " << expected_expression;
+  if (ignoring_case) {
+    msg << " (ignoring case)";
+  }
+  if (expected_value != expected_expression) {
+    msg << "\nWhich is: " << expected_value;
+  }
+
+  return AssertionFailure() << msg;
+}
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value) {
+  const char* actual_message = assertion_result.message();
+  Message msg;
+  msg << "Value of: " << expression_text
+      << "\n  Actual: " << actual_predicate_value;
+  if (actual_message[0] != '\0')
+    msg << " (" << actual_message << ")";
+  msg << "\nExpected: " << expected_predicate_value;
+  return msg.GetString();
+}
+
+// Helper function for implementing ASSERT_NEAR.
+AssertionResult DoubleNearPredFormat(const char* expr1,
+                                     const char* expr2,
+                                     const char* abs_error_expr,
+                                     double val1,
+                                     double val2,
+                                     double abs_error) {
+  const double diff = fabs(val1 - val2);
+  if (diff <= abs_error) return AssertionSuccess();
+
+  // TODO(wan): do not print the value of an expression if it's
+  // already a literal.
+  return AssertionFailure()
+      << "The difference between " << expr1 << " and " << expr2
+      << " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
+      << expr1 << " evaluates to " << val1 << ",\n"
+      << expr2 << " evaluates to " << val2 << ", and\n"
+      << abs_error_expr << " evaluates to " << abs_error << ".";
+}
+
+
+// Helper template for implementing FloatLE() and DoubleLE().
+template <typename RawType>
+AssertionResult FloatingPointLE(const char* expr1,
+                                const char* expr2,
+                                RawType val1,
+                                RawType val2) {
+  // Returns success if val1 is less than val2,
+  if (val1 < val2) {
+    return AssertionSuccess();
+  }
+
+  // or if val1 is almost equal to val2.
+  const FloatingPoint<RawType> lhs(val1), rhs(val2);
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  // Note that the above two checks will both fail if either val1 or
+  // val2 is NaN, as the IEEE floating-point standard requires that
+  // any predicate involving a NaN must return false.
+
+  ::std::stringstream val1_ss;
+  val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val1;
+
+  ::std::stringstream val2_ss;
+  val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+          << val2;
+
+  return AssertionFailure()
+      << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+      << "  Actual: " << StringStreamToString(&val1_ss) << " vs "
+      << StringStreamToString(&val2_ss);
+}
+
+}  // namespace internal
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult FloatLE(const char* expr1, const char* expr2,
+                        float val1, float val2) {
+  return internal::FloatingPointLE<float>(expr1, expr2, val1, val2);
+}
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                         double val1, double val2) {
+  return internal::FloatingPointLE<double>(expr1, expr2, val1, val2);
+}
+
+namespace internal {
+
+// The helper function for {ASSERT|EXPECT}_EQ with int or enum
+// arguments.
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            BiggestInt expected,
+                            BiggestInt actual) {
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_?? with integer or enum arguments.  It is here
+// just to avoid copy-and-paste of similar code.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   BiggestInt val1, BiggestInt val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}
+
+// Implements the helper function for {ASSERT|EXPECT}_NE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(NE, !=)
+// Implements the helper function for {ASSERT|EXPECT}_LE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LE, <=)
+// Implements the helper function for {ASSERT|EXPECT}_LT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(LT, < )
+// Implements the helper function for {ASSERT|EXPECT}_GE with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GE, >=)
+// Implements the helper function for {ASSERT|EXPECT}_GT with int or
+// enum arguments.
+GTEST_IMPL_CMP_HELPER_(GT, > )
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const char* expected,
+                               const char* actual) {
+  if (String::CStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   false);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                   const char* actual_expression,
+                                   const char* expected,
+                                   const char* actual) {
+  if (String::CaseInsensitiveCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   true);
+}
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const char* s1,
+                               const char* s2) {
+  if (!String::CStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                              << s2_expression << "), actual: \""
+                              << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                   const char* s2_expression,
+                                   const char* s1,
+                                   const char* s2) {
+  if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  } else {
+    return AssertionFailure()
+        << "Expected: (" << s1_expression << ") != ("
+        << s2_expression << ") (ignoring case), actual: \""
+        << s1 << "\" vs \"" << s2 << "\"";
+  }
+}
+
+}  // namespace internal
+
+namespace {
+
+// Helper functions for implementing IsSubString() and IsNotSubstring().
+
+// This group of overloaded functions return true iff needle is a
+// substring of haystack.  NULL is considered a substring of itself
+// only.
+
+bool IsSubstringPred(const char* needle, const char* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return strstr(haystack, needle) != NULL;
+}
+
+bool IsSubstringPred(const wchar_t* needle, const wchar_t* haystack) {
+  if (needle == NULL || haystack == NULL)
+    return needle == haystack;
+
+  return wcsstr(haystack, needle) != NULL;
+}
+
+// StringType here can be either ::std::string or ::std::wstring.
+template <typename StringType>
+bool IsSubstringPred(const StringType& needle,
+                     const StringType& haystack) {
+  return haystack.find(needle) != StringType::npos;
+}
+
+// This function implements either IsSubstring() or IsNotSubstring(),
+// depending on the value of the expected_to_be_substring parameter.
+// StringType here can be const char*, const wchar_t*, ::std::string,
+// or ::std::wstring.
+template <typename StringType>
+AssertionResult IsSubstringImpl(
+    bool expected_to_be_substring,
+    const char* needle_expr, const char* haystack_expr,
+    const StringType& needle, const StringType& haystack) {
+  if (IsSubstringPred(needle, haystack) == expected_to_be_substring)
+    return AssertionSuccess();
+
+  const bool is_wide_string = sizeof(needle[0]) > 1;
+  const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
+  return AssertionFailure()
+      << "Value of: " << needle_expr << "\n"
+      << "  Actual: " << begin_string_quote << needle << "\"\n"
+      << "Expected: " << (expected_to_be_substring ? "" : "not ")
+      << "a substring of " << haystack_expr << "\n"
+      << "Which is: " << begin_string_quote << haystack << "\"";
+}
+
+}  // namespace
+
+// IsSubstring() and IsNotSubstring() check whether needle is a
+// substring of haystack (NULL is considered a substring of itself
+// only), and return an appropriate error message when they fail.
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+
+#if GTEST_HAS_STD_WSTRING
+AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(true, needle_expr, haystack_expr, needle, haystack);
+}
+
+AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack) {
+  return IsSubstringImpl(false, needle_expr, haystack_expr, needle, haystack);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+
+namespace {
+
+// Helper function for IsHRESULT{SuccessFailure} predicates
+AssertionResult HRESULTFailureHelper(const char* expr,
+                                     const char* expected,
+                                     long hr) {  // NOLINT
+# if GTEST_OS_WINDOWS_MOBILE
+
+  // Windows CE doesn't support FormatMessage.
+  const char error_text[] = "";
+
+# else
+
+  // Looks up the human-readable system message for the HRESULT code
+  // and since we're not passing any params to FormatMessage, we don't
+  // want inserts expanded.
+  const DWORD kFlags = FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_IGNORE_INSERTS;
+  const DWORD kBufSize = 4096;
+  // Gets the system's human readable message string for this HRESULT.
+  char error_text[kBufSize] = { '\0' };
+  DWORD message_length = ::FormatMessageA(kFlags,
+                                          0,  // no source, we're asking system
+                                          hr,  // the error
+                                          0,  // no line width restrictions
+                                          error_text,  // output buffer
+                                          kBufSize,  // buf size
+                                          NULL);  // no arguments for inserts
+  // Trims tailing white space (FormatMessage leaves a trailing CR-LF)
+  for (; message_length && IsSpace(error_text[message_length - 1]);
+          --message_length) {
+    error_text[message_length - 1] = '\0';
+  }
+
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+  const std::string error_hex("0x" + String::FormatHexInt(hr));
+  return ::testing::AssertionFailure()
+      << "Expected: " << expr << " " << expected << ".\n"
+      << "  Actual: " << error_hex << " " << error_text << "\n";
+}
+
+}  // namespace
+
+AssertionResult IsHRESULTSuccess(const char* expr, long hr) {  // NOLINT
+  if (SUCCEEDED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "succeeds", hr);
+}
+
+AssertionResult IsHRESULTFailure(const char* expr, long hr) {  // NOLINT
+  if (FAILED(hr)) {
+    return AssertionSuccess();
+  }
+  return HRESULTFailureHelper(expr, "fails", hr);
+}
+
+#endif  // GTEST_OS_WINDOWS
+
+// Utility functions for encoding Unicode text (wide strings) in
+// UTF-8.
+
+// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// like this:
+//
+// Code-point length   Encoding
+//   0 -  7 bits       0xxxxxxx
+//   8 - 11 bits       110xxxxx 10xxxxxx
+//  12 - 16 bits       1110xxxx 10xxxxxx 10xxxxxx
+//  17 - 21 bits       11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+
+// The maximum code-point a one-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint1 = (static_cast<UInt32>(1) <<  7) - 1;
+
+// The maximum code-point a two-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint2 = (static_cast<UInt32>(1) << (5 + 6)) - 1;
+
+// The maximum code-point a three-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint3 = (static_cast<UInt32>(1) << (4 + 2*6)) - 1;
+
+// The maximum code-point a four-byte UTF-8 sequence can represent.
+const UInt32 kMaxCodePoint4 = (static_cast<UInt32>(1) << (3 + 3*6)) - 1;
+
+// Chops off the n lowest bits from a bit pattern.  Returns the n
+// lowest bits.  As a side effect, the original bit pattern will be
+// shifted to the right by n bits.
+inline UInt32 ChopLowBits(UInt32* bits, int n) {
+  const UInt32 low_bits = *bits & ((static_cast<UInt32>(1) << n) - 1);
+  *bits >>= n;
+  return low_bits;
+}
+
+// Converts a Unicode code point to a narrow string in UTF-8 encoding.
+// code_point parameter is of type UInt32 because wchar_t may not be
+// wide enough to contain a code point.
+// If the code_point is not a valid Unicode code point
+// (i.e. outside of Unicode range U+0 to U+10FFFF) it will be converted
+// to "(Invalid Unicode 0xXXXXXXXX)".
+std::string CodePointToUtf8(UInt32 code_point) {
+  if (code_point > kMaxCodePoint4) {
+    return "(Invalid Unicode 0x" + String::FormatHexInt(code_point) + ")";
+  }
+
+  char str[5];  // Big enough for the largest valid code point.
+  if (code_point <= kMaxCodePoint1) {
+    str[1] = '\0';
+    str[0] = static_cast<char>(code_point);                          // 0xxxxxxx
+  } else if (code_point <= kMaxCodePoint2) {
+    str[2] = '\0';
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xC0 | code_point);                   // 110xxxxx
+  } else if (code_point <= kMaxCodePoint3) {
+    str[3] = '\0';
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xE0 | code_point);                   // 1110xxxx
+  } else {  // code_point <= kMaxCodePoint4
+    str[4] = '\0';
+    str[3] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[2] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[1] = static_cast<char>(0x80 | ChopLowBits(&code_point, 6));  // 10xxxxxx
+    str[0] = static_cast<char>(0xF0 | code_point);                   // 11110xxx
+  }
+  return str;
+}
+
+// The following two functions only make sense if the the system
+// uses UTF-16 for wide string encoding. All supported systems
+// with 16 bit wchar_t (Windows, Cygwin, Symbian OS) do use UTF-16.
+
+// Determines if the arguments constitute UTF-16 surrogate pair
+// and thus should be combined into a single Unicode code point
+// using CreateCodePointFromUtf16SurrogatePair.
+inline bool IsUtf16SurrogatePair(wchar_t first, wchar_t second) {
+  return sizeof(wchar_t) == 2 &&
+      (first & 0xFC00) == 0xD800 && (second & 0xFC00) == 0xDC00;
+}
+
+// Creates a Unicode code point from UTF16 surrogate pair.
+inline UInt32 CreateCodePointFromUtf16SurrogatePair(wchar_t first,
+                                                    wchar_t second) {
+  const UInt32 mask = (1 << 10) - 1;
+  return (sizeof(wchar_t) == 2) ?
+      (((first & mask) << 10) | (second & mask)) + 0x10000 :
+      // This function should not be called when the condition is
+      // false, but we provide a sensible default in case it is.
+      static_cast<UInt32>(first);
+}
+
+// Converts a wide string to a narrow string in UTF-8 encoding.
+// The wide string is assumed to have the following encoding:
+//   UTF-16 if sizeof(wchar_t) == 2 (on Windows, Cygwin, Symbian OS)
+//   UTF-32 if sizeof(wchar_t) == 4 (on Linux)
+// Parameter str points to a null-terminated wide string.
+// Parameter num_chars may additionally limit the number
+// of wchar_t characters processed. -1 is used when the entire string
+// should be processed.
+// If the string contains code points that are not valid Unicode code points
+// (i.e. outside of Unicode range U+0 to U+10FFFF) they will be output
+// as '(Invalid Unicode 0xXXXXXXXX)'. If the string is in UTF16 encoding
+// and contains invalid UTF-16 surrogate pairs, values in those pairs
+// will be encoded as individual Unicode characters from Basic Normal Plane.
+std::string WideStringToUtf8(const wchar_t* str, int num_chars) {
+  if (num_chars == -1)
+    num_chars = static_cast<int>(wcslen(str));
+
+  ::std::stringstream stream;
+  for (int i = 0; i < num_chars; ++i) {
+    UInt32 unicode_code_point;
+
+    if (str[i] == L'\0') {
+      break;
+    } else if (i + 1 < num_chars && IsUtf16SurrogatePair(str[i], str[i + 1])) {
+      unicode_code_point = CreateCodePointFromUtf16SurrogatePair(str[i],
+                                                                 str[i + 1]);
+      i++;
+    } else {
+      unicode_code_point = static_cast<UInt32>(str[i]);
+    }
+
+    stream << CodePointToUtf8(unicode_code_point);
+  }
+  return StringStreamToString(&stream);
+}
+
+// Converts a wide C string to an std::string using the UTF-8 encoding.
+// NULL will be converted to "(null)".
+std::string String::ShowWideCString(const wchar_t * wide_c_str) {
+  if (wide_c_str == NULL)  return "(null)";
+
+  return internal::WideStringToUtf8(wide_c_str, -1);
+}
+
+// Compares two wide C strings.  Returns true iff they have the same
+// content.
+//
+// Unlike wcscmp(), this function can handle NULL argument(s).  A NULL
+// C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::WideCStringEquals(const wchar_t * lhs, const wchar_t * rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+  return wcscmp(lhs, rhs) == 0;
+}
+
+// Helper function for *_STREQ on wide strings.
+AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                               const char* actual_expression,
+                               const wchar_t* expected,
+                               const wchar_t* actual) {
+  if (String::WideCStringEquals(expected, actual)) {
+    return AssertionSuccess();
+  }
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   PrintToString(expected),
+                   PrintToString(actual),
+                   false);
+}
+
+// Helper function for *_STRNE on wide strings.
+AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                               const char* s2_expression,
+                               const wchar_t* s1,
+                               const wchar_t* s2) {
+  if (!String::WideCStringEquals(s1, s2)) {
+    return AssertionSuccess();
+  }
+
+  return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+                            << s2_expression << "), actual: "
+                            << PrintToString(s1)
+                            << " vs " << PrintToString(s2);
+}
+
+// Compares two C strings, ignoring case.  Returns true iff they have
+// the same content.
+//
+// Unlike strcasecmp(), this function can handle NULL argument(s).  A
+// NULL C string is considered different to any non-NULL C string,
+// including the empty string.
+bool String::CaseInsensitiveCStringEquals(const char * lhs, const char * rhs) {
+  if (lhs == NULL)
+    return rhs == NULL;
+  if (rhs == NULL)
+    return false;
+  return posix::StrCaseCmp(lhs, rhs) == 0;
+}
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                              const wchar_t* rhs) {
+  if (lhs == NULL) return rhs == NULL;
+
+  if (rhs == NULL) return false;
+
+#if GTEST_OS_WINDOWS
+  return _wcsicmp(lhs, rhs) == 0;
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
+  return wcscasecmp(lhs, rhs) == 0;
+#else
+  // Android, Mac OS X and Cygwin don't define wcscasecmp.
+  // Other unknown OSes may not define it either.
+  wint_t left, right;
+  do {
+    left = towlower(*lhs++);
+    right = towlower(*rhs++);
+  } while (left && left == right);
+  return left == right;
+#endif  // OS selector
+}
+
+// Returns true iff str ends with the given suffix, ignoring case.
+// Any string is considered to end with an empty suffix.
+bool String::EndsWithCaseInsensitive(
+    const std::string& str, const std::string& suffix) {
+  const size_t str_len = str.length();
+  const size_t suffix_len = suffix.length();
+  return (str_len >= suffix_len) &&
+         CaseInsensitiveCStringEquals(str.c_str() + str_len - suffix_len,
+                                      suffix.c_str());
+}
+
+// Formats an int value as "%02d".
+std::string String::FormatIntWidth2(int value) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2) << value;
+  return ss.str();
+}
+
+// Formats an int value as "%X".
+std::string String::FormatHexInt(int value) {
+  std::stringstream ss;
+  ss << std::hex << std::uppercase << value;
+  return ss.str();
+}
+
+// Formats a byte as "%02X".
+std::string String::FormatByte(unsigned char value) {
+  std::stringstream ss;
+  ss << std::setfill('0') << std::setw(2) << std::hex << std::uppercase
+     << static_cast<unsigned int>(value);
+  return ss.str();
+}
+
+// Converts the buffer in a stringstream to an std::string, converting NUL
+// bytes to "\\0" along the way.
+std::string StringStreamToString(::std::stringstream* ss) {
+  const ::std::string& str = ss->str();
+  const char* const start = str.c_str();
+  const char* const end = start + str.length();
+
+  std::string result;
+  result.reserve(2 * (end - start));
+  for (const char* ch = start; ch != end; ++ch) {
+    if (*ch == '\0') {
+      result += "\\0";  // Replaces NUL with "\\0";
+    } else {
+      result += *ch;
+    }
+  }
+
+  return result;
+}
+
+// Appends the user-supplied message to the Google-Test-generated message.
+std::string AppendUserMessage(const std::string& gtest_msg,
+                              const Message& user_msg) {
+  // Appends the user message if it's non-empty.
+  const std::string user_msg_string = user_msg.GetString();
+  if (user_msg_string.empty()) {
+    return gtest_msg;
+  }
+
+  return gtest_msg + "\n" + user_msg_string;
+}
+
+}  // namespace internal
+
+// class TestResult
+
+// Creates an empty TestResult.
+TestResult::TestResult()
+    : death_test_count_(0),
+      elapsed_time_(0) {
+}
+
+// D'tor.
+TestResult::~TestResult() {
+}
+
+// Returns the i-th test part result among all the results. i can
+// range from 0 to total_part_count() - 1. If i is not in that range,
+// aborts the program.
+const TestPartResult& TestResult::GetTestPartResult(int i) const {
+  if (i < 0 || i >= total_part_count())
+    internal::posix::Abort();
+  return test_part_results_.at(i);
+}
+
+// Returns the i-th test property. i can range from 0 to
+// test_property_count() - 1. If i is not in that range, aborts the
+// program.
+const TestProperty& TestResult::GetTestProperty(int i) const {
+  if (i < 0 || i >= test_property_count())
+    internal::posix::Abort();
+  return test_properties_.at(i);
+}
+
+// Clears the test part results.
+void TestResult::ClearTestPartResults() {
+  test_part_results_.clear();
+}
+
+// Adds a test part result to the list.
+void TestResult::AddTestPartResult(const TestPartResult& test_part_result) {
+  test_part_results_.push_back(test_part_result);
+}
+
+// Adds a test property to the list. If a property with the same key as the
+// supplied property is already represented, the value of this test_property
+// replaces the old value for that key.
+void TestResult::RecordProperty(const std::string& xml_element,
+                                const TestProperty& test_property) {
+  if (!ValidateTestProperty(xml_element, test_property)) {
+    return;
+  }
+  internal::MutexLock lock(&test_properites_mutex_);
+  const std::vector<TestProperty>::iterator property_with_matching_key =
+      std::find_if(test_properties_.begin(), test_properties_.end(),
+                   internal::TestPropertyKeyIs(test_property.key()));
+  if (property_with_matching_key == test_properties_.end()) {
+    test_properties_.push_back(test_property);
+    return;
+  }
+  property_with_matching_key->SetValue(test_property.value());
+}
+
+// The list of reserved attributes used in the <testsuites> element of XML
+// output.
+static const char* const kReservedTestSuitesAttributes[] = {
+  "disabled",
+  "errors",
+  "failures",
+  "name",
+  "random_seed",
+  "tests",
+  "time",
+  "timestamp"
+};
+
+// The list of reserved attributes used in the <testsuite> element of XML
+// output.
+static const char* const kReservedTestSuiteAttributes[] = {
+  "disabled",
+  "errors",
+  "failures",
+  "name",
+  "tests",
+  "time"
+};
+
+// The list of reserved attributes used in the <testcase> element of XML output.
+static const char* const kReservedTestCaseAttributes[] = {
+  "classname",
+  "name",
+  "status",
+  "time",
+  "type_param",
+  "value_param"
+};
+
+template <int kSize>
+std::vector<std::string> ArrayAsVector(const char* const (&array)[kSize]) {
+  return std::vector<std::string>(array, array + kSize);
+}
+
+static std::vector<std::string> GetReservedAttributesForElement(
+    const std::string& xml_element) {
+  if (xml_element == "testsuites") {
+    return ArrayAsVector(kReservedTestSuitesAttributes);
+  } else if (xml_element == "testsuite") {
+    return ArrayAsVector(kReservedTestSuiteAttributes);
+  } else if (xml_element == "testcase") {
+    return ArrayAsVector(kReservedTestCaseAttributes);
+  } else {
+    GTEST_CHECK_(false) << "Unrecognized xml_element provided: " << xml_element;
+  }
+  // This code is unreachable but some compilers may not realizes that.
+  return std::vector<std::string>();
+}
+
+static std::string FormatWordList(const std::vector<std::string>& words) {
+  Message word_list;
+  for (size_t i = 0; i < words.size(); ++i) {
+    if (i > 0 && words.size() > 2) {
+      word_list << ", ";
+    }
+    if (i == words.size() - 1) {
+      word_list << "and ";
+    }
+    word_list << "'" << words[i] << "'";
+  }
+  return word_list.GetString();
+}
+
+bool ValidateTestPropertyName(const std::string& property_name,
+                              const std::vector<std::string>& reserved_names) {
+  if (std::find(reserved_names.begin(), reserved_names.end(), property_name) !=
+          reserved_names.end()) {
+    ADD_FAILURE() << "Reserved key used in RecordProperty(): " << property_name
+                  << " (" << FormatWordList(reserved_names)
+                  << " are reserved by " << GTEST_NAME_ << ")";
+    return false;
+  }
+  return true;
+}
+
+// Adds a failure if the key is a reserved attribute of the element named
+// xml_element.  Returns true if the property is valid.
+bool TestResult::ValidateTestProperty(const std::string& xml_element,
+                                      const TestProperty& test_property) {
+  return ValidateTestPropertyName(test_property.key(),
+                                  GetReservedAttributesForElement(xml_element));
+}
+
+// Clears the object.
+void TestResult::Clear() {
+  test_part_results_.clear();
+  test_properties_.clear();
+  death_test_count_ = 0;
+  elapsed_time_ = 0;
+}
+
+// Returns true iff the test failed.
+bool TestResult::Failed() const {
+  for (int i = 0; i < total_part_count(); ++i) {
+    if (GetTestPartResult(i).failed())
+      return true;
+  }
+  return false;
+}
+
+// Returns true iff the test part fatally failed.
+static bool TestPartFatallyFailed(const TestPartResult& result) {
+  return result.fatally_failed();
+}
+
+// Returns true iff the test fatally failed.
+bool TestResult::HasFatalFailure() const {
+  return CountIf(test_part_results_, TestPartFatallyFailed) > 0;
+}
+
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+  return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+  return CountIf(test_part_results_, TestPartNonfatallyFailed) > 0;
+}
+
+// Gets the number of all test parts.  This is the sum of the number
+// of successful test parts and the number of failed test parts.
+int TestResult::total_part_count() const {
+  return static_cast<int>(test_part_results_.size());
+}
+
+// Returns the number of the test properties.
+int TestResult::test_property_count() const {
+  return static_cast<int>(test_properties_.size());
+}
+
+// class Test
+
+// Creates a Test object.
+
+// The c'tor saves the values of all Google Test flags.
+Test::Test()
+    : gtest_flag_saver_(new internal::GTestFlagSaver) {
+}
+
+// The d'tor restores the values of all Google Test flags.
+Test::~Test() {
+  delete gtest_flag_saver_;
+}
+
+// Sets up the test fixture.
+//
+// A sub-class may override this.
+void Test::SetUp() {
+}
+
+// Tears down the test fixture.
+//
+// A sub-class may override this.
+void Test::TearDown() {
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, const std::string& value) {
+  UnitTest::GetInstance()->RecordProperty(key, value);
+}
+
+// Allows user supplied key value pairs to be recorded for later output.
+void Test::RecordProperty(const std::string& key, int value) {
+  Message value_message;
+  value_message << value;
+  RecordProperty(key, value_message.GetString().c_str());
+}
+
+namespace internal {
+
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message) {
+  // This function is a friend of UnitTest and as such has access to
+  // AddTestPartResult.
+  UnitTest::GetInstance()->AddTestPartResult(
+      result_type,
+      NULL,  // No info about the source file where the exception occurred.
+      -1,    // We have no info on which line caused the exception.
+      message,
+      "");   // No stack trace, either.
+}
+
+}  // namespace internal
+
+// Google Test requires all tests in the same test case to use the same test
+// fixture class.  This function checks if the current test has the
+// same fixture class as the first test in the current test case.  If
+// yes, it returns true; otherwise it generates a Google Test failure and
+// returns false.
+bool Test::HasSameFixtureClass() {
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  const TestCase* const test_case = impl->current_test_case();
+
+  // Info about the first test in the current test case.
+  const TestInfo* const first_test_info = test_case->test_info_list()[0];
+  const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
+  const char* const first_test_name = first_test_info->name();
+
+  // Info about the current test.
+  const TestInfo* const this_test_info = impl->current_test_info();
+  const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
+  const char* const this_test_name = this_test_info->name();
+
+  if (this_fixture_id != first_fixture_id) {
+    // Is the first test defined using TEST?
+    const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId();
+    // Is this test defined using TEST?
+    const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
+
+    if (first_is_TEST || this_is_TEST) {
+      // The user mixed TEST and TEST_F in this test case - we'll tell
+      // him/her how to fix it.
+
+      // Gets the name of the TEST and the name of the TEST_F.  Note
+      // that first_is_TEST and this_is_TEST cannot both be true, as
+      // the fixture IDs are different for the two tests.
+      const char* const TEST_name =
+          first_is_TEST ? first_test_name : this_test_name;
+      const char* const TEST_F_name =
+          first_is_TEST ? this_test_name : first_test_name;
+
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class, so mixing TEST_F and TEST in the same test case is\n"
+          << "illegal.  In test case " << this_test_info->test_case_name()
+          << ",\n"
+          << "test " << TEST_F_name << " is defined using TEST_F but\n"
+          << "test " << TEST_name << " is defined using TEST.  You probably\n"
+          << "want to change the TEST to TEST_F or move it to another test\n"
+          << "case.";
+    } else {
+      // The user defined two fixture classes with the same name in
+      // two namespaces - we'll tell him/her how to fix it.
+      ADD_FAILURE()
+          << "All tests in the same test case must use the same test fixture\n"
+          << "class.  However, in test case "
+          << this_test_info->test_case_name() << ",\n"
+          << "you defined test " << first_test_name
+          << " and test " << this_test_name << "\n"
+          << "using two different test fixture classes.  This can happen if\n"
+          << "the two classes are from different namespaces or translation\n"
+          << "units and have the same name.  You should probably rename one\n"
+          << "of the classes to put the tests into different test cases.";
+    }
+    return false;
+  }
+
+  return true;
+}
+
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test.  This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static std::string* FormatSehExceptionMessage(DWORD exception_code,
+                                              const char* location) {
+  Message message;
+  message << "SEH exception with code 0x" << std::setbase(16) <<
+    exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+  return new std::string(message.GetString());
+}
+
+#endif  // GTEST_HAS_SEH
+
+namespace internal {
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static std::string FormatCxxExceptionMessage(const char* description,
+                                             const char* location) {
+  Message message;
+  if (description != NULL) {
+    message << "C++ exception with description \"" << description << "\"";
+  } else {
+    message << "Unknown C++ exception";
+  }
+  message << " thrown in " << location << ".";
+
+  return message.GetString();
+}
+
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result);
+
+GoogleTestFailureException::GoogleTestFailureException(
+    const TestPartResult& failure)
+    : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception.  (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function.  Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+  __try {
+    return (object->*method)();
+  } __except (internal::UnitTestOptions::GTestShouldProcessSEH(  // NOLINT
+      GetExceptionCode())) {
+    // We create the exception message on the heap because VC++ prohibits
+    // creation of objects with destructors on stack in functions using __try
+    // (see error C2712).
+    std::string* exception_message = FormatSehExceptionMessage(
+        GetExceptionCode(), location);
+    internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+                                             *exception_message);
+    delete exception_message;
+    return static_cast<Result>(0);
+  }
+#else
+  (void)location;
+  return (object->*method)();
+#endif  // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+    T* object, Result (T::*method)(), const char* location) {
+  // NOTE: The user code can affect the way in which Google Test handles
+  // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+  // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+  // after the exception is caught and either report or re-throw the
+  // exception based on the flag's value:
+  //
+  // try {
+  //   // Perform the test method.
+  // } catch (...) {
+  //   if (GTEST_FLAG(catch_exceptions))
+  //     // Report the exception as failure.
+  //   else
+  //     throw;  // Re-throws the original exception.
+  // }
+  //
+  // However, the purpose of this flag is to allow the program to drop into
+  // the debugger when the exception is thrown. On most platforms, once the
+  // control enters the catch block, the exception origin information is
+  // lost and the debugger will stop the program at the point of the
+  // re-throw in this function -- instead of at the point of the original
+  // throw statement in the code under test.  For this reason, we perform
+  // the check early, sacrificing the ability to affect Google Test's
+  // exception handling in the method where the exception is thrown.
+  if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+    try {
+      return HandleSehExceptionsInMethodIfSupported(object, method, location);
+    } catch (const internal::GoogleTestFailureException&) {  // NOLINT
+      // This exception type can only be thrown by a failed Google
+      // Test assertion with the intention of letting another testing
+      // framework catch it.  Therefore we just re-throw it.
+      throw;
+    } catch (const std::exception& e) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(e.what(), location));
+    } catch (...) {  // NOLINT
+      internal::ReportFailureInUnknownLocation(
+          TestPartResult::kFatalFailure,
+          FormatCxxExceptionMessage(NULL, location));
+    }
+    return static_cast<Result>(0);
+#else
+    return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif  // GTEST_HAS_EXCEPTIONS
+  } else {
+    return (object->*method)();
+  }
+}
+
+}  // namespace internal
+
+// Runs the test and updates the test result.
+void Test::Run() {
+  if (!HasSameFixtureClass()) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
+  // We will run the test only if SetUp() was successful.
+  if (!HasFatalFailure()) {
+    impl->os_stack_trace_getter()->UponLeavingGTest();
+    internal::HandleExceptionsInMethodIfSupported(
+        this, &Test::TestBody, "the test body");
+  }
+
+  // However, we want to clean up as much as possible.  Hence we will
+  // always call TearDown(), even if SetUp() or the test body has
+  // failed.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &Test::TearDown, "TearDown()");
+}
+
+// Returns true iff the current test has a fatal failure.
+bool Test::HasFatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
+}
+
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+  return internal::GetUnitTestImpl()->current_test_result()->
+      HasNonfatalFailure();
+}
+
+// class TestInfo
+
+// Constructs a TestInfo object. It assumes ownership of the test factory
+// object.
+TestInfo::TestInfo(const std::string& a_test_case_name,
+                   const std::string& a_name,
+                   const char* a_type_param,
+                   const char* a_value_param,
+                   internal::TypeId fixture_class_id,
+                   internal::TestFactoryBase* factory)
+    : test_case_name_(a_test_case_name),
+      name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+      fixture_class_id_(fixture_class_id),
+      should_run_(false),
+      is_disabled_(false),
+      matches_filter_(false),
+      factory_(factory),
+      result_() {}
+
+// Destructs a TestInfo object.
+TestInfo::~TestInfo() { delete factory_; }
+
+namespace internal {
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param:       the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param:      text representation of the test's value parameter,
+//                     or NULL if this is not a value-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name,
+    const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory) {
+  TestInfo* const test_info =
+      new TestInfo(test_case_name, name, type_param, value_param,
+                   fixture_class_id, factory);
+  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
+  return test_info;
+}
+
+#if GTEST_HAS_PARAM_TEST
+void ReportInvalidTestCaseType(const char* test_case_name,
+                               const char* file, int line) {
+  Message errors;
+  errors
+      << "Attempted redefinition of test case " << test_case_name << ".\n"
+      << "All tests in the same test case must use the same test fixture\n"
+      << "class.  However, in test case " << test_case_name << ", you tried\n"
+      << "to define a test using a fixture class different from the one\n"
+      << "used earlier. This can happen if the two fixture classes are\n"
+      << "from different namespaces and have the same name. You should\n"
+      << "probably rename one of the classes to put the tests into different\n"
+      << "test cases.";
+
+  fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+          errors.GetString().c_str());
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+}  // namespace internal
+
+namespace {
+
+// A predicate that checks the test name of a TestInfo against a known
+// value.
+//
+// This is used for implementation of the TestCase class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestNameIs is copyable.
+
+//Commenting out this class since its not used and wherefor produces warnings
+// class TestNameIs {
+// public:
+//  // Constructor.
+//  //
+//  // TestNameIs has NO default constructor.
+//  explicit TestNameIs(const char* name)
+//      : name_(name) {}
+//
+//  // Returns true iff the test name of test_info matches name_.
+//  bool operator()(const TestInfo * test_info) const {
+//    return test_info && test_info->name() == name_;
+//  }
+//
+// private:
+//  std::string name_;
+//};
+
+}  // namespace
+
+namespace internal {
+
+// This method expands all parameterized tests registered with macros TEST_P
+// and INSTANTIATE_TEST_CASE_P into regular tests and registers those.
+// This will be done just once during the program runtime.
+void UnitTestImpl::RegisterParameterizedTests() {
+#if GTEST_HAS_PARAM_TEST
+  if (!parameterized_tests_registered_) {
+    parameterized_test_registry_.RegisterTests();
+    parameterized_tests_registered_ = true;
+  }
+#endif
+}
+
+}  // namespace internal
+
+// Creates the test object, runs it, records its result, and then
+// deletes it.
+void TestInfo::Run() {
+  if (!should_run_) return;
+
+  // Tells UnitTest where to store test result.
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_info(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  // Notifies the unit test event listeners that a test is about to start.
+  repeater->OnTestStart(*this);
+
+  const TimeInMillis start = internal::GetTimeInMillis();
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+
+  // Creates the test object.
+  Test* const test = internal::HandleExceptionsInMethodIfSupported(
+      factory_, &internal::TestFactoryBase::CreateTest,
+      "the test fixture's constructor");
+
+  // Runs the test only if the test object was created and its
+  // constructor didn't generate a fatal failure.
+  if ((test != NULL) && !Test::HasFatalFailure()) {
+    // This doesn't throw as all user code that can throw are wrapped into
+    // exception handling code.
+    test->Run();
+  }
+
+  // Deletes the test object.
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      test, &Test::DeleteSelf_, "the test fixture's destructor");
+
+  result_.set_elapsed_time(internal::GetTimeInMillis() - start);
+
+  // Notifies the unit test event listener that a test has just finished.
+  repeater->OnTestEnd(*this);
+
+  // Tells UnitTest to stop associating assertion results to this
+  // test.
+  impl->set_current_test_info(NULL);
+}
+
+// class TestCase
+
+// Gets the number of successful tests in this test case.
+int TestCase::successful_test_count() const {
+  return CountIf(test_info_list_, TestPassed);
+}
+
+// Gets the number of failed tests in this test case.
+int TestCase::failed_test_count() const {
+  return CountIf(test_info_list_, TestFailed);
+}
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int TestCase::reportable_disabled_test_count() const {
+  return CountIf(test_info_list_, TestReportableDisabled);
+}
+
+// Gets the number of disabled tests in this test case.
+int TestCase::disabled_test_count() const {
+  return CountIf(test_info_list_, TestDisabled);
+}
+
+// Gets the number of tests to be printed in the XML report.
+int TestCase::reportable_test_count() const {
+  return CountIf(test_info_list_, TestReportable);
+}
+
+// Get the number of tests in this test case that should run.
+int TestCase::test_to_run_count() const {
+  return CountIf(test_info_list_, ShouldRunTest);
+}
+
+// Gets the number of all tests.
+int TestCase::total_test_count() const {
+  return static_cast<int>(test_info_list_.size());
+}
+
+// Creates a TestCase with the given name.
+//
+// Arguments:
+//
+//   name:         name of the test case
+//   a_type_param: the name of the test case's type parameter, or NULL if
+//                 this is not a typed or a type-parameterized test case.
+//   set_up_tc:    pointer to the function that sets up the test case
+//   tear_down_tc: pointer to the function that tears down the test case
+TestCase::TestCase(const char* a_name, const char* a_type_param,
+                   Test::SetUpTestCaseFunc set_up_tc,
+                   Test::TearDownTestCaseFunc tear_down_tc)
+    : name_(a_name),
+      type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+      set_up_tc_(set_up_tc),
+      tear_down_tc_(tear_down_tc),
+      should_run_(false),
+      elapsed_time_(0) {
+}
+
+// Destructor of TestCase.
+TestCase::~TestCase() {
+  // Deletes every Test in the collection.
+  ForEach(test_info_list_, internal::Delete<TestInfo>);
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+const TestInfo* TestCase::GetTestInfo(int i) const {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Returns the i-th test among all the tests. i can range from 0 to
+// total_test_count() - 1. If i is not in that range, returns NULL.
+TestInfo* TestCase::GetMutableTestInfo(int i) {
+  const int index = GetElementOr(test_indices_, i, -1);
+  return index < 0 ? NULL : test_info_list_[index];
+}
+
+// Adds a test to this test case.  Will delete the test upon
+// destruction of the TestCase object.
+void TestCase::AddTestInfo(TestInfo * test_info) {
+  test_info_list_.push_back(test_info);
+  test_indices_.push_back(static_cast<int>(test_indices_.size()));
+}
+
+// Runs every test in this TestCase.
+void TestCase::Run() {
+  if (!should_run_) return;
+
+  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+  impl->set_current_test_case(this);
+
+  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
+
+  repeater->OnTestCaseStart(*this);
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
+
+  const internal::TimeInMillis start = internal::GetTimeInMillis();
+  for (int i = 0; i < total_test_count(); i++) {
+    GetMutableTestInfo(i)->Run();
+  }
+  elapsed_time_ = internal::GetTimeInMillis() - start;
+
+  impl->os_stack_trace_getter()->UponLeavingGTest();
+  internal::HandleExceptionsInMethodIfSupported(
+      this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
+  repeater->OnTestCaseEnd(*this);
+  impl->set_current_test_case(NULL);
+}
+
+// Clears the results of all tests in this test case.
+void TestCase::ClearResult() {
+  ad_hoc_test_result_.Clear();
+  ForEach(test_info_list_, TestInfo::ClearTestResult);
+}
+
+// Shuffles the tests in this test case.
+void TestCase::ShuffleTests(internal::Random* random) {
+  Shuffle(random, &test_indices_);
+}
+
+// Restores the test order to before the first shuffle.
+void TestCase::UnshuffleTests() {
+  for (size_t i = 0; i < test_indices_.size(); i++) {
+    test_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Formats a countable noun.  Depending on its quantity, either the
+// singular form or the plural form is used. e.g.
+//
+// FormatCountableNoun(1, "formula", "formuli") returns "1 formula".
+// FormatCountableNoun(5, "book", "books") returns "5 books".
+static std::string FormatCountableNoun(int count,
+                                       const char * singular_form,
+                                       const char * plural_form) {
+  return internal::StreamableToString(count) + " " +
+      (count == 1 ? singular_form : plural_form);
+}
+
+// Formats the count of tests.
+static std::string FormatTestCount(int test_count) {
+  return FormatCountableNoun(test_count, "test", "tests");
+}
+
+// Formats the count of test cases.
+static std::string FormatTestCaseCount(int test_case_count) {
+  return FormatCountableNoun(test_case_count, "test case", "test cases");
+}
+
+// Converts a TestPartResult::Type enum to human-friendly string
+// representation.  Both kNonFatalFailure and kFatalFailure are translated
+// to "Failure", as the user usually doesn't care about the difference
+// between the two when viewing the test result.
+static const char * TestPartResultTypeToString(TestPartResult::Type type) {
+  switch (type) {
+    case TestPartResult::kSuccess:
+      return "Success";
+
+    case TestPartResult::kNonFatalFailure:
+    case TestPartResult::kFatalFailure:
+#ifdef _MSC_VER
+      return "error: ";
+#else
+      return "Failure\n";
+#endif
+    default:
+      return "Unknown result type";
+  }
+}
+
+namespace internal {
+
+// Prints a TestPartResult to an std::string.
+static std::string PrintTestPartResultToString(
+    const TestPartResult& test_part_result) {
+  return (Message()
+          << internal::FormatFileLocation(test_part_result.file_name(),
+                                          test_part_result.line_number())
+          << " " << TestPartResultTypeToString(test_part_result.type())
+          << test_part_result.message()).GetString();
+}
+
+// Prints a TestPartResult.
+static void PrintTestPartResult(const TestPartResult& test_part_result) {
+  const std::string& result =
+      PrintTestPartResultToString(test_part_result);
+  printf("%s\n", result.c_str());
+  fflush(stdout);
+  // If the test program runs in Visual Studio or a debugger, the
+  // following statements add the test part result message to the Output
+  // window such that the user can double-click on it to jump to the
+  // corresponding source code location; otherwise they do nothing.
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  // We don't call OutputDebugString*() on Windows Mobile, as printing
+  // to stdout is done by OutputDebugString() there already - we don't
+  // want the same message printed twice.
+  ::OutputDebugStringA(result.c_str());
+  ::OutputDebugStringA("\n");
+#endif
+}
+
+// class PrettyUnitTestResultPrinter
+
+enum GTestColor {
+  COLOR_DEFAULT,
+  COLOR_RED,
+  COLOR_GREEN,
+  COLOR_YELLOW
+};
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns the character attribute for the given color.
+WORD GetColorAttribute(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:    return FOREGROUND_RED;
+    case COLOR_GREEN:  return FOREGROUND_GREEN;
+    case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
+    default:           return 0;
+  }
+}
+
+#else
+
+// Returns the ANSI color code for the given color.  COLOR_DEFAULT is
+// an invalid input.
+const char* GetAnsiColorCode(GTestColor color) {
+  switch (color) {
+    case COLOR_RED:     return "1";
+    case COLOR_GREEN:   return "2";
+    case COLOR_YELLOW:  return "3";
+    default:            return NULL;
+  };
+}
+
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+
+// Returns true iff Google Test should use colors in the output.
+bool ShouldUseColor(bool stdout_is_tty) {
+  const char* const gtest_color = GTEST_FLAG(color).c_str();
+
+  if (String::CaseInsensitiveCStringEquals(gtest_color, "auto")) {
+#if GTEST_OS_WINDOWS
+    // On Windows the TERM variable is usually not set, but the
+    // console there does support colors.
+    return stdout_is_tty;
+#else
+    // On non-Windows platforms, we rely on the TERM variable.
+    const char* const term = posix::GetEnv("TERM");
+    const bool term_supports_color =
+        String::CStringEquals(term, "xterm") ||
+        String::CStringEquals(term, "xterm-color") ||
+        String::CStringEquals(term, "xterm-256color") ||
+        String::CStringEquals(term, "screen") ||
+        String::CStringEquals(term, "screen-256color") ||
+        String::CStringEquals(term, "linux") ||
+        String::CStringEquals(term, "cygwin");
+    return stdout_is_tty && term_supports_color;
+#endif  // GTEST_OS_WINDOWS
+  }
+
+  return String::CaseInsensitiveCStringEquals(gtest_color, "yes") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "true") ||
+      String::CaseInsensitiveCStringEquals(gtest_color, "t") ||
+      String::CStringEquals(gtest_color, "1");
+  // We take "yes", "true", "t", and "1" as meaning "yes".  If the
+  // value is neither one of these nor "auto", we treat it as "no" to
+  // be conservative.
+}
+
+// Helpers for printing colored strings to stdout. Note that on Windows, we
+// cannot simply emit special characters and have the terminal change colors.
+// This routine must actually emit the characters rather than return a string
+// that would be colored when printed, as can be done on Linux.
+void ColoredPrintf(GTestColor color, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+
+#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS
+  const bool use_color = false;
+#else
+  static const bool in_color_mode =
+      ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
+  const bool use_color = in_color_mode && (color != COLOR_DEFAULT);
+#endif  // GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS
+  // The '!= 0' comparison is necessary to satisfy MSVC 7.1.
+
+  if (!use_color) {
+    vprintf(fmt, args);
+    va_end(args);
+    return;
+  }
+
+#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
+
+  // Gets the current text color.
+  CONSOLE_SCREEN_BUFFER_INFO buffer_info;
+  GetConsoleScreenBufferInfo(stdout_handle, &buffer_info);
+  const WORD old_color_attrs = buffer_info.wAttributes;
+
+  // We need to flush the stream buffers into the console before each
+  // SetConsoleTextAttribute call lest it affect the text that is already
+  // printed but has not yet reached the console.
+  fflush(stdout);
+  SetConsoleTextAttribute(stdout_handle,
+                          GetColorAttribute(color) | FOREGROUND_INTENSITY);
+  vprintf(fmt, args);
+
+  fflush(stdout);
+  // Restores the text color.
+  SetConsoleTextAttribute(stdout_handle, old_color_attrs);
+#else
+  printf("\033[0;3%sm", GetAnsiColorCode(color));
+  vprintf(fmt, args);
+  printf("\033[m");  // Resets the terminal to default.
+#endif  // GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE
+  va_end(args);
+}
+
+// Text printed in Google Test's text output and --gunit_list_tests
+// output to label the type parameter and value parameter for a test.
+static const char kTypeParamLabel[] = "TypeParam";
+static const char kValueParamLabel[] = "GetParam()";
+
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+  const char* const type_param = test_info.type_param();
+  const char* const value_param = test_info.value_param();
+
+  if (type_param != NULL || value_param != NULL) {
+    printf(", where ");
+    if (type_param != NULL) {
+      printf("%s = %s", kTypeParamLabel, type_param);
+      if (value_param != NULL)
+        printf(" and ");
+    }
+    if (value_param != NULL) {
+      printf("%s = %s", kValueParamLabel, value_param);
+    }
+  }
+}
+
+// This class implements the TestEventListener interface.
+//
+// Class PrettyUnitTestResultPrinter is copyable.
+class PrettyUnitTestResultPrinter : public TestEventListener {
+ public:
+  PrettyUnitTestResultPrinter() {}
+  static void PrintTestName(const char * test_case, const char * test) {
+    printf("%s.%s", test_case, test);
+  }
+
+  // The following methods override what's in the TestEventListener class.
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+
+ private:
+  static void PrintFailedTests(const UnitTest& unit_test);
+};
+
+  // Fired before each iteration of tests starts.
+void PrettyUnitTestResultPrinter::OnTestIterationStart(
+    const UnitTest& unit_test, int iteration) {
+  if (GTEST_FLAG(repeat) != 1)
+    printf("\nRepeating all tests (iteration %d) . . .\n\n", iteration + 1);
+
+  const char* const filter = GTEST_FLAG(filter).c_str();
+
+  // Prints the filter if it's not *.  This reminds the user that some
+  // tests may be skipped.
+  if (!String::CStringEquals(filter, kUniversalFilter)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: %s filter = %s\n", GTEST_NAME_, filter);
+  }
+
+  if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+    const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: This is test shard %d of %s.\n",
+                  static_cast<int>(shard_index) + 1,
+                  internal::posix::GetEnv(kTestTotalShards));
+  }
+
+  if (GTEST_FLAG(shuffle)) {
+    ColoredPrintf(COLOR_YELLOW,
+                  "Note: Randomizing tests' orders with a seed of %d .\n",
+                  unit_test.random_seed());
+  }
+
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("Running %s from %s.\n",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsSetUpStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment set-up.\n");
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseStart(const TestCase& test_case) {
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s", counts.c_str(), test_case.name());
+  if (test_case.type_param() == NULL) {
+    printf("\n");
+  } else {
+    printf(", where %s = %s\n", kTypeParamLabel, test_case.type_param());
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
+  ColoredPrintf(COLOR_GREEN,  "[ RUN      ] ");
+  PrintTestName(test_info.test_case_name(), test_info.name());
+  printf("\n");
+  fflush(stdout);
+}
+
+// Called after an assertion failure.
+void PrettyUnitTestResultPrinter::OnTestPartResult(
+    const TestPartResult& result) {
+  // If the test part succeeded, we don't need to do anything.
+  if (result.type() == TestPartResult::kSuccess)
+    return;
+
+  // Print failure message from the assertion (e.g. expected this and got that).
+  PrintTestPartResult(result);
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestEnd(const TestInfo& test_info) {
+  if (test_info.result()->Passed()) {
+    ColoredPrintf(COLOR_GREEN, "[       OK ] ");
+  } else {
+    ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+  }
+  PrintTestName(test_info.test_case_name(), test_info.name());
+  if (test_info.result()->Failed())
+    PrintFullTestCommentIfPresent(test_info);
+
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms)\n", internal::StreamableToString(
+           test_info.result()->elapsed_time()).c_str());
+  } else {
+    printf("\n");
+  }
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnTestCaseEnd(const TestCase& test_case) {
+  if (!GTEST_FLAG(print_time)) return;
+
+  const std::string counts =
+      FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
+  ColoredPrintf(COLOR_GREEN, "[----------] ");
+  printf("%s from %s (%s ms total)\n\n",
+         counts.c_str(), test_case.name(),
+         internal::StreamableToString(test_case.elapsed_time()).c_str());
+  fflush(stdout);
+}
+
+void PrettyUnitTestResultPrinter::OnEnvironmentsTearDownStart(
+    const UnitTest& /*unit_test*/) {
+  ColoredPrintf(COLOR_GREEN,  "[----------] ");
+  printf("Global test environment tear-down\n");
+  fflush(stdout);
+}
+
+// Internal helper for printing the list of failed tests.
+void PrettyUnitTestResultPrinter::PrintFailedTests(const UnitTest& unit_test) {
+  const int failed_test_count = unit_test.failed_test_count();
+  if (failed_test_count == 0) {
+    return;
+  }
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    const TestCase& test_case = *unit_test.GetTestCase(i);
+    if (!test_case.should_run() || (test_case.failed_test_count() == 0)) {
+      continue;
+    }
+    for (int j = 0; j < test_case.total_test_count(); ++j) {
+      const TestInfo& test_info = *test_case.GetTestInfo(j);
+      if (!test_info.should_run() || test_info.result()->Passed()) {
+        continue;
+      }
+      ColoredPrintf(COLOR_RED, "[  FAILED  ] ");
+      printf("%s.%s", test_case.name(), test_info.name());
+      PrintFullTestCommentIfPresent(test_info);
+      printf("\n");
+    }
+  }
+}
+
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                     int /*iteration*/) {
+  ColoredPrintf(COLOR_GREEN,  "[==========] ");
+  printf("%s from %s ran.",
+         FormatTestCount(unit_test.test_to_run_count()).c_str(),
+         FormatTestCaseCount(unit_test.test_case_to_run_count()).c_str());
+  if (GTEST_FLAG(print_time)) {
+    printf(" (%s ms total)",
+           internal::StreamableToString(unit_test.elapsed_time()).c_str());
+  }
+  printf("\n");
+  ColoredPrintf(COLOR_GREEN,  "[  PASSED  ] ");
+  printf("%s.\n", FormatTestCount(unit_test.successful_test_count()).c_str());
+
+  int num_failures = unit_test.failed_test_count();
+  if (!unit_test.Passed()) {
+    const int failed_test_count = unit_test.failed_test_count();
+    ColoredPrintf(COLOR_RED,  "[  FAILED  ] ");
+    printf("%s, listed below:\n", FormatTestCount(failed_test_count).c_str());
+    PrintFailedTests(unit_test);
+    printf("\n%2d FAILED %s\n", num_failures,
+                        num_failures == 1 ? "TEST" : "TESTS");
+  }
+
+  int num_disabled = unit_test.reportable_disabled_test_count();
+  if (num_disabled && !GTEST_FLAG(also_run_disabled_tests)) {
+    if (!num_failures) {
+      printf("\n");  // Add a spacer if no FAILURE banner is displayed.
+    }
+    ColoredPrintf(COLOR_YELLOW,
+                  "  YOU HAVE %d DISABLED %s\n\n",
+                  num_disabled,
+                  num_disabled == 1 ? "TEST" : "TESTS");
+  }
+  // Ensure that Google Test output is printed before, e.g., heapchecker output.
+  fflush(stdout);
+}
+
+// End PrettyUnitTestResultPrinter
+
+// class TestEventRepeater
+//
+// This class forwards events to other event listeners.
+class TestEventRepeater : public TestEventListener {
+ public:
+  TestEventRepeater() : forwarding_enabled_(true) {}
+  virtual ~TestEventRepeater();
+  void Append(TestEventListener *listener);
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled() const { return forwarding_enabled_; }
+  void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
+
+  virtual void OnTestProgramStart(const UnitTest& unit_test);
+  virtual void OnTestIterationStart(const UnitTest& unit_test, int iteration);
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test);
+  virtual void OnTestCaseStart(const TestCase& test_case);
+  virtual void OnTestStart(const TestInfo& test_info);
+  virtual void OnTestPartResult(const TestPartResult& result);
+  virtual void OnTestEnd(const TestInfo& test_info);
+  virtual void OnTestCaseEnd(const TestCase& test_case);
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test);
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test);
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+  virtual void OnTestProgramEnd(const UnitTest& unit_test);
+
+ private:
+  // Controls whether events will be forwarded to listeners_. Set to false
+  // in death test child processes.
+  bool forwarding_enabled_;
+  // The list of listeners that receive events.
+  std::vector<TestEventListener*> listeners_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventRepeater);
+};
+
+TestEventRepeater::~TestEventRepeater() {
+  ForEach(listeners_, Delete<TestEventListener>);
+}
+
+void TestEventRepeater::Append(TestEventListener *listener) {
+  listeners_.push_back(listener);
+}
+
+// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
+TestEventListener* TestEventRepeater::Release(TestEventListener *listener) {
+  for (size_t i = 0; i < listeners_.size(); ++i) {
+    if (listeners_[i] == listener) {
+      listeners_.erase(listeners_.begin() + i);
+      return listener;
+    }
+  }
+
+  return NULL;
+}
+
+// Since most methods are very similar, use macros to reduce boilerplate.
+// This defines a member that forwards the call to all listeners.
+#define GTEST_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (size_t i = 0; i < listeners_.size(); i++) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+// This defines a member that forwards the call to all listeners in reverse
+// order.
+#define GTEST_REVERSE_REPEATER_METHOD_(Name, Type) \
+void TestEventRepeater::Name(const Type& parameter) { \
+  if (forwarding_enabled_) { \
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) { \
+      listeners_[i]->Name(parameter); \
+    } \
+  } \
+}
+
+GTEST_REPEATER_METHOD_(OnTestProgramStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnEnvironmentsSetUpStart, UnitTest)
+GTEST_REPEATER_METHOD_(OnTestCaseStart, TestCase)
+GTEST_REPEATER_METHOD_(OnTestStart, TestInfo)
+GTEST_REPEATER_METHOD_(OnTestPartResult, TestPartResult)
+GTEST_REPEATER_METHOD_(OnEnvironmentsTearDownStart, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsSetUpEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnEnvironmentsTearDownEnd, UnitTest)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestEnd, TestInfo)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestCaseEnd, TestCase)
+GTEST_REVERSE_REPEATER_METHOD_(OnTestProgramEnd, UnitTest)
+
+#undef GTEST_REPEATER_METHOD_
+#undef GTEST_REVERSE_REPEATER_METHOD_
+
+void TestEventRepeater::OnTestIterationStart(const UnitTest& unit_test,
+                                             int iteration) {
+  if (forwarding_enabled_) {
+    for (size_t i = 0; i < listeners_.size(); i++) {
+      listeners_[i]->OnTestIterationStart(unit_test, iteration);
+    }
+  }
+}
+
+void TestEventRepeater::OnTestIterationEnd(const UnitTest& unit_test,
+                                           int iteration) {
+  if (forwarding_enabled_) {
+    for (int i = static_cast<int>(listeners_.size()) - 1; i >= 0; i--) {
+      listeners_[i]->OnTestIterationEnd(unit_test, iteration);
+    }
+  }
+}
+
+// End TestEventRepeater
+
+// This class generates an XML output file.
+class XmlUnitTestResultPrinter : public EmptyTestEventListener {
+ public:
+  explicit XmlUnitTestResultPrinter(const char* output_file);
+
+  virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration);
+
+ private:
+  // Is c a whitespace character that is normalized to a space character
+  // when it appears in an XML attribute value?
+  static bool IsNormalizableWhitespace(char c) {
+    return c == 0x9 || c == 0xA || c == 0xD;
+  }
+
+  // May c appear in a well-formed XML document?
+  static bool IsValidXmlCharacter(char c) {
+    return IsNormalizableWhitespace(c) || c >= 0x20;
+  }
+
+  // Returns an XML-escaped copy of the input string str.  If
+  // is_attribute is true, the text is meant to appear as an attribute
+  // value, and normalizable whitespace is preserved by replacing it
+  // with character references.
+  static std::string EscapeXml(const std::string& str, bool is_attribute);
+
+  // Returns the given string with all characters invalid in XML removed.
+  static std::string RemoveInvalidXmlCharacters(const std::string& str);
+
+  // Convenience wrapper around EscapeXml when str is an attribute value.
+  static std::string EscapeXmlAttribute(const std::string& str) {
+    return EscapeXml(str, true);
+  }
+
+  // Convenience wrapper around EscapeXml when str is not an attribute value.
+  static std::string EscapeXmlText(const char* str) {
+    return EscapeXml(str, false);
+  }
+
+  // Verifies that the given attribute belongs to the given element and
+  // streams the attribute as XML.
+  static void OutputXmlAttribute(std::ostream* stream,
+                                 const std::string& element_name,
+                                 const std::string& name,
+                                 const std::string& value);
+
+  // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+  static void OutputXmlCDataSection(::std::ostream* stream, const char* data);
+
+  // Streams an XML representation of a TestInfo object.
+  static void OutputXmlTestInfo(::std::ostream* stream,
+                                const char* test_case_name,
+                                const TestInfo& test_info);
+
+  // Prints an XML representation of a TestCase object
+  static void PrintXmlTestCase(::std::ostream* stream,
+                               const TestCase& test_case);
+
+  // Prints an XML summary of unit_test to output stream out.
+  static void PrintXmlUnitTest(::std::ostream* stream,
+                               const UnitTest& unit_test);
+
+  // Produces a string representing the test properties in a result as space
+  // delimited XML attributes based on the property key="value" pairs.
+  // When the std::string is not empty, it includes a space at the beginning,
+  // to delimit this attribute from prior attributes.
+  static std::string TestPropertiesAsXmlAttributes(const TestResult& result);
+
+  // The output file.
+  const std::string output_file_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
+};
+
+// Creates a new XmlUnitTestResultPrinter.
+XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
+    : output_file_(output_file) {
+  if (output_file_.c_str() == NULL || output_file_.empty()) {
+    fprintf(stderr, "XML output file may not be null\n");
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+}
+
+// Called after the unit test ends.
+void XmlUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+                                                  int /*iteration*/) {
+  FILE* xmlout = NULL;
+  FilePath output_file(output_file_);
+  FilePath output_dir(output_file.RemoveFileName());
+
+  if (output_dir.CreateDirectoriesRecursively()) {
+    xmlout = posix::FOpen(output_file_.c_str(), "w");
+  }
+  if (xmlout == NULL) {
+    // TODO(wan): report the reason of the failure.
+    //
+    // We don't do it for now as:
+    //
+    //   1. There is no urgent need for it.
+    //   2. It's a bit involved to make the errno variable thread-safe on
+    //      all three operating systems (Linux, Windows, and Mac OS).
+    //   3. To interpret the meaning of errno in a thread-safe way,
+    //      we need the strerror_r() function, which is not available on
+    //      Windows.
+    fprintf(stderr,
+            "Unable to open file \"%s\"\n",
+            output_file_.c_str());
+    fflush(stderr);
+    exit(EXIT_FAILURE);
+  }
+  std::stringstream stream;
+  PrintXmlUnitTest(&stream, unit_test);
+  fprintf(xmlout, "%s", StringStreamToString(&stream).c_str());
+  fclose(xmlout);
+}
+
+// Returns an XML-escaped copy of the input string str.  If is_attribute
+// is true, the text is meant to appear as an attribute value, and
+// normalizable whitespace is preserved by replacing it with character
+// references.
+//
+// Invalid XML characters in str, if any, are stripped from the output.
+// It is expected that most, if not all, of the text processed by this
+// module will consist of ordinary English text.
+// If this module is ever modified to produce version 1.1 XML output,
+// most invalid characters can be retained using character references.
+// TODO(wan): It might be nice to have a minimally invasive, human-readable
+// escaping scheme for invalid characters, rather than dropping them.
+std::string XmlUnitTestResultPrinter::EscapeXml(
+    const std::string& str, bool is_attribute) {
+  Message m;
+
+  for (size_t i = 0; i < str.size(); ++i) {
+    const char ch = str[i];
+    switch (ch) {
+      case '<':
+        m << "&lt;";
+        break;
+      case '>':
+        m << "&gt;";
+        break;
+      case '&':
+        m << "&amp;";
+        break;
+      case '\'':
+        if (is_attribute)
+          m << "&apos;";
+        else
+          m << '\'';
+        break;
+      case '"':
+        if (is_attribute)
+          m << "&quot;";
+        else
+          m << '"';
+        break;
+      default:
+        if (IsValidXmlCharacter(ch)) {
+          if (is_attribute && IsNormalizableWhitespace(ch))
+            m << "&#x" << String::FormatByte(static_cast<unsigned char>(ch))
+              << ";";
+          else
+            m << ch;
+        }
+        break;
+    }
+  }
+
+  return m.GetString();
+}
+
+// Returns the given string with all characters invalid in XML removed.
+// Currently invalid characters are dropped from the string. An
+// alternative is to replace them with certain characters such as . or ?.
+std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
+    const std::string& str) {
+  std::string output;
+  output.reserve(str.size());
+  for (std::string::const_iterator it = str.begin(); it != str.end(); ++it)
+    if (IsValidXmlCharacter(*it))
+      output.push_back(*it);
+
+  return output;
+}
+
+// The following routines generate an XML representation of a UnitTest
+// object.
+//
+// This is how Google Test concepts map to the DTD:
+//
+// <testsuites name="AllTests">        <-- corresponds to a UnitTest object
+//   <testsuite name="testcase-name">  <-- corresponds to a TestCase object
+//     <testcase name="test-name">     <-- corresponds to a TestInfo object
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//       <failure message="...">...</failure>
+//                                     <-- individual assertion failures
+//     </testcase>
+//   </testsuite>
+// </testsuites>
+
+// Formats the given time in milliseconds as seconds.
+std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
+  ::std::stringstream ss;
+  ss << ms/1000.0;
+  return ss.str();
+}
+
+// Converts the given epoch time in milliseconds to a date string in the ISO
+// 8601 format, without the timezone information.
+std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
+  // Using non-reentrant version as localtime_r is not portable.
+  time_t seconds = static_cast<time_t>(ms / 1000);
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4996)  // Temporarily disables warning 4996
+                                // (function or variable may be unsafe).
+  const struct tm* const time_struct = localtime(&seconds);  // NOLINT
+# pragma warning(pop)           // Restores the warning state again.
+#else
+  const struct tm* const time_struct = localtime(&seconds);  // NOLINT
+#endif
+  if (time_struct == NULL)
+    return "";  // Invalid ms value
+
+  // YYYY-MM-DDThh:mm:ss
+  return StreamableToString(time_struct->tm_year + 1900) + "-" +
+      String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" +
+      String::FormatIntWidth2(time_struct->tm_mday) + "T" +
+      String::FormatIntWidth2(time_struct->tm_hour) + ":" +
+      String::FormatIntWidth2(time_struct->tm_min) + ":" +
+      String::FormatIntWidth2(time_struct->tm_sec);
+}
+
+// Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
+void XmlUnitTestResultPrinter::OutputXmlCDataSection(::std::ostream* stream,
+                                                     const char* data) {
+  const char* segment = data;
+  *stream << "<![CDATA[";
+  for (;;) {
+    const char* const next_segment = strstr(segment, "]]>");
+    if (next_segment != NULL) {
+      stream->write(
+          segment, static_cast<std::streamsize>(next_segment - segment));
+      *stream << "]]>]]&gt;<![CDATA[";
+      segment = next_segment + strlen("]]>");
+    } else {
+      *stream << segment;
+      break;
+    }
+  }
+  *stream << "]]>";
+}
+
+void XmlUnitTestResultPrinter::OutputXmlAttribute(
+    std::ostream* stream,
+    const std::string& element_name,
+    const std::string& name,
+    const std::string& value) {
+  const std::vector<std::string>& allowed_names =
+      GetReservedAttributesForElement(element_name);
+
+  GTEST_CHECK_(std::find(allowed_names.begin(), allowed_names.end(), name) !=
+                   allowed_names.end())
+      << "Attribute " << name << " is not allowed for element <" << element_name
+      << ">.";
+
+  *stream << " " << name << "=\"" << EscapeXmlAttribute(value) << "\"";
+}
+
+// Prints an XML representation of a TestInfo object.
+// TODO(wan): There is also value in printing properties with the plain printer.
+void XmlUnitTestResultPrinter::OutputXmlTestInfo(::std::ostream* stream,
+                                                 const char* test_case_name,
+                                                 const TestInfo& test_info) {
+  const TestResult& result = *test_info.result();
+  const std::string kTestcase = "testcase";
+
+  *stream << "    <testcase";
+  OutputXmlAttribute(stream, kTestcase, "name", test_info.name());
+
+  if (test_info.value_param() != NULL) {
+    OutputXmlAttribute(stream, kTestcase, "value_param",
+                       test_info.value_param());
+  }
+  if (test_info.type_param() != NULL) {
+    OutputXmlAttribute(stream, kTestcase, "type_param", test_info.type_param());
+  }
+
+  OutputXmlAttribute(stream, kTestcase, "status",
+                     test_info.should_run() ? "run" : "notrun");
+  OutputXmlAttribute(stream, kTestcase, "time",
+                     FormatTimeInMillisAsSeconds(result.elapsed_time()));
+  OutputXmlAttribute(stream, kTestcase, "classname", test_case_name);
+  *stream << TestPropertiesAsXmlAttributes(result);
+
+  int failures = 0;
+  for (int i = 0; i < result.total_part_count(); ++i) {
+    const TestPartResult& part = result.GetTestPartResult(i);
+    if (part.failed()) {
+      if (++failures == 1) {
+        *stream << ">\n";
+      }
+      const string location = internal::FormatCompilerIndependentFileLocation(
+          part.file_name(), part.line_number());
+      const string summary = location + "\n" + part.summary();
+      *stream << "      <failure message=\""
+              << EscapeXmlAttribute(summary.c_str())
+              << "\" type=\"\">";
+      const string detail = location + "\n" + part.message();
+      OutputXmlCDataSection(stream, RemoveInvalidXmlCharacters(detail).c_str());
+      *stream << "</failure>\n";
+    }
+  }
+
+  if (failures == 0)
+    *stream << " />\n";
+  else
+    *stream << "    </testcase>\n";
+}
+
+// Prints an XML representation of a TestCase object
+void XmlUnitTestResultPrinter::PrintXmlTestCase(std::ostream* stream,
+                                                const TestCase& test_case) {
+  const std::string kTestsuite = "testsuite";
+  *stream << "  <" << kTestsuite;
+  OutputXmlAttribute(stream, kTestsuite, "name", test_case.name());
+  OutputXmlAttribute(stream, kTestsuite, "tests",
+                     StreamableToString(test_case.reportable_test_count()));
+  OutputXmlAttribute(stream, kTestsuite, "failures",
+                     StreamableToString(test_case.failed_test_count()));
+  OutputXmlAttribute(
+      stream, kTestsuite, "disabled",
+      StreamableToString(test_case.reportable_disabled_test_count()));
+  OutputXmlAttribute(stream, kTestsuite, "errors", "0");
+  OutputXmlAttribute(stream, kTestsuite, "time",
+                     FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
+  *stream << TestPropertiesAsXmlAttributes(test_case.ad_hoc_test_result())
+          << ">\n";
+
+  for (int i = 0; i < test_case.total_test_count(); ++i) {
+    if (test_case.GetTestInfo(i)->is_reportable())
+      OutputXmlTestInfo(stream, test_case.name(), *test_case.GetTestInfo(i));
+  }
+  *stream << "  </" << kTestsuite << ">\n";
+}
+
+// Prints an XML summary of unit_test to output stream out.
+void XmlUnitTestResultPrinter::PrintXmlUnitTest(std::ostream* stream,
+                                                const UnitTest& unit_test) {
+  const std::string kTestsuites = "testsuites";
+
+  *stream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+  *stream << "<" << kTestsuites;
+
+  OutputXmlAttribute(stream, kTestsuites, "tests",
+                     StreamableToString(unit_test.reportable_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "failures",
+                     StreamableToString(unit_test.failed_test_count()));
+  OutputXmlAttribute(
+      stream, kTestsuites, "disabled",
+      StreamableToString(unit_test.reportable_disabled_test_count()));
+  OutputXmlAttribute(stream, kTestsuites, "errors", "0");
+  OutputXmlAttribute(
+      stream, kTestsuites, "timestamp",
+      FormatEpochTimeInMillisAsIso8601(unit_test.start_timestamp()));
+  OutputXmlAttribute(stream, kTestsuites, "time",
+                     FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
+
+  if (GTEST_FLAG(shuffle)) {
+    OutputXmlAttribute(stream, kTestsuites, "random_seed",
+                       StreamableToString(unit_test.random_seed()));
+  }
+
+  *stream << TestPropertiesAsXmlAttributes(unit_test.ad_hoc_test_result());
+
+  OutputXmlAttribute(stream, kTestsuites, "name", "AllTests");
+  *stream << ">\n";
+
+  for (int i = 0; i < unit_test.total_test_case_count(); ++i) {
+    if (unit_test.GetTestCase(i)->reportable_test_count() > 0)
+      PrintXmlTestCase(stream, *unit_test.GetTestCase(i));
+  }
+  *stream << "</" << kTestsuites << ">\n";
+}
+
+// Produces a string representing the test properties in a result as space
+// delimited XML attributes based on the property key="value" pairs.
+std::string XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+    const TestResult& result) {
+  Message attributes;
+  for (int i = 0; i < result.test_property_count(); ++i) {
+    const TestProperty& property = result.GetTestProperty(i);
+    attributes << " " << property.key() << "="
+        << "\"" << EscapeXmlAttribute(property.value()) << "\"";
+  }
+  return attributes.GetString();
+}
+
+// End XmlUnitTestResultPrinter
+
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D".  This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+  string result;
+  result.reserve(strlen(str) + 1);
+  for (char ch = *str; ch != '\0'; ch = *++str) {
+    switch (ch) {
+      case '%':
+      case '=':
+      case '&':
+      case '\n':
+        result.append("%" + String::FormatByte(static_cast<unsigned char>(ch)));
+        break;
+      default:
+        result.push_back(ch);
+        break;
+    }
+  }
+  return result;
+}
+
+void StreamingListener::SocketWriter::MakeConnection() {
+  GTEST_CHECK_(sockfd_ == -1)
+      << "MakeConnection() can't be called when there is already a connection.";
+
+  addrinfo hints;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;    // To allow both IPv4 and IPv6 addresses.
+  hints.ai_socktype = SOCK_STREAM;
+  addrinfo* servinfo = NULL;
+
+  // Use the getaddrinfo() to get a linked list of IP addresses for
+  // the given host name.
+  const int error_num = getaddrinfo(
+      host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+  if (error_num != 0) {
+    GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+                        << gai_strerror(error_num);
+  }
+
+  // Loop through all the results and connect to the first we can.
+  for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+       cur_addr = cur_addr->ai_next) {
+    sockfd_ = socket(
+        cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+    if (sockfd_ != -1) {
+      // Connect the client socket to the server socket.
+      if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+        close(sockfd_);
+        sockfd_ = -1;
+      }
+    }
+  }
+
+  freeaddrinfo(servinfo);  // all done with this structure
+
+  if (sockfd_ == -1) {
+    GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+                        << host_name_ << ":" << port_num_;
+  }
+}
+
+// End of class Streaming Listener
+#endif  // GTEST_CAN_STREAM_RESULTS__
+
+// Class ScopedTrace
+
+// Pushes the given source file location and message onto a per-thread
+// trace stack maintained by Google Test.
+ScopedTrace::ScopedTrace(const char* file, int line, const Message& message)
+    GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+  TraceInfo trace;
+  trace.file = file;
+  trace.line = line;
+  trace.message = message.GetString();
+
+  UnitTest::GetInstance()->PushGTestTrace(trace);
+}
+
+// Pops the info pushed by the c'tor.
+ScopedTrace::~ScopedTrace()
+    GTEST_LOCK_EXCLUDED_(&UnitTest::mutex_) {
+  UnitTest::GetInstance()->PopGTestTrace();
+}
+
+
+// class OsStackTraceGetter
+
+// Returns the current OS stack trace as an std::string.  Parameters:
+//
+//   max_depth  - the maximum number of stack frames to be included
+//                in the trace.
+//   skip_count - the number of top frames to be skipped; doesn't count
+//                against max_depth.
+//
+string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */,
+                                             int /* skip_count */)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  return "";
+}
+
+void OsStackTraceGetter::UponLeavingGTest()
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+}
+
+const char* const
+OsStackTraceGetter::kElidedFramesMarker =
+    "... " GTEST_NAME_ " internal frames ...";
+
+// A helper class that creates the premature-exit file in its
+// constructor and deletes the file in its destructor.
+class ScopedPrematureExitFile {
+ public:
+  explicit ScopedPrematureExitFile(const char* premature_exit_filepath)
+      : premature_exit_filepath_(premature_exit_filepath) {
+    // If a path to the premature-exit file is specified...
+    if (premature_exit_filepath != NULL && *premature_exit_filepath != '\0') {
+      // create the file with a single "0" character in it.  I/O
+      // errors are ignored as there's nothing better we can do and we
+      // don't want to fail the test because of this.
+      FILE* pfile = posix::FOpen(premature_exit_filepath, "w");
+      fwrite("0", 1, 1, pfile);
+      fclose(pfile);
+    }
+  }
+
+  ~ScopedPrematureExitFile() {
+    if (premature_exit_filepath_ != NULL && *premature_exit_filepath_ != '\0') {
+      remove(premature_exit_filepath_);
+    }
+  }
+
+ private:
+  const char* const premature_exit_filepath_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedPrematureExitFile);
+};
+
+}  // namespace internal
+
+// class TestEventListeners
+
+TestEventListeners::TestEventListeners()
+    : repeater_(new internal::TestEventRepeater()),
+      default_result_printer_(NULL),
+      default_xml_generator_(NULL) {
+}
+
+TestEventListeners::~TestEventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output.  Can be removed from the listeners list to shut down default
+// console output.  Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void TestEventListeners::Append(TestEventListener* listener) {
+  repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it.  It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+TestEventListener* TestEventListeners::Release(TestEventListener* listener) {
+  if (listener == default_result_printer_)
+    default_result_printer_ = NULL;
+  else if (listener == default_xml_generator_)
+    default_xml_generator_ = NULL;
+  return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the TestEventListener events to all
+// subscribers.
+TestEventListener* TestEventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultResultPrinter(TestEventListener* listener) {
+  if (default_result_printer_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_result_printer_);
+    default_result_printer_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Sets the default_xml_generator attribute to the provided listener.  The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void TestEventListeners::SetDefaultXmlGenerator(TestEventListener* listener) {
+  if (default_xml_generator_ != listener) {
+    // It is an error to pass this method a listener that is already in the
+    // list.
+    delete Release(default_xml_generator_);
+    default_xml_generator_ = listener;
+    if (listener != NULL)
+      Append(listener);
+  }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool TestEventListeners::EventForwardingEnabled() const {
+  return repeater_->forwarding_enabled();
+}
+
+void TestEventListeners::SuppressEventForwarding() {
+  repeater_->set_forwarding_enabled(false);
+}
+
+// class UnitTest
+
+// Gets the singleton UnitTest object.  The first time this method is
+// called, a UnitTest object is constructed and returned.  Consecutive
+// calls will return the same object.
+//
+// We don't protect this under mutex_ as a user is not supposed to
+// call this before main() starts, from which point on the return
+// value will never change.
+UnitTest* UnitTest::GetInstance() {
+  // When compiled with MSVC 7.1 in optimized mode, destroying the
+  // UnitTest object upon exiting the program messes up the exit code,
+  // causing successful tests to appear failed.  We have to use a
+  // different implementation in this case to bypass the compiler bug.
+  // This implementation makes the compiler happy, at the cost of
+  // leaking the UnitTest object.
+
+  // CodeGear C++Builder insists on a public destructor for the
+  // default implementation.  Use this implementation to keep good OO
+  // design with private destructor.
+
+#if (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+  static UnitTest* const instance = new UnitTest;
+  return instance;
+#else
+  static UnitTest instance;
+  return &instance;
+#endif  // (_MSC_VER == 1310 && !defined(_DEBUG)) || defined(__BORLANDC__)
+}
+
+// Gets the number of successful test cases.
+int UnitTest::successful_test_case_count() const {
+  return impl()->successful_test_case_count();
+}
+
+// Gets the number of failed test cases.
+int UnitTest::failed_test_case_count() const {
+  return impl()->failed_test_case_count();
+}
+
+// Gets the number of all test cases.
+int UnitTest::total_test_case_count() const {
+  return impl()->total_test_case_count();
+}
+
+// Gets the number of all test cases that contain at least one test
+// that should run.
+int UnitTest::test_case_to_run_count() const {
+  return impl()->test_case_to_run_count();
+}
+
+// Gets the number of successful tests.
+int UnitTest::successful_test_count() const {
+  return impl()->successful_test_count();
+}
+
+// Gets the number of failed tests.
+int UnitTest::failed_test_count() const { return impl()->failed_test_count(); }
+
+// Gets the number of disabled tests that will be reported in the XML report.
+int UnitTest::reportable_disabled_test_count() const {
+  return impl()->reportable_disabled_test_count();
+}
+
+// Gets the number of disabled tests.
+int UnitTest::disabled_test_count() const {
+  return impl()->disabled_test_count();
+}
+
+// Gets the number of tests to be printed in the XML report.
+int UnitTest::reportable_test_count() const {
+  return impl()->reportable_test_count();
+}
+
+// Gets the number of all tests.
+int UnitTest::total_test_count() const { return impl()->total_test_count(); }
+
+// Gets the number of tests that should run.
+int UnitTest::test_to_run_count() const { return impl()->test_to_run_count(); }
+
+// Gets the time of the test program start, in ms from the start of the
+// UNIX epoch.
+internal::TimeInMillis UnitTest::start_timestamp() const {
+    return impl()->start_timestamp();
+}
+
+// Gets the elapsed time, in milliseconds.
+internal::TimeInMillis UnitTest::elapsed_time() const {
+  return impl()->elapsed_time();
+}
+
+// Returns true iff the unit test passed (i.e. all test cases passed).
+bool UnitTest::Passed() const { return impl()->Passed(); }
+
+// Returns true iff the unit test failed (i.e. some test case failed
+// or something outside of all tests failed).
+bool UnitTest::Failed() const { return impl()->Failed(); }
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+const TestCase* UnitTest::GetTestCase(int i) const {
+  return impl()->GetTestCase(i);
+}
+
+// Returns the TestResult containing information on test failures and
+// properties logged outside of individual test cases.
+const TestResult& UnitTest::ad_hoc_test_result() const {
+  return *impl()->ad_hoc_test_result();
+}
+
+// Gets the i-th test case among all the test cases. i can range from 0 to
+// total_test_case_count() - 1. If i is not in that range, returns NULL.
+TestCase* UnitTest::GetMutableTestCase(int i) {
+  return impl()->GetMutableTestCase(i);
+}
+
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+TestEventListeners& UnitTest::listeners() {
+  return *impl()->listeners();
+}
+
+// Registers and returns a global test environment.  When a test
+// program is run, all global test environments will be set-up in the
+// order they were registered.  After all tests in the program have
+// finished, all global test environments will be torn-down in the
+// *reverse* order they were registered.
+//
+// The UnitTest object takes ownership of the given environment.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+Environment* UnitTest::AddEnvironment(Environment* env) {
+  if (env == NULL) {
+    return NULL;
+  }
+
+  impl_->environments().push_back(env);
+  return env;
+}
+
+// Adds a TestPartResult to the current TestResult object.  All Google Test
+// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
+// this to report their results.  The user code should use the
+// assertion macros instead of calling this directly.
+void UnitTest::AddTestPartResult(
+    TestPartResult::Type result_type,
+    const char* file_name,
+    int line_number,
+    const std::string& message,
+    const std::string& os_stack_trace) GTEST_LOCK_EXCLUDED_(mutex_) {
+  Message msg;
+  msg << message;
+
+  internal::MutexLock lock(&mutex_);
+  if (impl_->gtest_trace_stack().size() > 0) {
+    msg << "\n" << GTEST_NAME_ << " trace:";
+
+    for (int i = static_cast<int>(impl_->gtest_trace_stack().size());
+         i > 0; --i) {
+      const internal::TraceInfo& trace = impl_->gtest_trace_stack()[i - 1];
+      msg << "\n" << internal::FormatFileLocation(trace.file, trace.line)
+          << " " << trace.message;
+    }
+  }
+
+  if (os_stack_trace.c_str() != NULL && !os_stack_trace.empty()) {
+    msg << internal::kStackTraceMarker << os_stack_trace;
+  }
+
+  const TestPartResult result =
+    TestPartResult(result_type, file_name, line_number,
+                   msg.GetString().c_str());
+  impl_->GetTestPartResultReporterForCurrentThread()->
+      ReportTestPartResult(result);
+
+  if (result_type != TestPartResult::kSuccess) {
+    // gtest_break_on_failure takes precedence over
+    // gtest_throw_on_failure.  This allows a user to set the latter
+    // in the code (perhaps in order to use Google Test assertions
+    // with another testing framework) and specify the former on the
+    // command line for debugging.
+    if (GTEST_FLAG(break_on_failure)) {
+#if GTEST_OS_WINDOWS
+      // Using DebugBreak on Windows allows gtest to still break into a debugger
+      // when a failure happens and both the --gtest_break_on_failure and
+      // the --gtest_catch_exceptions flags are specified.
+      DebugBreak();
+#else
+      // Dereference NULL through a volatile pointer to prevent the compiler
+      // from removing. We use this rather than abort() or __builtin_trap() for
+      // portability: Symbian doesn't implement abort() well, and some debuggers
+      // don't correctly trap abort().
+      *static_cast<volatile int*>(NULL) = 1;
+#endif  // GTEST_OS_WINDOWS
+    } else if (GTEST_FLAG(throw_on_failure)) {
+#if GTEST_HAS_EXCEPTIONS
+      throw internal::GoogleTestFailureException(result);
+#else
+      // We cannot call abort() as it generates a pop-up in debug mode
+      // that cannot be suppressed in VC 7.1 or below.
+      exit(1);
+#endif
+    }
+  }
+}
+
+// Adds a TestProperty to the current TestResult object when invoked from
+// inside a test, to current TestCase's ad_hoc_test_result_ when invoked
+// from SetUpTestCase or TearDownTestCase, or to the global property set
+// when invoked elsewhere.  If the result already contains a property with
+// the same key, the value will be updated.
+void UnitTest::RecordProperty(const std::string& key,
+                              const std::string& value) {
+  impl_->RecordProperty(TestProperty(key, value));
+}
+
+// Runs all tests in this UnitTest object and prints the result.
+// Returns 0 if successful, or 1 otherwise.
+//
+// We don't protect this under mutex_, as we only support calling it
+// from the main thread.
+int UnitTest::Run() {
+  const bool in_death_test_child_process =
+      internal::GTEST_FLAG(internal_run_death_test).length() > 0;
+
+  // Google Test implements this protocol for catching that a test
+  // program exits before returning control to Google Test:
+  //
+  //   1. Upon start, Google Test creates a file whose absolute path
+  //      is specified by the environment variable
+  //      TEST_PREMATURE_EXIT_FILE.
+  //   2. When Google Test has finished its work, it deletes the file.
+  //
+  // This allows a test runner to set TEST_PREMATURE_EXIT_FILE before
+  // running a Google-Test-based test program and check the existence
+  // of the file at the end of the test execution to see if it has
+  // exited prematurely.
+
+  // If we are in the child process of a death test, don't
+  // create/delete the premature exit file, as doing so is unnecessary
+  // and will confuse the parent process.  Otherwise, create/delete
+  // the file upon entering/leaving this function.  If the program
+  // somehow exits before this function has a chance to return, the
+  // premature-exit file will be left undeleted, causing a test runner
+  // that understands the premature-exit-file protocol to report the
+  // test as having failed.
+  const internal::ScopedPrematureExitFile premature_exit_file(
+      in_death_test_child_process ?
+      NULL : internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));
+
+  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
+  // used for the duration of the program.
+  impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+
+#if GTEST_HAS_SEH
+  // Either the user wants Google Test to catch exceptions thrown by the
+  // tests or this is executing in the context of death test child
+  // process. In either case the user does not want to see pop-up dialogs
+  // about crashes - they are expected.
+  if (impl()->catch_exceptions() || in_death_test_child_process) {
+# if !GTEST_OS_WINDOWS_MOBILE
+    // SetErrorMode doesn't exist on CE.
+    SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
+                 SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
+# endif  // !GTEST_OS_WINDOWS_MOBILE
+
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+    // Death test children can be terminated with _abort().  On Windows,
+    // _abort() can show a dialog with a warning message.  This forces the
+    // abort message to go to stderr instead.
+    _set_error_mode(_OUT_TO_STDERR);
+# endif
+
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+    // In the debug version, Visual Studio pops up a separate dialog
+    // offering a choice to debug the aborted program. We need to suppress
+    // this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
+    // executed. Google Test will notify the user of any unexpected
+    // failure via stderr.
+    //
+    // VC++ doesn't define _set_abort_behavior() prior to the version 8.0.
+    // Users of prior VC versions shall suffer the agony and pain of
+    // clicking through the countless debug dialogs.
+    // TODO(vladl@google.com): find a way to suppress the abort dialog() in the
+    // debug mode when compiled with VC 7.1 or lower.
+    if (!GTEST_FLAG(break_on_failure))
+      _set_abort_behavior(
+          0x0,                                    // Clear the following flags:
+          _WRITE_ABORT_MSG | _CALL_REPORTFAULT);  // pop-up window, core dump.
+# endif
+  }
+#endif  // GTEST_HAS_SEH
+
+  return internal::HandleExceptionsInMethodIfSupported(
+      impl(),
+      &internal::UnitTestImpl::RunAllTests,
+      "auxiliary test code (environments or event listeners)") ? 0 : 1;
+}
+
+// Returns the working directory when the first TEST() or TEST_F() was
+// executed.
+const char* UnitTest::original_working_dir() const {
+  return impl_->original_working_dir_.c_str();
+}
+
+// Returns the TestCase object for the test that's currently running,
+// or NULL if no test is running.
+const TestCase* UnitTest::current_test_case() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_case();
+}
+
+// Returns the TestInfo object for the test that's currently running,
+// or NULL if no test is running.
+const TestInfo* UnitTest::current_test_info() const
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  return impl_->current_test_info();
+}
+
+// Returns the random seed used at the start of the current test run.
+int UnitTest::random_seed() const { return impl_->random_seed(); }
+
+#if GTEST_HAS_PARAM_TEST
+// Returns ParameterizedTestCaseRegistry object used to keep track of
+// value-parameterized tests and instantiate and register them.
+internal::ParameterizedTestCaseRegistry&
+    UnitTest::parameterized_test_registry()
+        GTEST_LOCK_EXCLUDED_(mutex_) {
+  return impl_->parameterized_test_registry();
+}
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Creates an empty UnitTest.
+UnitTest::UnitTest() {
+  impl_ = new internal::UnitTestImpl(this);
+}
+
+// Destructor of UnitTest.
+UnitTest::~UnitTest() {
+  delete impl_;
+}
+
+// Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+// Google Test trace stack.
+void UnitTest::PushGTestTrace(const internal::TraceInfo& trace)
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().push_back(trace);
+}
+
+// Pops a trace from the per-thread Google Test trace stack.
+void UnitTest::PopGTestTrace()
+    GTEST_LOCK_EXCLUDED_(mutex_) {
+  internal::MutexLock lock(&mutex_);
+  impl_->gtest_trace_stack().pop_back();
+}
+
+namespace internal {
+
+UnitTestImpl::UnitTestImpl(UnitTest* parent)
+    : parent_(parent),
+#ifdef _MSC_VER
+# pragma warning(push)                    // Saves the current warning state.
+# pragma warning(disable:4355)            // Temporarily disables warning 4355
+                                         // (using this in initializer).
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+# pragma warning(pop)                     // Restores the warning state again.
+#else
+      default_global_test_part_result_reporter_(this),
+      default_per_thread_test_part_result_reporter_(this),
+#endif  // _MSC_VER
+      global_test_part_result_repoter_(
+          &default_global_test_part_result_reporter_),
+      per_thread_test_part_result_reporter_(
+          &default_per_thread_test_part_result_reporter_),
+#if GTEST_HAS_PARAM_TEST
+      parameterized_test_registry_(),
+      parameterized_tests_registered_(false),
+#endif  // GTEST_HAS_PARAM_TEST
+      last_death_test_case_(-1),
+      current_test_case_(NULL),
+      current_test_info_(NULL),
+      ad_hoc_test_result_(),
+      os_stack_trace_getter_(NULL),
+      post_flag_parse_init_performed_(false),
+      random_seed_(0),  // Will be overridden by the flag before first use.
+      random_(0),  // Will be reseeded before first use.
+      start_timestamp_(0),
+      elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
+      death_test_factory_(new DefaultDeathTestFactory),
+#endif
+      // Will be overridden by the flag before first use.
+      catch_exceptions_(false) {
+  listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
+}
+
+UnitTestImpl::~UnitTestImpl() {
+  // Deletes every TestCase.
+  ForEach(test_cases_, internal::Delete<TestCase>);
+
+  // Deletes every Environment.
+  ForEach(environments_, internal::Delete<Environment>);
+
+  delete os_stack_trace_getter_;
+}
+
+// Adds a TestProperty to the current TestResult object when invoked in a
+// context of a test, to current test case's ad_hoc_test_result when invoke
+// from SetUpTestCase/TearDownTestCase, or to the global property set
+// otherwise.  If the result already contains a property with the same key,
+// the value will be updated.
+void UnitTestImpl::RecordProperty(const TestProperty& test_property) {
+  std::string xml_element;
+  TestResult* test_result;  // TestResult appropriate for property recording.
+
+  if (current_test_info_ != NULL) {
+    xml_element = "testcase";
+    test_result = &(current_test_info_->result_);
+  } else if (current_test_case_ != NULL) {
+    xml_element = "testsuite";
+    test_result = &(current_test_case_->ad_hoc_test_result_);
+  } else {
+    xml_element = "testsuites";
+    test_result = &ad_hoc_test_result_;
+  }
+  test_result->RecordProperty(xml_element, test_property);
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+  if (internal_run_death_test_flag_.get() != NULL)
+    listeners()->SuppressEventForwarding();
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+  const std::string& output_format = UnitTestOptions::GetOutputFormat();
+  if (output_format == "xml") {
+    listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+        UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+  } else if (output_format != "") {
+    printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+           output_format.c_str());
+    fflush(stdout);
+  }
+}
+
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in string form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+  const std::string& target = GTEST_FLAG(stream_result_to);
+  if (!target.empty()) {
+    const size_t pos = target.find(':');
+    if (pos != std::string::npos) {
+      listeners()->Append(new StreamingListener(target.substr(0, pos),
+                                                target.substr(pos+1)));
+    } else {
+      printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+             target.c_str());
+      fflush(stdout);
+    }
+  }
+}
+#endif  // GTEST_CAN_STREAM_RESULTS_
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly.  Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly.  In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests.  Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+  // Ensures that this function does not execute more than once.
+  if (!post_flag_parse_init_performed_) {
+    post_flag_parse_init_performed_ = true;
+
+#if GTEST_HAS_DEATH_TEST
+    InitDeathTestSubprocessControlInfo();
+    SuppressTestEventsIfInSubprocess();
+#endif  // GTEST_HAS_DEATH_TEST
+
+    // Registers parameterized tests. This makes parameterized tests
+    // available to the UnitTest reflection API without running
+    // RUN_ALL_TESTS.
+    RegisterParameterizedTests();
+
+    // Configures listeners for XML output. This makes it possible for users
+    // to shut down the default XML output before invoking RUN_ALL_TESTS.
+    ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+    // Configures listeners for streaming test results to the specified server.
+    ConfigureStreamingOutput();
+#endif  // GTEST_CAN_STREAM_RESULTS_
+  }
+}
+
+// A predicate that checks the name of a TestCase against a known
+// value.
+//
+// This is used for implementation of the UnitTest class only.  We put
+// it in the anonymous namespace to prevent polluting the outer
+// namespace.
+//
+// TestCaseNameIs is copyable.
+class TestCaseNameIs {
+ public:
+  // Constructor.
+  explicit TestCaseNameIs(const std::string& name)
+      : name_(name) {}
+
+  // Returns true iff the name of test_case matches name_.
+  bool operator()(const TestCase* test_case) const {
+    return test_case != NULL && strcmp(test_case->name(), name_.c_str()) == 0;
+  }
+
+ private:
+  std::string name_;
+};
+
+// Finds and returns a TestCase with the given name.  If one doesn't
+// exist, creates one and returns it.  It's the CALLER'S
+// RESPONSIBILITY to ensure that this function is only called WHEN THE
+// TESTS ARE NOT SHUFFLED.
+//
+// Arguments:
+//
+//   test_case_name: name of the test case
+//   type_param:     the name of the test case's type parameter, or NULL if
+//                   this is not a typed or a type-parameterized test case.
+//   set_up_tc:      pointer to the function that sets up the test case
+//   tear_down_tc:   pointer to the function that tears down the test case
+TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
+                                    const char* type_param,
+                                    Test::SetUpTestCaseFunc set_up_tc,
+                                    Test::TearDownTestCaseFunc tear_down_tc) {
+  // Can we find a TestCase with the given name?
+  const std::vector<TestCase*>::const_iterator test_case =
+      std::find_if(test_cases_.begin(), test_cases_.end(),
+                   TestCaseNameIs(test_case_name));
+
+  if (test_case != test_cases_.end())
+    return *test_case;
+
+  // No.  Let's create one.
+  TestCase* const new_test_case =
+      new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
+
+  // Is this a death test case?
+  if (internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                               kDeathTestCaseFilter)) {
+    // Yes.  Inserts the test case after the last death test case
+    // defined so far.  This only works when the test cases haven't
+    // been shuffled.  Otherwise we may end up running a death test
+    // after a non-death test.
+    ++last_death_test_case_;
+    test_cases_.insert(test_cases_.begin() + last_death_test_case_,
+                       new_test_case);
+  } else {
+    // No.  Appends to the end of the list.
+    test_cases_.push_back(new_test_case);
+  }
+
+  test_case_indices_.push_back(static_cast<int>(test_case_indices_.size()));
+  return new_test_case;
+}
+
+// Helpers for setting up / tearing down the given environment.  They
+// are for use in the ForEach() function.
+static void SetUpEnvironment(Environment* env) { env->SetUp(); }
+static void TearDownEnvironment(Environment* env) { env->TearDown(); }
+
+// Runs all tests in this UnitTest object, prints the result, and
+// returns true if all tests are successful.  If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
+// When parameterized tests are enabled, it expands and registers
+// parameterized tests first in RegisterParameterizedTests().
+// All other functions called from RunAllTests() may safely assume that
+// parameterized tests are ready to be counted and run.
+bool UnitTestImpl::RunAllTests() {
+  // Makes sure InitGoogleTest() was called.
+  if (!GTestIsInitialized()) {
+    printf("%s",
+           "\nThis test program did NOT call ::testing::InitGoogleTest "
+           "before calling RUN_ALL_TESTS().  Please fix it.\n");
+    return false;
+  }
+
+  // Do not run any test if the --help flag was specified.
+  if (g_help_flag)
+    return true;
+
+  // Repeats the call to the post-flag parsing initialization in case the
+  // user didn't call InitGoogleTest.
+  PostFlagParsingInit();
+
+  // Even if sharding is not on, test runners may want to use the
+  // GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
+  // protocol.
+  internal::WriteToShardStatusFileIfNeeded();
+
+  // True iff we are in a subprocess for running a thread-safe-style
+  // death test.
+  bool in_subprocess_for_death_test = false;
+
+#if GTEST_HAS_DEATH_TEST
+  in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
+#endif  // GTEST_HAS_DEATH_TEST
+
+  const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
+                                        in_subprocess_for_death_test);
+
+  // Compares the full test names with the filter to decide which
+  // tests to run.
+  const bool has_tests_to_run = FilterTests(should_shard
+                                              ? HONOR_SHARDING_PROTOCOL
+                                              : IGNORE_SHARDING_PROTOCOL) > 0;
+
+  // Lists the tests and exits if the --gtest_list_tests flag was specified.
+  if (GTEST_FLAG(list_tests)) {
+    // This must be called *after* FilterTests() has been called.
+    ListTestsMatchingFilter();
+    return true;
+  }
+
+  random_seed_ = GTEST_FLAG(shuffle) ?
+      GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;
+
+  // True iff at least one test has failed.
+  bool failed = false;
+
+  TestEventListener* repeater = listeners()->repeater();
+
+  start_timestamp_ = GetTimeInMillis();
+  repeater->OnTestProgramStart(*parent_);
+
+  // How many times to repeat the tests?  We don't want to repeat them
+  // when we are inside the subprocess of a death test.
+  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
+  // Repeats forever if the repeat count is negative.
+  const bool forever = repeat < 0;
+  for (int i = 0; forever || i != repeat; i++) {
+    // We want to preserve failures generated by ad-hoc test
+    // assertions executed before RUN_ALL_TESTS().
+    ClearNonAdHocTestResult();
+
+    const TimeInMillis start = GetTimeInMillis();
+
+    // Shuffles test cases and tests if requested.
+    if (has_tests_to_run && GTEST_FLAG(shuffle)) {
+      random()->Reseed(random_seed_);
+      // This should be done before calling OnTestIterationStart(),
+      // such that a test event listener can see the actual test order
+      // in the event.
+      ShuffleTests();
+    }
+
+    // Tells the unit test event listeners that the tests are about to start.
+    repeater->OnTestIterationStart(*parent_, i);
+
+    // Runs each test case if there is at least one test to run.
+    if (has_tests_to_run) {
+      // Sets up all environments beforehand.
+      repeater->OnEnvironmentsSetUpStart(*parent_);
+      ForEach(environments_, SetUpEnvironment);
+      repeater->OnEnvironmentsSetUpEnd(*parent_);
+
+      // Runs the tests only if there was no fatal failure during global
+      // set-up.
+      if (!Test::HasFatalFailure()) {
+        for (int test_index = 0; test_index < total_test_case_count();
+             test_index++) {
+          GetMutableTestCase(test_index)->Run();
+        }
+      }
+
+      // Tears down all environments in reverse order afterwards.
+      repeater->OnEnvironmentsTearDownStart(*parent_);
+      std::for_each(environments_.rbegin(), environments_.rend(),
+                    TearDownEnvironment);
+      repeater->OnEnvironmentsTearDownEnd(*parent_);
+    }
+
+    elapsed_time_ = GetTimeInMillis() - start;
+
+    // Tells the unit test event listener that the tests have just finished.
+    repeater->OnTestIterationEnd(*parent_, i);
+
+    // Gets the result and clears it.
+    if (!Passed()) {
+      failed = true;
+    }
+
+    // Restores the original test order after the iteration.  This
+    // allows the user to quickly repro a failure that happens in the
+    // N-th iteration without repeating the first (N - 1) iterations.
+    // This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in
+    // case the user somehow changes the value of the flag somewhere
+    // (it's always safe to unshuffle the tests).
+    UnshuffleTests();
+
+    if (GTEST_FLAG(shuffle)) {
+      // Picks a new random seed for each iteration.
+      random_seed_ = GetNextRandomSeed(random_seed_);
+    }
+  }
+
+  repeater->OnTestProgramEnd(*parent_);
+
+  return !failed;
+}
+
+// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
+// if the variable is present. If a file already exists at this location, this
+// function will write over it. If the variable is present, but the file cannot
+// be created, prints an error and exits.
+void WriteToShardStatusFileIfNeeded() {
+  const char* const test_shard_file = posix::GetEnv(kTestShardStatusFile);
+  if (test_shard_file != NULL) {
+    FILE* const file = posix::FOpen(test_shard_file, "w");
+    if (file == NULL) {
+      ColoredPrintf(COLOR_RED,
+                    "Could not write to the test shard status file \"%s\" "
+                    "specified by the %s environment variable.\n",
+                    test_shard_file, kTestShardStatusFile);
+      fflush(stdout);
+      exit(EXIT_FAILURE);
+    }
+    fclose(file);
+  }
+}
+
+// Checks whether sharding is enabled by examining the relevant
+// environment variable values. If the variables are present,
+// but inconsistent (i.e., shard_index >= total_shards), prints
+// an error and exits. If in_subprocess_for_death_test, sharding is
+// disabled because it must only be applied to the original test
+// process. Otherwise, we could filter out death tests we intended to execute.
+bool ShouldShard(const char* total_shards_env,
+                 const char* shard_index_env,
+                 bool in_subprocess_for_death_test) {
+  if (in_subprocess_for_death_test) {
+    return false;
+  }
+
+  const Int32 total_shards = Int32FromEnvOrDie(total_shards_env, -1);
+  const Int32 shard_index = Int32FromEnvOrDie(shard_index_env, -1);
+
+  if (total_shards == -1 && shard_index == -1) {
+    return false;
+  } else if (total_shards == -1 && shard_index != -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestShardIndex << " = " << shard_index
+      << ", but have left " << kTestTotalShards << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (total_shards != -1 && shard_index == -1) {
+    const Message msg = Message()
+      << "Invalid environment variables: you have "
+      << kTestTotalShards << " = " << total_shards
+      << ", but have left " << kTestShardIndex << " unset.\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  } else if (shard_index < 0 || shard_index >= total_shards) {
+    const Message msg = Message()
+      << "Invalid environment variables: we require 0 <= "
+      << kTestShardIndex << " < " << kTestTotalShards
+      << ", but you have " << kTestShardIndex << "=" << shard_index
+      << ", " << kTestTotalShards << "=" << total_shards << ".\n";
+    ColoredPrintf(COLOR_RED, msg.GetString().c_str());
+    fflush(stdout);
+    exit(EXIT_FAILURE);
+  }
+
+  return total_shards > 1;
+}
+
+// Parses the environment variable var as an Int32. If it is unset,
+// returns default_val. If it is not an Int32, prints an error
+// and aborts.
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
+  const char* str_val = posix::GetEnv(var);
+  if (str_val == NULL) {
+    return default_val;
+  }
+
+  Int32 result;
+  if (!ParseInt32(Message() << "The value of environment variable " << var,
+                  str_val, &result)) {
+    exit(EXIT_FAILURE);
+  }
+  return result;
+}
+
+// Given the total number of shards, the shard index, and the test id,
+// returns true iff the test should be run on this shard. The test id is
+// some arbitrary but unique non-negative integer assigned to each test
+// method. Assumes that 0 <= shard_index < total_shards.
+bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
+  return (test_id % total_shards) == shard_index;
+}
+
+// Compares the name of each test with the user-specified filter to
+// decide whether the test should be run, then records the result in
+// each TestCase and TestInfo object.
+// If shard_tests == true, further filters tests based on sharding
+// variables in the environment - see
+// http://code.google.com/p/googletest/wiki/GoogleTestAdvancedGuide.
+// Returns the number of tests that should run.
+int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
+  const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
+  const Int32 shard_index = shard_tests == HONOR_SHARDING_PROTOCOL ?
+      Int32FromEnvOrDie(kTestShardIndex, -1) : -1;
+
+  // num_runnable_tests are the number of tests that will
+  // run across all shards (i.e., match filter and are not disabled).
+  // num_selected_tests are the number of tests to be run on
+  // this shard.
+  int num_runnable_tests = 0;
+  int num_selected_tests = 0;
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    TestCase* const test_case = test_cases_[i];
+    const std::string &test_case_name = test_case->name();
+    test_case->set_should_run(false);
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      TestInfo* const test_info = test_case->test_info_list()[j];
+      const std::string test_name(test_info->name());
+      // A test is disabled if test case name or test name matches
+      // kDisableTestFilter.
+      const bool is_disabled =
+          internal::UnitTestOptions::MatchesFilter(test_case_name,
+                                                   kDisableTestFilter) ||
+          internal::UnitTestOptions::MatchesFilter(test_name,
+                                                   kDisableTestFilter);
+      test_info->is_disabled_ = is_disabled;
+
+      const bool matches_filter =
+          internal::UnitTestOptions::FilterMatchesTest(test_case_name,
+                                                       test_name);
+      test_info->matches_filter_ = matches_filter;
+
+      const bool is_runnable =
+          (GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
+          matches_filter;
+
+      const bool is_selected = is_runnable &&
+          (shard_tests == IGNORE_SHARDING_PROTOCOL ||
+           ShouldRunTestOnShard(total_shards, shard_index,
+                                num_runnable_tests));
+
+      num_runnable_tests += is_runnable;
+      num_selected_tests += is_selected;
+
+      test_info->should_run_ = is_selected;
+      test_case->set_should_run(test_case->should_run() || is_selected);
+    }
+  }
+  return num_selected_tests;
+}
+
+// Prints the given C-string on a single line by replacing all '\n'
+// characters with string "\\n".  If the output takes more than
+// max_length characters, only prints the first max_length characters
+// and "...".
+static void PrintOnOneLine(const char* str, int max_length) {
+  if (str != NULL) {
+    for (int i = 0; *str != '\0'; ++str) {
+      if (i >= max_length) {
+        printf("...");
+        break;
+      }
+      if (*str == '\n') {
+        printf("\\n");
+        i += 2;
+      } else {
+        printf("%c", *str);
+        ++i;
+      }
+    }
+  }
+}
+
+// Prints the names of the tests matching the user-specified filter flag.
+void UnitTestImpl::ListTestsMatchingFilter() {
+  // Print at most this many characters for each type/value parameter.
+  const int kMaxParamLength = 250;
+
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    const TestCase* const test_case = test_cases_[i];
+    bool printed_test_case_name = false;
+
+    for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
+      const TestInfo* const test_info =
+          test_case->test_info_list()[j];
+      if (test_info->matches_filter_) {
+        if (!printed_test_case_name) {
+          printed_test_case_name = true;
+          printf("%s.", test_case->name());
+          if (test_case->type_param() != NULL) {
+            printf("  # %s = ", kTypeParamLabel);
+            // We print the type parameter on a single line to make
+            // the output easy to parse by a program.
+            PrintOnOneLine(test_case->type_param(), kMaxParamLength);
+          }
+          printf("\n");
+        }
+        printf("  %s", test_info->name());
+        if (test_info->value_param() != NULL) {
+          printf("  # %s = ", kValueParamLabel);
+          // We print the value parameter on a single line to make the
+          // output easy to parse by a program.
+          PrintOnOneLine(test_info->value_param(), kMaxParamLength);
+        }
+        printf("\n");
+      }
+    }
+  }
+  fflush(stdout);
+}
+
+// Sets the OS stack trace getter.
+//
+// Does nothing if the input and the current OS stack trace getter are
+// the same; otherwise, deletes the old getter and makes the input the
+// current getter.
+void UnitTestImpl::set_os_stack_trace_getter(
+    OsStackTraceGetterInterface* getter) {
+  if (os_stack_trace_getter_ != getter) {
+    delete os_stack_trace_getter_;
+    os_stack_trace_getter_ = getter;
+  }
+}
+
+// Returns the current OS stack trace getter if it is not NULL;
+// otherwise, creates an OsStackTraceGetter, makes it the current
+// getter, and returns it.
+OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
+  if (os_stack_trace_getter_ == NULL) {
+    os_stack_trace_getter_ = new OsStackTraceGetter;
+  }
+
+  return os_stack_trace_getter_;
+}
+
+// Returns the TestResult for the test that's currently running, or
+// the TestResult for the ad hoc test if no test is running.
+TestResult* UnitTestImpl::current_test_result() {
+  return current_test_info_ ?
+      &(current_test_info_->result_) : &ad_hoc_test_result_;
+}
+
+// Shuffles all test cases, and the tests within each test case,
+// making sure that death tests are still run first.
+void UnitTestImpl::ShuffleTests() {
+  // Shuffles the death test cases.
+  ShuffleRange(random(), 0, last_death_test_case_ + 1, &test_case_indices_);
+
+  // Shuffles the non-death test cases.
+  ShuffleRange(random(), last_death_test_case_ + 1,
+               static_cast<int>(test_cases_.size()), &test_case_indices_);
+
+  // Shuffles the tests inside each test case.
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    test_cases_[i]->ShuffleTests(random());
+  }
+}
+
+// Restores the test cases and tests to their order before the first shuffle.
+void UnitTestImpl::UnshuffleTests() {
+  for (size_t i = 0; i < test_cases_.size(); i++) {
+    // Unshuffles the tests in each test case.
+    test_cases_[i]->UnshuffleTests();
+    // Resets the index of each test case.
+    test_case_indices_[i] = static_cast<int>(i);
+  }
+}
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+std::string GetCurrentOsStackTraceExceptTop(UnitTest* /*unit_test*/,
+                                            int skip_count) {
+  // We pass skip_count + 1 to skip this wrapper function in addition
+  // to what the user really wants to skip.
+  return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
+}
+
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
+namespace {
+class ClassUniqueToAlwaysTrue {};
+}
+
+bool IsTrue(bool condition) { return condition; }
+
+bool AlwaysTrue() {
+#if GTEST_HAS_EXCEPTIONS
+  // This condition is always false so AlwaysTrue() never actually throws,
+  // but it makes the compiler think that it may throw.
+  if (IsTrue(false))
+    throw ClassUniqueToAlwaysTrue();
+#endif  // GTEST_HAS_EXCEPTIONS
+  return true;
+}
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+bool SkipPrefix(const char* prefix, const char** pstr) {
+  const size_t prefix_len = strlen(prefix);
+  if (strncmp(*pstr, prefix, prefix_len) == 0) {
+    *pstr += prefix_len;
+    return true;
+  }
+  return false;
+}
+
+// Parses a string as a command line flag.  The string should have
+// the format "--flag=value".  When def_optional is true, the "=value"
+// part can be omitted.
+//
+// Returns the value of the flag, or NULL if the parsing failed.
+const char* ParseFlagValue(const char* str,
+                           const char* flag,
+                           bool def_optional) {
+  // str and flag must not be NULL.
+  if (str == NULL || flag == NULL) return NULL;
+
+  // The flag must start with "--" followed by GTEST_FLAG_PREFIX_.
+  const std::string flag_str = std::string("--") + GTEST_FLAG_PREFIX_ + flag;
+  const size_t flag_len = flag_str.length();
+  if (strncmp(str, flag_str.c_str(), flag_len) != 0) return NULL;
+
+  // Skips the flag name.
+  const char* flag_end = str + flag_len;
+
+  // When def_optional is true, it's OK to not have a "=value" part.
+  if (def_optional && (flag_end[0] == '\0')) {
+    return flag_end;
+  }
+
+  // If def_optional is true and there are more characters after the
+  // flag name, or if def_optional is false, there must be a '=' after
+  // the flag name.
+  if (flag_end[0] != '=') return NULL;
+
+  // Returns the string after "=".
+  return flag_end + 1;
+}
+
+// Parses a string for a bool flag, in the form of either
+// "--flag=value" or "--flag".
+//
+// In the former case, the value is taken as true as long as it does
+// not start with '0', 'f', or 'F'.
+//
+// In the latter case, the value is taken as true.
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseBoolFlag(const char* str, const char* flag, bool* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, true);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Converts the string value to a bool.
+  *value = !(*value_str == '0' || *value_str == 'f' || *value_str == 'F');
+  return true;
+}
+
+// Parses a string for an Int32 flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseInt32Flag(const char* str, const char* flag, Int32* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  return ParseInt32(Message() << "The value of flag --" << flag,
+                    value_str, value);
+}
+
+// Parses a string for a string flag, in the form of
+// "--flag=value".
+//
+// On success, stores the value of the flag in *value, and returns
+// true.  On failure, returns false without changing *value.
+bool ParseStringFlag(const char* str, const char* flag, std::string* value) {
+  // Gets the value of the flag as a string.
+  const char* const value_str = ParseFlagValue(str, flag, false);
+
+  // Aborts if the parsing failed.
+  if (value_str == NULL) return false;
+
+  // Sets *value to the value of the flag.
+  *value = value_str;
+  return true;
+}
+
+// Determines whether a string has a prefix that Google Test uses for its
+// flags, i.e., starts with GTEST_FLAG_PREFIX_ or GTEST_FLAG_PREFIX_DASH_.
+// If Google Test detects that a command line flag has its prefix but is not
+// recognized, it will print its help message. Flags starting with
+// GTEST_INTERNAL_PREFIX_ followed by "internal_" are considered Google Test
+// internal flags and do not trigger the help message.
+static bool HasGoogleTestFlagPrefix(const char* str) {
+  return (SkipPrefix("--", &str) ||
+          SkipPrefix("-", &str) ||
+          SkipPrefix("/", &str)) &&
+         !SkipPrefix(GTEST_FLAG_PREFIX_ "internal_", &str) &&
+         (SkipPrefix(GTEST_FLAG_PREFIX_, &str) ||
+          SkipPrefix(GTEST_FLAG_PREFIX_DASH_, &str));
+}
+
+// Prints a string containing code-encoded text.  The following escape
+// sequences can be used in the string to control the text color:
+//
+//   @@    prints a single '@' character.
+//   @R    changes the color to red.
+//   @G    changes the color to green.
+//   @Y    changes the color to yellow.
+//   @D    changes to the default terminal text color.
+//
+// TODO(wan@google.com): Write tests for this once we add stdout
+// capturing to Google Test.
+static void PrintColorEncoded(const char* str) {
+  GTestColor color = COLOR_DEFAULT;  // The current color.
+
+  // Conceptually, we split the string into segments divided by escape
+  // sequences.  Then we print one segment at a time.  At the end of
+  // each iteration, the str pointer advances to the beginning of the
+  // next segment.
+  for (;;) {
+    const char* p = strchr(str, '@');
+    if (p == NULL) {
+      ColoredPrintf(color, "%s", str);
+      return;
+    }
+
+    ColoredPrintf(color, "%s", std::string(str, p).c_str());
+
+    const char ch = p[1];
+    str = p + 2;
+    if (ch == '@') {
+      ColoredPrintf(color, "@");
+    } else if (ch == 'D') {
+      color = COLOR_DEFAULT;
+    } else if (ch == 'R') {
+      color = COLOR_RED;
+    } else if (ch == 'G') {
+      color = COLOR_GREEN;
+    } else if (ch == 'Y') {
+      color = COLOR_YELLOW;
+    } else {
+      --str;
+    }
+  }
+}
+
+static const char kColorEncodedHelpMessage[] =
+"This program contains tests written using " GTEST_NAME_ ". You can use the\n"
+"following command line flags to control its behavior:\n"
+"\n"
+"Test Selection:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "list_tests@D\n"
+"      List the names of all tests instead of running them. The name of\n"
+"      TEST(Foo, Bar) is \"Foo.Bar\".\n"
+"  @G--" GTEST_FLAG_PREFIX_ "filter=@YPOSTIVE_PATTERNS"
+    "[@G-@YNEGATIVE_PATTERNS]@D\n"
+"      Run only the tests whose name matches one of the positive patterns but\n"
+"      none of the negative patterns. '?' matches any single character; '*'\n"
+"      matches any substring; ':' separates two patterns.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "also_run_disabled_tests@D\n"
+"      Run all disabled tests too.\n"
+"\n"
+"Test Execution:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "repeat=@Y[COUNT]@D\n"
+"      Run the tests repeatedly; use a negative count to repeat forever.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "shuffle@D\n"
+"      Randomize tests' orders on every iteration.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "random_seed=@Y[NUMBER]@D\n"
+"      Random number seed to use for shuffling test orders (between 1 and\n"
+"      99999, or 0 to use a seed based on the current time).\n"
+"\n"
+"Test Output:\n"
+"  @G--" GTEST_FLAG_PREFIX_ "color=@Y(@Gyes@Y|@Gno@Y|@Gauto@Y)@D\n"
+"      Enable/disable colored output. The default is @Gauto@D.\n"
+"  -@G-" GTEST_FLAG_PREFIX_ "print_time=0@D\n"
+"      Don't print the elapsed time of each test.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "output=xml@Y[@G:@YDIRECTORY_PATH@G"
+    GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
+"      Generate an XML report in the given directory or with the given file\n"
+"      name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+"  @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
+"      Stream test results to the given server.\n"
+#endif  // GTEST_CAN_STREAM_RESULTS_
+"\n"
+"Assertion Behavior:\n"
+#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "death_test_style=@Y(@Gfast@Y|@Gthreadsafe@Y)@D\n"
+"      Set the default death test style.\n"
+#endif  // GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
+"  @G--" GTEST_FLAG_PREFIX_ "break_on_failure@D\n"
+"      Turn assertion failures into debugger break-points.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
+"      Turn assertion failures into C++ exceptions.\n"
+"  @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
+"      Do not report exceptions as test failures. Instead, allow them\n"
+"      to crash the program or throw a pop-up (on Windows).\n"
+"\n"
+"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
+    "the corresponding\n"
+"environment variable of a flag (all letters in upper-case). For example, to\n"
+"disable colored text output, you can either specify @G--" GTEST_FLAG_PREFIX_
+    "color=no@D or set\n"
+"the @G" GTEST_FLAG_PREFIX_UPPER_ "COLOR@D environment variable to @Gno@D.\n"
+"\n"
+"For more information, please read the " GTEST_NAME_ " documentation at\n"
+"@G" GTEST_PROJECT_URL_ "@D. If you find a bug in " GTEST_NAME_ "\n"
+"(not one in your own code or tests), please report it to\n"
+"@G<" GTEST_DEV_EMAIL_ ">@D.\n";
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.  The type parameter CharType can be
+// instantiated to either char or wchar_t.
+template <typename CharType>
+void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
+  for (int i = 1; i < *argc; i++) {
+    const std::string arg_string = StreamableToString(argv[i]);
+    const char* const arg = arg_string.c_str();
+
+    using internal::ParseBoolFlag;
+    using internal::ParseInt32Flag;
+    using internal::ParseStringFlag;
+
+    // Do we see a Google Test flag?
+    if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
+                      &GTEST_FLAG(also_run_disabled_tests)) ||
+        ParseBoolFlag(arg, kBreakOnFailureFlag,
+                      &GTEST_FLAG(break_on_failure)) ||
+        ParseBoolFlag(arg, kCatchExceptionsFlag,
+                      &GTEST_FLAG(catch_exceptions)) ||
+        ParseStringFlag(arg, kColorFlag, &GTEST_FLAG(color)) ||
+        ParseStringFlag(arg, kDeathTestStyleFlag,
+                        &GTEST_FLAG(death_test_style)) ||
+        ParseBoolFlag(arg, kDeathTestUseFork,
+                      &GTEST_FLAG(death_test_use_fork)) ||
+        ParseStringFlag(arg, kFilterFlag, &GTEST_FLAG(filter)) ||
+        ParseStringFlag(arg, kInternalRunDeathTestFlag,
+                        &GTEST_FLAG(internal_run_death_test)) ||
+        ParseBoolFlag(arg, kListTestsFlag, &GTEST_FLAG(list_tests)) ||
+        ParseStringFlag(arg, kOutputFlag, &GTEST_FLAG(output)) ||
+        ParseBoolFlag(arg, kPrintTimeFlag, &GTEST_FLAG(print_time)) ||
+        ParseInt32Flag(arg, kRandomSeedFlag, &GTEST_FLAG(random_seed)) ||
+        ParseInt32Flag(arg, kRepeatFlag, &GTEST_FLAG(repeat)) ||
+        ParseBoolFlag(arg, kShuffleFlag, &GTEST_FLAG(shuffle)) ||
+        ParseInt32Flag(arg, kStackTraceDepthFlag,
+                       &GTEST_FLAG(stack_trace_depth)) ||
+        ParseStringFlag(arg, kStreamResultToFlag,
+                        &GTEST_FLAG(stream_result_to)) ||
+        ParseBoolFlag(arg, kThrowOnFailureFlag,
+                      &GTEST_FLAG(throw_on_failure))
+        ) {
+      // Yes.  Shift the remainder of the argv list left by one.  Note
+      // that argv has (*argc + 1) elements, the last one always being
+      // NULL.  The following loop moves the trailing NULL element as
+      // well.
+      for (int j = i; j != *argc; j++) {
+        argv[j] = argv[j + 1];
+      }
+
+      // Decrements the argument count.
+      (*argc)--;
+
+      // We also need to decrement the iterator as we just removed
+      // an element.
+      i--;
+    } else if (arg_string == "--help" || arg_string == "-h" ||
+               arg_string == "-?" || arg_string == "/?" ||
+               HasGoogleTestFlagPrefix(arg)) {
+      // Both help flag and unrecognized Google Test flags (excluding
+      // internal ones) trigger help display.
+      g_help_flag = true;
+    }
+  }
+
+  if (g_help_flag) {
+    // We print the help here instead of in RUN_ALL_TESTS(), as the
+    // latter may not be called at all if the user is using Google
+    // Test with another testing framework.
+    PrintColorEncoded(kColorEncodedHelpMessage);
+  }
+}
+
+// Parses the command line for Google Test flags, without initializing
+// other parts of Google Test.
+void ParseGoogleTestFlagsOnly(int* argc, char** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv) {
+  ParseGoogleTestFlagsOnlyImpl(argc, argv);
+}
+
+// The internal implementation of InitGoogleTest().
+//
+// The type parameter CharType can be instantiated to either char or
+// wchar_t.
+template <typename CharType>
+void InitGoogleTestImpl(int* argc, CharType** argv) {
+  g_init_gtest_count++;
+
+  // We don't want to run the initialization code twice.
+  if (g_init_gtest_count != 1) return;
+
+  if (*argc <= 0) return;
+
+  internal::g_executable_path = internal::StreamableToString(argv[0]);
+
+#if GTEST_HAS_DEATH_TEST
+
+  g_argvs.clear();
+  for (int i = 0; i != *argc; i++) {
+    g_argvs.push_back(StreamableToString(argv[i]));
+  }
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+  ParseGoogleTestFlagsOnly(argc, argv);
+  GetUnitTestImpl()->PostFlagParsingInit();
+}
+
+}  // namespace internal
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+void InitGoogleTest(int* argc, char** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+void InitGoogleTest(int* argc, wchar_t** argv) {
+  internal::InitGoogleTestImpl(argc, argv);
+}
+
+}  // namespace testing
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan), vladl@google.com (Vlad Losev)
+//
+// This file implements death tests.
+
+
+#if GTEST_HAS_DEATH_TEST
+
+# if GTEST_OS_MAC
+#  include <crt_externs.h>
+# endif  // GTEST_OS_MAC
+
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+
+# if GTEST_OS_LINUX
+#  include <signal.h>
+# endif  // GTEST_OS_LINUX
+
+# include <stdarg.h>
+
+# if GTEST_OS_WINDOWS
+#  include <windows.h>
+# else
+#  include <sys/mman.h>
+#  include <sys/wait.h>
+# endif  // GTEST_OS_WINDOWS
+
+# if GTEST_OS_QNX
+#  include <spawn.h>
+# endif  // GTEST_OS_QNX
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+// Constants.
+
+// The default death test style.
+static const char kDefaultDeathTestStyle[] = "fast";
+
+GTEST_DEFINE_string_(
+    death_test_style,
+    internal::StringFromGTestEnv("death_test_style", kDefaultDeathTestStyle),
+    "Indicates how to run a death test in a forked child process: "
+    "\"threadsafe\" (child process re-executes the test binary "
+    "from the beginning, running only the specific death test) or "
+    "\"fast\" (child process runs the death test immediately "
+    "after forking).");
+
+GTEST_DEFINE_bool_(
+    death_test_use_fork,
+    internal::BoolFromGTestEnv("death_test_use_fork", false),
+    "Instructs to use fork()/_exit() instead of clone() in death tests. "
+    "Ignored and always uses fork() on POSIX systems where clone() is not "
+    "implemented. Useful when running under valgrind or similar tools if "
+    "those do not support clone(). Valgrind 3.3.1 will just fail if "
+    "it sees an unsupported combination of clone() flags. "
+    "It is not recommended to use this flag w/o valgrind though it will "
+    "work in 99% of the cases. Once valgrind is fixed, this flag will "
+    "most likely be removed.");
+
+namespace internal {
+GTEST_DEFINE_string_(
+    internal_run_death_test, "",
+    "Indicates the file, line number, temporal index of "
+    "the single death test to run, and a file descriptor to "
+    "which a success code may be sent, all separated by "
+    "the '|' characters.  This flag is specified if and only if the current "
+    "process is a sub-process launched for running a thread-safe "
+    "death test.  FOR INTERNAL USE ONLY.");
+}  // namespace internal
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Valid only for fast death tests. Indicates the code is running in the
+// child process of a fast style death test.
+static bool g_in_fast_death_test_child = false;
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+bool InDeathTestChild() {
+# if GTEST_OS_WINDOWS
+
+  // On Windows, death tests are thread-safe regardless of the value of the
+  // death_test_style flag.
+  return !GTEST_FLAG(internal_run_death_test).empty();
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe")
+    return !GTEST_FLAG(internal_run_death_test).empty();
+  else
+    return g_in_fast_death_test_child;
+#endif
+}
+
+}  // namespace internal
+
+// ExitedWithCode constructor.
+ExitedWithCode::ExitedWithCode(int exit_code) : exit_code_(exit_code) {
+}
+
+// ExitedWithCode function-call operator.
+bool ExitedWithCode::operator()(int exit_status) const {
+# if GTEST_OS_WINDOWS
+
+  return exit_status == exit_code_;
+
+# else
+
+  return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
+
+# endif  // GTEST_OS_WINDOWS
+}
+
+# if !GTEST_OS_WINDOWS
+// KilledBySignal constructor.
+KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
+}
+
+// KilledBySignal function-call operator.
+bool KilledBySignal::operator()(int exit_status) const {
+  return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
+}
+# endif  // !GTEST_OS_WINDOWS
+
+namespace internal {
+
+// Utilities needed for death tests.
+
+// Generates a textual description of a given exit code, in the format
+// specified by wait(2).
+static std::string ExitSummary(int exit_code) {
+  Message m;
+
+# if GTEST_OS_WINDOWS
+
+  m << "Exited with exit status " << exit_code;
+
+# else
+
+  if (WIFEXITED(exit_code)) {
+    m << "Exited with exit status " << WEXITSTATUS(exit_code);
+  } else if (WIFSIGNALED(exit_code)) {
+    m << "Terminated by signal " << WTERMSIG(exit_code);
+  }
+#  ifdef WCOREDUMP
+  if (WCOREDUMP(exit_code)) {
+    m << " (core dumped)";
+  }
+#  endif
+# endif  // GTEST_OS_WINDOWS
+
+  return m.GetString();
+}
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+bool ExitedUnsuccessfully(int exit_status) {
+  return !ExitedWithCode(0)(exit_status);
+}
+
+# if !GTEST_OS_WINDOWS
+// Generates a textual failure message when a death test finds more than
+// one thread running, or cannot determine the number of threads, prior
+// to executing the given statement.  It is the responsibility of the
+// caller not to pass a thread_count of 1.
+static std::string DeathTestThreadWarning(size_t thread_count) {
+  Message msg;
+  msg << "Death tests use fork(), which is unsafe particularly"
+      << " in a threaded context. For this test, " << GTEST_NAME_ << " ";
+  if (thread_count == 0)
+    msg << "couldn't detect the number of threads.";
+  else
+    msg << "detected " << thread_count << " threads.";
+  return msg.GetString();
+}
+# endif  // !GTEST_OS_WINDOWS
+
+// Flag characters for reporting a death test that did not die.
+static const char kDeathTestLived = 'L';
+static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
+static const char kDeathTestInternalError = 'I';
+
+// An enumeration describing all of the possible ways that a death test can
+// conclude.  DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception.  IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl@google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
+
+// Routine for aborting the program which is safe to call from an
+// exec-style death test child process, in which case the error
+// message is propagated back to the parent process.  Otherwise, the
+// message is simply printed to stderr.  In either case, the program
+// then exits with status 1.
+void DeathTestAbort(const std::string& message) {
+  // On a POSIX system, this function may be called from a threadsafe-style
+  // death test child process, which operates on a very small stack.  Use
+  // the heap for any additional non-minuscule memory requirements.
+  const InternalRunDeathTestFlag* const flag =
+      GetUnitTestImpl()->internal_run_death_test_flag();
+  if (flag != NULL) {
+    FILE* parent = posix::FDOpen(flag->write_fd(), "w");
+    fputc(kDeathTestInternalError, parent);
+    fprintf(parent, "%s", message.c_str());
+    fflush(parent);
+    _exit(1);
+  } else {
+    fprintf(stderr, "%s", message.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+
+// A replacement for CHECK that calls DeathTestAbort if the assertion
+// fails.
+# define GTEST_DEATH_TEST_CHECK_(expression) \
+  do { \
+    if (!::testing::internal::IsTrue(expression)) { \
+      DeathTestAbort( \
+          ::std::string("CHECK failed: File ") + __FILE__ +  ", line " \
+          + ::testing::internal::StreamableToString(__LINE__) + ": " \
+          + #expression); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// This macro is similar to GTEST_DEATH_TEST_CHECK_, but it is meant for
+// evaluating any system call that fulfills two conditions: it must return
+// -1 on failure, and set errno to EINTR when it is interrupted and
+// should be tried again.  The macro expands to a loop that repeatedly
+// evaluates the expression as long as it evaluates to -1 and sets
+// errno to EINTR.  If the expression evaluates to -1 but errno is
+// something other than EINTR, DeathTestAbort is called.
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+  do { \
+    int gtest_retval; \
+    do { \
+      gtest_retval = (expression); \
+    } while (gtest_retval == -1 && errno == EINTR); \
+    if (gtest_retval == -1) { \
+      DeathTestAbort( \
+          ::std::string("CHECK failed: File ") + __FILE__ + ", line " \
+          + ::testing::internal::StreamableToString(__LINE__) + ": " \
+          + #expression + " != -1"); \
+    } \
+  } while (::testing::internal::AlwaysFalse())
+
+// Returns the message describing the last system error in errno.
+std::string GetLastErrnoDescription() {
+    return errno == 0 ? "" : posix::StrError(errno);
+}
+
+// This is called from a death test parent process to read a failure
+// message from the death test child process and log it with the FATAL
+// severity. On Windows, the message is read from a pipe handle. On other
+// platforms, it is read from a file descriptor.
+static void FailFromInternalError(int fd) {
+  Message error;
+  char buffer[256];
+  int num_read;
+
+  do {
+    while ((num_read = posix::Read(fd, buffer, 255)) > 0) {
+      buffer[num_read] = '\0';
+      error << buffer;
+    }
+  } while (num_read == -1 && errno == EINTR);
+
+  if (num_read == 0) {
+    GTEST_LOG_(FATAL) << error.GetString();
+  } else {
+    const int last_error = errno;
+    GTEST_LOG_(FATAL) << "Error while reading death test internal: "
+                      << GetLastErrnoDescription() << " [" << last_error << "]";
+  }
+}
+
+// Death test constructor.  Increments the running death test count
+// for the current test.
+DeathTest::DeathTest() {
+  TestInfo* const info = GetUnitTestImpl()->current_test_info();
+  if (info == NULL) {
+    DeathTestAbort("Cannot run a death test outside of a TEST or "
+                   "TEST_F construct");
+  }
+}
+
+// Creates and returns a death test by dispatching to the current
+// death test factory.
+bool DeathTest::Create(const char* statement, const RE* regex,
+                       const char* file, int line, DeathTest** test) {
+  return GetUnitTestImpl()->death_test_factory()->Create(
+      statement, regex, file, line, test);
+}
+
+const char* DeathTest::LastMessage() {
+  return last_death_test_message_.c_str();
+}
+
+void DeathTest::set_last_death_test_message(const std::string& message) {
+  last_death_test_message_ = message;
+}
+
+std::string DeathTest::last_death_test_message_;
+
+// Provides cross platform implementation for some death functionality.
+class DeathTestImpl : public DeathTest {
+ protected:
+  DeathTestImpl(const char* a_statement, const RE* a_regex)
+      : statement_(a_statement),
+        regex_(a_regex),
+        spawned_(false),
+        status_(-1),
+        outcome_(IN_PROGRESS),
+        read_fd_(-1),
+        write_fd_(-1) {}
+
+  // read_fd_ is expected to be closed and cleared by a derived class.
+  ~DeathTestImpl() { GTEST_DEATH_TEST_CHECK_(read_fd_ == -1); }
+
+  void Abort(AbortReason reason);
+  virtual bool Passed(bool status_ok);
+
+  const char* statement() const { return statement_; }
+  const RE* regex() const { return regex_; }
+  bool spawned() const { return spawned_; }
+  void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
+  int status() const { return status_; }
+  void set_status(int a_status) { status_ = a_status; }
+  DeathTestOutcome outcome() const { return outcome_; }
+  void set_outcome(DeathTestOutcome an_outcome) { outcome_ = an_outcome; }
+  int read_fd() const { return read_fd_; }
+  void set_read_fd(int fd) { read_fd_ = fd; }
+  int write_fd() const { return write_fd_; }
+  void set_write_fd(int fd) { write_fd_ = fd; }
+
+  // Called in the parent process only. Reads the result code of the death
+  // test child process via a pipe, interprets it to set the outcome_
+  // member, and closes read_fd_.  Outputs diagnostics and terminates in
+  // case of unexpected codes.
+  void ReadAndInterpretStatusByte();
+
+ private:
+  // The textual content of the code this object is testing.  This class
+  // doesn't own this string and should not attempt to delete it.
+  const char* const statement_;
+  // The regular expression which test output must match.  DeathTestImpl
+  // doesn't own this object and should not attempt to delete it.
+  const RE* const regex_;
+  // True if the death test child process has been successfully spawned.
+  bool spawned_;
+  // The exit status of the child process.
+  int status_;
+  // How the death test concluded.
+  DeathTestOutcome outcome_;
+  // Descriptor to the read end of the pipe to the child process.  It is
+  // always -1 in the child process.  The child keeps its write end of the
+  // pipe in write_fd_.
+  int read_fd_;
+  // Descriptor to the child's write end of the pipe to the parent process.
+  // It is always -1 in the parent process.  The parent keeps its end of the
+  // pipe in read_fd_.
+  int write_fd_;
+};
+
+// Called in the parent process only. Reads the result code of the death
+// test child process via a pipe, interprets it to set the outcome_
+// member, and closes read_fd_.  Outputs diagnostics and terminates in
+// case of unexpected codes.
+void DeathTestImpl::ReadAndInterpretStatusByte() {
+  char flag;
+  int bytes_read;
+
+  // The read() here blocks until data is available (signifying the
+  // failure of the death test) or until the pipe is closed (signifying
+  // its success), so it's okay to call this in the parent before
+  // the child process has exited.
+  do {
+    bytes_read = posix::Read(read_fd(), &flag, 1);
+  } while (bytes_read == -1 && errno == EINTR);
+
+  if (bytes_read == 0) {
+    set_outcome(DIED);
+  } else if (bytes_read == 1) {
+    switch (flag) {
+      case kDeathTestReturned:
+        set_outcome(RETURNED);
+        break;
+      case kDeathTestThrew:
+        set_outcome(THREW);
+        break;
+      case kDeathTestLived:
+        set_outcome(LIVED);
+        break;
+      case kDeathTestInternalError:
+        FailFromInternalError(read_fd());  // Does not return.
+        break;
+      default:
+        GTEST_LOG_(FATAL) << "Death test child process reported "
+                          << "unexpected status byte ("
+                          << static_cast<unsigned int>(flag) << ")";
+    }
+  } else {
+    GTEST_LOG_(FATAL) << "Read from death test child process failed: "
+                      << GetLastErrnoDescription();
+  }
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(read_fd()));
+  set_read_fd(-1);
+}
+
+// Signals that the death test code which should have exited, didn't.
+// Should be called only in a death test child process.
+// Writes a status byte to the child's status file descriptor, then
+// calls _exit(1).
+void DeathTestImpl::Abort(AbortReason reason) {
+  // The parent process considers the death test to be a failure if
+  // it finds any data in our pipe.  So, here we write a single flag byte
+  // to the pipe, then exit.
+  const char status_ch =
+      reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+      reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
+  // We are leaking the descriptor here because on some platforms (i.e.,
+  // when built as Windows DLL), destructors of global objects will still
+  // run after calling _exit(). On such systems, write_fd_ will be
+  // indirectly closed from the destructor of UnitTestImpl, causing double
+  // close if it is also closed here. On debug configurations, double close
+  // may assert. As there are no in-process buffers to flush here, we are
+  // relying on the OS to close the descriptor after the process terminates
+  // when the destructors are not run.
+  _exit(1);  // Exits w/o any normal exit hooks (we were supposed to crash)
+}
+
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+  ::std::string ret;
+  for (size_t at = 0; ; ) {
+    const size_t line_end = output.find('\n', at);
+    ret += "[  DEATH   ] ";
+    if (line_end == ::std::string::npos) {
+      ret += output.substr(at);
+      break;
+    }
+    ret += output.substr(at, line_end + 1 - at);
+    at = line_end + 1;
+  }
+  return ret;
+}
+
+// Assesses the success or failure of a death test, using both private
+// members which have previously been set, and one argument:
+//
+// Private data members:
+//   outcome:  An enumeration describing how the death test
+//             concluded: DIED, LIVED, THREW, or RETURNED.  The death test
+//             fails in the latter three cases.
+//   status:   The exit status of the child process. On *nix, it is in the
+//             in the format specified by wait(2). On Windows, this is the
+//             value supplied to the ExitProcess() API or a numeric code
+//             of the exception that terminated the program.
+//   regex:    A regular expression object to be applied to
+//             the test's captured standard error output; the death test
+//             fails if it does not match.
+//
+// Argument:
+//   status_ok: true if exit_status is acceptable in the context of
+//              this particular death test, which fails if it is false
+//
+// Returns true iff all of the above conditions are met.  Otherwise, the
+// first failing condition, in the order given above, is the one that is
+// reported. Also sets the last death test message string.
+bool DeathTestImpl::Passed(bool status_ok) {
+  if (!spawned())
+    return false;
+
+  const std::string error_message = GetCapturedStderr();
+
+  bool success = false;
+  Message buffer;
+
+  buffer << "Death test: " << statement() << "\n";
+  switch (outcome()) {
+    case LIVED:
+      buffer << "    Result: failed to die.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case THREW:
+      buffer << "    Result: threw an exception.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case RETURNED:
+      buffer << "    Result: illegal return in test statement.\n"
+             << " Error msg:\n" << FormatDeathTestOutput(error_message);
+      break;
+    case DIED:
+      if (status_ok) {
+        const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+        if (matched) {
+          success = true;
+        } else {
+          buffer << "    Result: died but not with expected error.\n"
+                 << "  Expected: " << regex()->pattern() << "\n"
+                 << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+        }
+      } else {
+        buffer << "    Result: died but not with expected exit code:\n"
+               << "            " << ExitSummary(status()) << "\n"
+               << "Actual msg:\n" << FormatDeathTestOutput(error_message);
+      }
+      break;
+    case IN_PROGRESS:
+    default:
+      GTEST_LOG_(FATAL)
+          << "DeathTest::Passed somehow called before conclusion of test";
+  }
+
+  DeathTest::set_last_death_test_message(buffer.GetString());
+  return success;
+}
+
+# if GTEST_OS_WINDOWS
+// WindowsDeathTest implements death tests on Windows. Due to the
+// specifics of starting new processes on Windows, death tests there are
+// always threadsafe, and Google Test considers the
+// --gtest_death_test_style=fast setting to be equivalent to
+// --gtest_death_test_style=threadsafe there.
+//
+// A few implementation notes:  Like the Linux version, the Windows
+// implementation uses pipes for child-to-parent communication. But due to
+// the specifics of pipes on Windows, some extra steps are required:
+//
+// 1. The parent creates a communication pipe and stores handles to both
+//    ends of it.
+// 2. The parent starts the child and provides it with the information
+//    necessary to acquire the handle to the write end of the pipe.
+// 3. The child acquires the write end of the pipe and signals the parent
+//    using a Windows event.
+// 4. Now the parent can release the write end of the pipe on its side. If
+//    this is done before step 3, the object's reference count goes down to
+//    0 and it is destroyed, preventing the child from acquiring it. The
+//    parent now has to release it, or read operations on the read end of
+//    the pipe will not return when the child terminates.
+// 5. The parent reads child's output through the pipe (outcome code and
+//    any possible error messages) from the pipe, and its stderr and then
+//    determines whether to fail the test.
+//
+// Note: to distinguish Win32 API calls from the local method and function
+// calls, the former are explicitly resolved in the global namespace.
+//
+class WindowsDeathTest : public DeathTestImpl {
+ public:
+  WindowsDeathTest(const char* a_statement,
+                   const RE* a_regex,
+                   const char* file,
+                   int line)
+      : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+  virtual TestRole AssumeRole();
+
+ private:
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+  // Handle to the write end of the pipe to the child process.
+  AutoHandle write_handle_;
+  // Child process handle.
+  AutoHandle child_handle_;
+  // Event the child process uses to signal the parent that it has
+  // acquired the handle to the write end of the pipe. After seeing this
+  // event the parent can release its own handles to make sure its
+  // ReadFile() calls return when the child terminates.
+  AutoHandle event_handle_;
+};
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int WindowsDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  // Wait until the child either signals that it has acquired the write end
+  // of the pipe or it dies.
+  const HANDLE wait_handles[2] = { child_handle_.Get(), event_handle_.Get() };
+  switch (::WaitForMultipleObjects(2,
+                                   wait_handles,
+                                   FALSE,  // Waits for any of the handles.
+                                   INFINITE)) {
+    case WAIT_OBJECT_0:
+    case WAIT_OBJECT_0 + 1:
+      break;
+    default:
+      GTEST_DEATH_TEST_CHECK_(false);  // Should not get here.
+  }
+
+  // The child has acquired the write end of the pipe or exited.
+  // We release the handle on our side and continue.
+  write_handle_.Reset();
+  event_handle_.Reset();
+
+  ReadAndInterpretStatusByte();
+
+  // Waits for the child process to exit if it haven't already. This
+  // returns immediately if the child has already exited, regardless of
+  // whether previous calls to WaitForMultipleObjects synchronized on this
+  // handle or not.
+  GTEST_DEATH_TEST_CHECK_(
+      WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
+                                             INFINITE));
+  DWORD status_code;
+  GTEST_DEATH_TEST_CHECK_(
+      ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
+  child_handle_.Reset();
+  set_status(static_cast<int>(status_code));
+  return status();
+}
+
+// The AssumeRole process for a Windows death test.  It creates a child
+// process with the same executable as the current process to run the
+// death test.  The child process is given the --gtest_filter and
+// --gtest_internal_run_death_test flags such that it knows to run the
+// current death test only.
+DeathTest::TestRole WindowsDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    // ParseInternalRunDeathTestFlag() has performed all the necessary
+    // processing.
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  // WindowsDeathTest uses an anonymous pipe to communicate results of
+  // a death test.
+  SECURITY_ATTRIBUTES handles_are_inheritable = {
+    sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
+  HANDLE read_handle, write_handle;
+  GTEST_DEATH_TEST_CHECK_(
+      ::CreatePipe(&read_handle, &write_handle, &handles_are_inheritable,
+                   0)  // Default buffer size.
+      != FALSE);
+  set_read_fd(::_open_osfhandle(reinterpret_cast<intptr_t>(read_handle),
+                                O_RDONLY));
+  write_handle_.Reset(write_handle);
+  event_handle_.Reset(::CreateEvent(
+      &handles_are_inheritable,
+      TRUE,    // The event will automatically reset to non-signaled state.
+      FALSE,   // The initial state is non-signalled.
+      NULL));  // The even is unnamed.
+  GTEST_DEATH_TEST_CHECK_(event_handle_.Get() != NULL);
+  const std::string filter_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "=" +
+      info->test_case_name() + "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag +
+      "=" + file_ + "|" + StreamableToString(line_) + "|" +
+      StreamableToString(death_test_index) + "|" +
+      StreamableToString(static_cast<unsigned int>(::GetCurrentProcessId())) +
+      // size_t has the same width as pointers on both 32-bit and 64-bit
+      // Windows platforms.
+      // See http://msdn.microsoft.com/en-us/library/tcxf1dw6.aspx.
+      "|" + StreamableToString(reinterpret_cast<size_t>(write_handle)) +
+      "|" + StreamableToString(reinterpret_cast<size_t>(event_handle_.Get()));
+
+  char executable_path[_MAX_PATH + 1];  // NOLINT
+  GTEST_DEATH_TEST_CHECK_(
+      _MAX_PATH + 1 != ::GetModuleFileNameA(NULL,
+                                            executable_path,
+                                            _MAX_PATH));
+
+  std::string command_line =
+      std::string(::GetCommandLineA()) + " " + filter_flag + " \"" +
+      internal_flag + "\"";
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // Flush the log buffers since the log streams are shared with the child.
+  FlushInfoLog();
+
+  // The child process will share the standard handles with the parent.
+  STARTUPINFOA startup_info;
+  memset(&startup_info, 0, sizeof(STARTUPINFO));
+  startup_info.dwFlags = STARTF_USESTDHANDLES;
+  startup_info.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE);
+  startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
+  startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
+
+  PROCESS_INFORMATION process_info;
+  GTEST_DEATH_TEST_CHECK_(::CreateProcessA(
+      executable_path,
+      const_cast<char*>(command_line.c_str()),
+      NULL,   // Retuned process handle is not inheritable.
+      NULL,   // Retuned thread handle is not inheritable.
+      TRUE,   // Child inherits all inheritable handles (for write_handle_).
+      0x0,    // Default creation flags.
+      NULL,   // Inherit the parent's environment.
+      UnitTest::GetInstance()->original_working_dir(),
+      &startup_info,
+      &process_info) != FALSE);
+  child_handle_.Reset(process_info.hProcess);
+  ::CloseHandle(process_info.hThread);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+# else  // We are not on Windows.
+
+// ForkingDeathTest provides implementations for most of the abstract
+// methods of the DeathTest interface.  Only the AssumeRole method is
+// left undefined.
+class ForkingDeathTest : public DeathTestImpl {
+ public:
+  ForkingDeathTest(const char* statement, const RE* regex);
+
+  // All of these virtual functions are inherited from DeathTest.
+  virtual int Wait();
+
+ protected:
+  void set_child_pid(pid_t child_pid) { child_pid_ = child_pid; }
+
+ private:
+  // PID of child process during death test; 0 in the child process itself.
+  pid_t child_pid_;
+};
+
+// Constructs a ForkingDeathTest.
+ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
+    : DeathTestImpl(a_statement, a_regex),
+      child_pid_(-1) {}
+
+// Waits for the child in a death test to exit, returning its exit
+// status, or 0 if no child process exists.  As a side effect, sets the
+// outcome data member.
+int ForkingDeathTest::Wait() {
+  if (!spawned())
+    return 0;
+
+  ReadAndInterpretStatusByte();
+
+  int status_value;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(waitpid(child_pid_, &status_value, 0));
+  set_status(status_value);
+  return status_value;
+}
+
+// A concrete death test class that forks, then immediately runs the test
+// in the child process.
+class NoExecDeathTest : public ForkingDeathTest {
+ public:
+  NoExecDeathTest(const char* a_statement, const RE* a_regex) :
+      ForkingDeathTest(a_statement, a_regex) { }
+  virtual TestRole AssumeRole();
+};
+
+// The AssumeRole process for a fork-and-run death test.  It implements a
+// straightforward fork, with a simple pipe to transmit the status byte.
+DeathTest::TestRole NoExecDeathTest::AssumeRole() {
+  const size_t thread_count = GetThreadCount();
+  if (thread_count != 1) {
+    GTEST_LOG_(WARNING) << DeathTestThreadWarning(thread_count);
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+
+  DeathTest::set_last_death_test_message("");
+  CaptureStderr();
+  // When we fork the process below, the log file buffers are copied, but the
+  // file descriptors are shared.  We flush all log files here so that closing
+  // the file descriptors in the child process doesn't throw off the
+  // synchronization between descriptors and buffers in the parent process.
+  // This is as close to the fork as possible to avoid a race condition in case
+  // there are multiple threads running before the death test, and another
+  // thread writes to the log file.
+  FlushInfoLog();
+
+  const pid_t child_pid = fork();
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  set_child_pid(child_pid);
+  if (child_pid == 0) {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[0]));
+    set_write_fd(pipe_fd[1]);
+    // Redirects all logging to stderr in the child process to prevent
+    // concurrent writes to the log files.  We capture stderr in the parent
+    // process and append the child process' output to a log.
+    LogToStderr();
+    // Event forwarding to the listeners of event listener API mush be shut
+    // down in death test subprocesses.
+    GetUnitTestImpl()->listeners()->SuppressEventForwarding();
+    g_in_fast_death_test_child = true;
+    return EXECUTE_TEST;
+  } else {
+    GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+    set_read_fd(pipe_fd[0]);
+    set_spawned(true);
+    return OVERSEE_TEST;
+  }
+}
+
+// A concrete death test class that forks and re-executes the main
+// program from the beginning, with command-line flags set that cause
+// only this specific death test to be run.
+class ExecDeathTest : public ForkingDeathTest {
+ public:
+  ExecDeathTest(const char* a_statement, const RE* a_regex,
+                const char* file, int line) :
+      ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
+  virtual TestRole AssumeRole();
+ private:
+  static ::std::vector<testing::internal::string>
+  GetArgvsForDeathTestChildProcess() {
+    ::std::vector<testing::internal::string> args = GetInjectableArgvs();
+    return args;
+  }
+  // The name of the file in which the death test is located.
+  const char* const file_;
+  // The line number on which the death test is located.
+  const int line_;
+};
+
+// Utility class for accumulating command-line arguments.
+class Arguments {
+ public:
+  Arguments() {
+    args_.push_back(NULL);
+  }
+
+  ~Arguments() {
+    for (std::vector<char*>::iterator i = args_.begin(); i != args_.end();
+         ++i) {
+      free(*i);
+    }
+  }
+  void AddArgument(const char* argument) {
+    args_.insert(args_.end() - 1, posix::StrDup(argument));
+  }
+
+  template <typename Str>
+  void AddArguments(const ::std::vector<Str>& arguments) {
+    for (typename ::std::vector<Str>::const_iterator i = arguments.begin();
+         i != arguments.end();
+         ++i) {
+      args_.insert(args_.end() - 1, posix::StrDup(i->c_str()));
+    }
+  }
+  char* const* Argv() {
+    return &args_[0];
+  }
+
+ private:
+  std::vector<char*> args_;
+};
+
+// A struct that encompasses the arguments to the child process of a
+// threadsafe-style death test process.
+struct ExecDeathTestArgs {
+  char* const* argv;  // Command-line arguments for the child's call to exec
+  int close_fd;       // File descriptor to close; the read end of a pipe
+};
+
+#  if GTEST_OS_MAC
+inline char** GetEnviron() {
+  // When Google Test is built as a framework on MacOS X, the environ variable
+  // is unavailable. Apple's documentation (man environ) recommends using
+  // _NSGetEnviron() instead.
+  return *_NSGetEnviron();
+}
+#  else
+// Some POSIX platforms expect you to declare environ. extern "C" makes
+// it reside in the global namespace.
+extern "C" char** environ;
+inline char** GetEnviron() { return environ; }
+#  endif  // GTEST_OS_MAC
+
+#  if !GTEST_OS_QNX
+// The main function for a threadsafe-style death test child process.
+// This function is called in a clone()-ed process and thus must avoid
+// any potentially unsafe operations like malloc or libc functions.
+static int ExecDeathTestChildMain(void* child_arg) {
+  ExecDeathTestArgs* const args = static_cast<ExecDeathTestArgs*>(child_arg);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(args->close_fd));
+
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+                   GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  // We can safely call execve() as it's a direct system call.  We
+  // cannot use execvp() as it's a libc function and thus potentially
+  // unsafe.  Since execve() doesn't search the PATH, the user must
+  // invoke the test program via a valid path that contains at least
+  // one path separator.
+  execve(args->argv[0], args->argv, GetEnviron());
+  DeathTestAbort(std::string("execve(") + args->argv[0] + ", ...) in " +
+                 original_dir + " failed: " +
+                 GetLastErrnoDescription());
+  return EXIT_FAILURE;
+}
+#  endif  // !GTEST_OS_QNX
+
+// Two utility routines that together determine the direction the stack
+// grows.
+// This could be accomplished more elegantly by a single recursive
+// function, but we want to guard against the unlikely possibility of
+// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+void StackLowerThanAddress(const void* ptr, bool* result) GTEST_NO_INLINE_;
+void StackLowerThanAddress(const void* ptr, bool* result) {
+  int dummy;
+  *result = (&dummy < ptr);
+}
+
+bool StackGrowsDown() {
+  int dummy;
+  bool result;
+  StackLowerThanAddress(&dummy, &result);
+  return result;
+}
+
+// Spawns a child process with the same executable as the current process in
+// a thread-safe manner and instructs it to run the death test.  The
+// implementation uses fork(2) + exec.  On systems where clone(2) is
+// available, it is used instead, being slightly more thread-safe.  On QNX,
+// fork supports only single-threaded environments, so this function uses
+// spawn(2) there instead.  The function dies with an error message if
+// anything goes wrong.
+static pid_t ExecDeathTestSpawnChild(char* const* argv, int close_fd) {
+  ExecDeathTestArgs args = { argv, close_fd };
+  pid_t child_pid = -1;
+
+#  if GTEST_OS_QNX
+  // Obtains the current directory and sets it to be closed in the child
+  // process.
+  const int cwd_fd = open(".", O_RDONLY);
+  GTEST_DEATH_TEST_CHECK_(cwd_fd != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(cwd_fd, F_SETFD, FD_CLOEXEC));
+  // We need to execute the test program in the same environment where
+  // it was originally invoked.  Therefore we change to the original
+  // working directory first.
+  const char* const original_dir =
+      UnitTest::GetInstance()->original_working_dir();
+  // We can safely call chdir() as it's a direct system call.
+  if (chdir(original_dir) != 0) {
+    DeathTestAbort(std::string("chdir(\"") + original_dir + "\") failed: " +
+                   GetLastErrnoDescription());
+    return EXIT_FAILURE;
+  }
+
+  int fd_flags;
+  // Set close_fd to be closed after spawn.
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fd_flags = fcntl(close_fd, F_GETFD));
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(fcntl(close_fd, F_SETFD,
+                                        fd_flags | FD_CLOEXEC));
+  struct inheritance inherit = {0};
+  // spawn is a system call.
+  child_pid = spawn(args.argv[0], 0, NULL, &inherit, args.argv, GetEnviron());
+  // Restores the current working directory.
+  GTEST_DEATH_TEST_CHECK_(fchdir(cwd_fd) != -1);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(cwd_fd));
+
+#  else   // GTEST_OS_QNX
+#   if GTEST_OS_LINUX
+  // When a SIGPROF signal is received while fork() or clone() are executing,
+  // the process may hang. To avoid this, we ignore SIGPROF here and re-enable
+  // it after the call to fork()/clone() is complete.
+  struct sigaction saved_sigprof_action;
+  struct sigaction ignore_sigprof_action;
+  memset(&ignore_sigprof_action, 0, sizeof(ignore_sigprof_action));
+  sigemptyset(&ignore_sigprof_action.sa_mask);
+  ignore_sigprof_action.sa_handler = SIG_IGN;
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(sigaction(
+      SIGPROF, &ignore_sigprof_action, &saved_sigprof_action));
+#   endif  // GTEST_OS_LINUX
+
+#   if GTEST_HAS_CLONE
+  const bool use_fork = GTEST_FLAG(death_test_use_fork);
+
+  if (!use_fork) {
+    static const bool stack_grows_down = StackGrowsDown();
+    const size_t stack_size = getpagesize();
+    // MMAP_ANONYMOUS is not defined on Mac, so we use MAP_ANON instead.
+    void* const stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,
+                             MAP_ANON | MAP_PRIVATE, -1, 0);
+    GTEST_DEATH_TEST_CHECK_(stack != MAP_FAILED);
+
+    // Maximum stack alignment in bytes:  For a downward-growing stack, this
+    // amount is subtracted from size of the stack space to get an address
+    // that is within the stack space and is aligned on all systems we care
+    // about.  As far as I know there is no ABI with stack alignment greater
+    // than 64.  We assume stack and stack_size already have alignment of
+    // kMaxStackAlignment.
+    const size_t kMaxStackAlignment = 64;
+    void* const stack_top =
+        static_cast<char*>(stack) +
+            (stack_grows_down ? stack_size - kMaxStackAlignment : 0);
+    GTEST_DEATH_TEST_CHECK_(stack_size > kMaxStackAlignment &&
+        reinterpret_cast<intptr_t>(stack_top) % kMaxStackAlignment == 0);
+
+    child_pid = clone(&ExecDeathTestChildMain, stack_top, SIGCHLD, &args);
+
+    GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
+  }
+#   else
+  const bool use_fork = true;
+#   endif  // GTEST_HAS_CLONE
+
+  if (use_fork && (child_pid = fork()) == 0) {
+      ExecDeathTestChildMain(&args);
+      _exit(0);
+  }
+#  endif  // GTEST_OS_QNX
+#  if GTEST_OS_LINUX
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(
+      sigaction(SIGPROF, &saved_sigprof_action, NULL));
+#  endif  // GTEST_OS_LINUX
+
+  GTEST_DEATH_TEST_CHECK_(child_pid != -1);
+  return child_pid;
+}
+
+// The AssumeRole process for a fork-and-exec death test.  It re-executes the
+// main program from the beginning, setting the --gtest_filter
+// and --gtest_internal_run_death_test flags to cause only the current
+// death test to be re-run.
+DeathTest::TestRole ExecDeathTest::AssumeRole() {
+  const UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const TestInfo* const info = impl->current_test_info();
+  const int death_test_index = info->result()->death_test_count();
+
+  if (flag != NULL) {
+    set_write_fd(flag->write_fd());
+    return EXECUTE_TEST;
+  }
+
+  int pipe_fd[2];
+  GTEST_DEATH_TEST_CHECK_(pipe(pipe_fd) != -1);
+  // Clear the close-on-exec flag on the write end of the pipe, lest
+  // it be closed when the child process does an exec:
+  GTEST_DEATH_TEST_CHECK_(fcntl(pipe_fd[1], F_SETFD, 0) != -1);
+
+  const std::string filter_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kFilterFlag + "="
+      + info->test_case_name() + "." + info->name();
+  const std::string internal_flag =
+      std::string("--") + GTEST_FLAG_PREFIX_ + kInternalRunDeathTestFlag + "="
+      + file_ + "|" + StreamableToString(line_) + "|"
+      + StreamableToString(death_test_index) + "|"
+      + StreamableToString(pipe_fd[1]);
+  Arguments args;
+  args.AddArguments(GetArgvsForDeathTestChildProcess());
+  args.AddArgument(filter_flag.c_str());
+  args.AddArgument(internal_flag.c_str());
+
+  DeathTest::set_last_death_test_message("");
+
+  CaptureStderr();
+  // See the comment in NoExecDeathTest::AssumeRole for why the next line
+  // is necessary.
+  FlushInfoLog();
+
+  const pid_t child_pid = ExecDeathTestSpawnChild(args.Argv(), pipe_fd[0]);
+  GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
+  set_child_pid(child_pid);
+  set_read_fd(pipe_fd[0]);
+  set_spawned(true);
+  return OVERSEE_TEST;
+}
+
+# endif  // !GTEST_OS_WINDOWS
+
+// Creates a concrete DeathTest-derived class that depends on the
+// --gtest_death_test_style flag, and sets the pointer pointed to
+// by the "test" argument to its address.  If the test should be
+// skipped, sets that pointer to NULL.  Returns true, unless the
+// flag is set to an invalid value.
+bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
+                                     const char* file, int line,
+                                     DeathTest** test) {
+  UnitTestImpl* const impl = GetUnitTestImpl();
+  const InternalRunDeathTestFlag* const flag =
+      impl->internal_run_death_test_flag();
+  const int death_test_index = impl->current_test_info()
+      ->increment_death_test_count();
+
+  if (flag != NULL) {
+    if (death_test_index > flag->index()) {
+      DeathTest::set_last_death_test_message(
+          "Death test count (" + StreamableToString(death_test_index)
+          + ") somehow exceeded expected maximum ("
+          + StreamableToString(flag->index()) + ")");
+      return false;
+    }
+
+    if (!(flag->file() == file && flag->line() == line &&
+          flag->index() == death_test_index)) {
+      *test = NULL;
+      return true;
+    }
+  }
+
+# if GTEST_OS_WINDOWS
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe" ||
+      GTEST_FLAG(death_test_style) == "fast") {
+    *test = new WindowsDeathTest(statement, regex, file, line);
+  }
+
+# else
+
+  if (GTEST_FLAG(death_test_style) == "threadsafe") {
+    *test = new ExecDeathTest(statement, regex, file, line);
+  } else if (GTEST_FLAG(death_test_style) == "fast") {
+    *test = new NoExecDeathTest(statement, regex);
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  else {  // NOLINT - this is more readable than unbalanced brackets inside #if.
+    DeathTest::set_last_death_test_message(
+        "Unknown death test style \"" + GTEST_FLAG(death_test_style)
+        + "\" encountered");
+    return false;
+  }
+
+  return true;
+}
+
+// Splits a given string on a given delimiter, populating a given
+// vector with the fields.  GTEST_HAS_DEATH_TEST implies that we have
+// ::std::string, so we can use it here.
+static void SplitString(const ::std::string& str, char delimiter,
+                        ::std::vector< ::std::string>* dest) {
+  ::std::vector< ::std::string> parsed;
+  ::std::string::size_type pos = 0;
+  while (::testing::internal::AlwaysTrue()) {
+    const ::std::string::size_type colon = str.find(delimiter, pos);
+    if (colon == ::std::string::npos) {
+      parsed.push_back(str.substr(pos));
+      break;
+    } else {
+      parsed.push_back(str.substr(pos, colon - pos));
+      pos = colon + 1;
+    }
+  }
+  dest->swap(parsed);
+}
+
+# if GTEST_OS_WINDOWS
+// Recreates the pipe and event handles from the provided parameters,
+// signals the event, and returns a file descriptor wrapped around the pipe
+// handle. This function is called in the child process only.
+int GetStatusFileDescriptor(unsigned int parent_process_id,
+                            size_t write_handle_as_size_t,
+                            size_t event_handle_as_size_t) {
+  AutoHandle parent_process_handle(::OpenProcess(PROCESS_DUP_HANDLE,
+                                                   FALSE,  // Non-inheritable.
+                                                   parent_process_id));
+  if (parent_process_handle.Get() == INVALID_HANDLE_VALUE) {
+    DeathTestAbort("Unable to open parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  // TODO(vladl@google.com): Replace the following check with a
+  // compile-time assertion when available.
+  GTEST_CHECK_(sizeof(HANDLE) <= sizeof(size_t));
+
+  const HANDLE write_handle =
+      reinterpret_cast<HANDLE>(write_handle_as_size_t);
+  HANDLE dup_write_handle;
+
+  // The newly initialized handle is accessible only in in the parent
+  // process. To obtain one accessible within the child, we need to use
+  // DuplicateHandle.
+  if (!::DuplicateHandle(parent_process_handle.Get(), write_handle,
+                         ::GetCurrentProcess(), &dup_write_handle,
+                         0x0,    // Requested privileges ignored since
+                                 // DUPLICATE_SAME_ACCESS is used.
+                         FALSE,  // Request non-inheritable handler.
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const HANDLE event_handle = reinterpret_cast<HANDLE>(event_handle_as_size_t);
+  HANDLE dup_event_handle;
+
+  if (!::DuplicateHandle(parent_process_handle.Get(), event_handle,
+                         ::GetCurrentProcess(), &dup_event_handle,
+                         0x0,
+                         FALSE,
+                         DUPLICATE_SAME_ACCESS)) {
+    DeathTestAbort("Unable to duplicate the event handle " +
+                   StreamableToString(event_handle_as_size_t) +
+                   " from the parent process " +
+                   StreamableToString(parent_process_id));
+  }
+
+  const int write_fd =
+      ::_open_osfhandle(reinterpret_cast<intptr_t>(dup_write_handle), O_APPEND);
+  if (write_fd == -1) {
+    DeathTestAbort("Unable to convert pipe handle " +
+                   StreamableToString(write_handle_as_size_t) +
+                   " to a file descriptor");
+  }
+
+  // Signals the parent that the write end of the pipe has been acquired
+  // so the parent can release its own write end.
+  ::SetEvent(dup_event_handle);
+
+  return write_fd;
+}
+# endif  // GTEST_OS_WINDOWS
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag() {
+  if (GTEST_FLAG(internal_run_death_test) == "") return NULL;
+
+  // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we
+  // can use it here.
+  int line = -1;
+  int index = -1;
+  ::std::vector< ::std::string> fields;
+  SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
+  int write_fd = -1;
+
+# if GTEST_OS_WINDOWS
+
+  unsigned int parent_process_id = 0;
+  size_t write_handle_as_size_t = 0;
+  size_t event_handle_as_size_t = 0;
+
+  if (fields.size() != 6
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &parent_process_id)
+      || !ParseNaturalNumber(fields[4], &write_handle_as_size_t)
+      || !ParseNaturalNumber(fields[5], &event_handle_as_size_t)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: " +
+                   GTEST_FLAG(internal_run_death_test));
+  }
+  write_fd = GetStatusFileDescriptor(parent_process_id,
+                                     write_handle_as_size_t,
+                                     event_handle_as_size_t);
+# else
+
+  if (fields.size() != 4
+      || !ParseNaturalNumber(fields[1], &line)
+      || !ParseNaturalNumber(fields[2], &index)
+      || !ParseNaturalNumber(fields[3], &write_fd)) {
+    DeathTestAbort("Bad --gtest_internal_run_death_test flag: "
+        + GTEST_FLAG(internal_run_death_test));
+  }
+
+# endif  // GTEST_OS_WINDOWS
+
+  return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
+}
+
+}  // namespace internal
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace testing
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Authors: keith.ray@gmail.com (Keith Ray)
+
+
+#include <stdlib.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>
+#elif GTEST_OS_WINDOWS
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN
+// Symbian OpenC has PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
+#else
+# include <limits.h>
+# include <climits>  // Some Linux distributions define PATH_MAX here.
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_MAX_ _MAX_PATH
+#elif defined(PATH_MAX)
+# define GTEST_PATH_MAX_ PATH_MAX
+#elif defined(_XOPEN_PATH_MAX)
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+#else
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+#endif  // GTEST_OS_WINDOWS
+
+
+namespace testing {
+namespace internal {
+
+#if GTEST_OS_WINDOWS
+// On Windows, '\\' is the standard path separator, but many tools and the
+// Windows API also accept '/' as an alternate path separator. Unless otherwise
+// noted, a file path can contain either kind of path separators, or a mixture
+// of them.
+const char kPathSeparator = '\\';
+const char kAlternatePathSeparator = '/';
+//const char kPathSeparatorString[] = "\\";
+const char kAlternatePathSeparatorString[] = "/";
+# if GTEST_OS_WINDOWS_MOBILE
+// Windows CE doesn't have a current directory. You should not use
+// the current directory in tests on Windows CE, but this at least
+// provides a reasonable fallback.
+const char kCurrentDirectoryString[] = "\\";
+// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
+const DWORD kInvalidFileAttributes = 0xffffffff;
+# else
+const char kCurrentDirectoryString[] = ".\\";
+# endif  // GTEST_OS_WINDOWS_MOBILE
+#else
+const char kPathSeparator = '/';
+//const char kPathSeparatorString[] = "/";
+const char kCurrentDirectoryString[] = "./";
+#endif  // GTEST_OS_WINDOWS
+
+// Returns whether the given character is a valid path separator.
+static bool IsPathSeparator(char c) {
+#if GTEST_HAS_ALT_PATH_SEP_
+  return (c == kPathSeparator) || (c == kAlternatePathSeparator);
+#else
+  return c == kPathSeparator;
+#endif
+}
+
+// Returns the current working directory, or "" if unsuccessful.
+FilePath FilePath::GetCurrentDir() {
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE doesn't have a current directory, so we just return
+  // something reasonable.
+  return FilePath(kCurrentDirectoryString);
+#elif GTEST_OS_WINDOWS
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#else
+  char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
+  return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns a copy of the FilePath with the case-insensitive extension removed.
+// Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+// FilePath("dir/file"). If a case-insensitive extension is not
+// found, returns a copy of the original FilePath.
+FilePath FilePath::RemoveExtension(const char* extension) const {
+  const std::string dot_extension = std::string(".") + extension;
+  if (String::EndsWithCaseInsensitive(pathname_, dot_extension)) {
+    return FilePath(pathname_.substr(
+        0, pathname_.length() - dot_extension.length()));
+  }
+  return *this;
+}
+
+// Returns a pointer to the last occurence of a valid path separator in
+// the FilePath. On Windows, for example, both '/' and '\' are valid path
+// separators. Returns NULL if no path separator was found.
+const char* FilePath::FindLastPathSeparator() const {
+  const char* const last_sep = strrchr(c_str(), kPathSeparator);
+#if GTEST_HAS_ALT_PATH_SEP_
+  const char* const last_alt_sep = strrchr(c_str(), kAlternatePathSeparator);
+  // Comparing two pointers of which only one is NULL is undefined.
+  if (last_alt_sep != NULL &&
+      (last_sep == NULL || last_alt_sep > last_sep)) {
+    return last_alt_sep;
+  }
+#endif
+  return last_sep;
+}
+
+// Returns a copy of the FilePath with the directory part removed.
+// Example: FilePath("path/to/file").RemoveDirectoryName() returns
+// FilePath("file"). If there is no directory part ("just_a_file"), it returns
+// the FilePath unmodified. If there is no file part ("just_a_dir/") it
+// returns an empty FilePath ("").
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveDirectoryName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  return last_sep ? FilePath(last_sep + 1) : *this;
+}
+
+// RemoveFileName returns the directory path with the filename removed.
+// Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+// If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+// FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+// not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+// On Windows platform, '\' is the path separator, otherwise it is '/'.
+FilePath FilePath::RemoveFileName() const {
+  const char* const last_sep = FindLastPathSeparator();
+  std::string dir;
+  if (last_sep) {
+    dir = std::string(c_str(), last_sep + 1 - c_str());
+  } else {
+    dir = kCurrentDirectoryString;
+  }
+  return FilePath(dir);
+}
+
+// Helper functions for naming files in a directory for xml output.
+
+// Given directory = "dir", base_name = "test", number = 0,
+// extension = "xml", returns "dir/test.xml". If number is greater
+// than zero (e.g., 12), returns "dir/test_12.xml".
+// On Windows platform, uses \ as the separator rather than /.
+FilePath FilePath::MakeFileName(const FilePath& directory,
+                                const FilePath& base_name,
+                                int number,
+                                const char* extension) {
+  std::string file;
+  if (number == 0) {
+    file = base_name.string() + "." + extension;
+  } else {
+    file = base_name.string() + "_" + StreamableToString(number)
+        + "." + extension;
+  }
+  return ConcatPaths(directory, FilePath(file));
+}
+
+// Given directory = "dir", relative_path = "test.xml", returns "dir/test.xml".
+// On Windows, uses \ as the separator rather than /.
+FilePath FilePath::ConcatPaths(const FilePath& directory,
+                               const FilePath& relative_path) {
+  if (directory.IsEmpty())
+    return relative_path;
+  const FilePath dir(directory.RemoveTrailingPathSeparator());
+  return FilePath(dir.string() + kPathSeparator + relative_path.string());
+}
+
+// Returns true if pathname describes something findable in the file-system,
+// either a file, directory, or whatever.
+bool FilePath::FileOrDirectoryExists() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(pathname_.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  return attributes != kInvalidFileAttributes;
+#else
+  posix::StatStruct file_stat;
+  return posix::Stat(pathname_.c_str(), &file_stat) == 0;
+#endif  // GTEST_OS_WINDOWS_MOBILE
+}
+
+// Returns true if pathname describes a directory in the file-system
+// that exists.
+bool FilePath::DirectoryExists() const {
+  bool result = false;
+#if GTEST_OS_WINDOWS
+  // Don't strip off trailing separator if path is a root directory on
+  // Windows (like "C:\\").
+  const FilePath& path(IsRootDirectory() ? *this :
+                                           RemoveTrailingPathSeparator());
+#else
+  const FilePath& path(*this);
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+  LPCWSTR unicode = String::AnsiToUtf16(path.c_str());
+  const DWORD attributes = GetFileAttributes(unicode);
+  delete [] unicode;
+  if ((attributes != kInvalidFileAttributes) &&
+      (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+    result = true;
+  }
+#else
+  posix::StatStruct file_stat;
+  result = posix::Stat(path.c_str(), &file_stat) == 0 &&
+      posix::IsDir(file_stat);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  return result;
+}
+
+// Returns true if pathname describes a root directory. (Windows has one
+// root directory per disk drive.)
+bool FilePath::IsRootDirectory() const {
+#if GTEST_OS_WINDOWS
+  // TODO(wan@google.com): on Windows a network share like
+  // \\server\share can be a root directory, although it cannot be the
+  // current directory.  Handle this properly.
+  return pathname_.length() == 3 && IsAbsolutePath();
+#else
+  return pathname_.length() == 1 && IsPathSeparator(pathname_.c_str()[0]);
+#endif
+}
+
+// Returns true if pathname describes an absolute path.
+bool FilePath::IsAbsolutePath() const {
+  const char* const name = pathname_.c_str();
+#if GTEST_OS_WINDOWS
+  return pathname_.length() >= 3 &&
+     ((name[0] >= 'a' && name[0] <= 'z') ||
+      (name[0] >= 'A' && name[0] <= 'Z')) &&
+     name[1] == ':' &&
+     IsPathSeparator(name[2]);
+#else
+  return IsPathSeparator(name[0]);
+#endif
+}
+
+// Returns a pathname for a file that does not currently exist. The pathname
+// will be directory/base_name.extension or
+// directory/base_name_<number>.extension if directory/base_name.extension
+// already exists. The number will be incremented until a pathname is found
+// that does not already exist.
+// Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+// There could be a race condition if two or more processes are calling this
+// function at the same time -- they could both pick the same filename.
+FilePath FilePath::GenerateUniqueFileName(const FilePath& directory,
+                                          const FilePath& base_name,
+                                          const char* extension) {
+  FilePath full_pathname;
+  int number = 0;
+  do {
+    full_pathname.Set(MakeFileName(directory, base_name, number++, extension));
+  } while (full_pathname.FileOrDirectoryExists());
+  return full_pathname;
+}
+
+// Returns true if FilePath ends with a path separator, which indicates that
+// it is intended to represent a directory. Returns false otherwise.
+// This does NOT check that a directory (or file) actually exists.
+bool FilePath::IsDirectory() const {
+  return !pathname_.empty() &&
+         IsPathSeparator(pathname_.c_str()[pathname_.length() - 1]);
+}
+
+// Create directories so that path exists. Returns true if successful or if
+// the directories already exist; returns false if unable to create directories
+// for any reason.
+bool FilePath::CreateDirectoriesRecursively() const {
+  if (!this->IsDirectory()) {
+    return false;
+  }
+
+  if (pathname_.length() == 0 || this->DirectoryExists()) {
+    return true;
+  }
+
+  const FilePath parent(this->RemoveTrailingPathSeparator().RemoveFileName());
+  return parent.CreateDirectoriesRecursively() && this->CreateFolder();
+}
+
+// Create the directory so that path exists. Returns true if successful or
+// if the directory already exists; returns false if unable to create the
+// directory for any reason, including if the parent directory does not
+// exist. Not named "CreateDirectory" because that's a macro on Windows.
+bool FilePath::CreateFolder() const {
+#if GTEST_OS_WINDOWS_MOBILE
+  FilePath removed_sep(this->RemoveTrailingPathSeparator());
+  LPCWSTR unicode = String::AnsiToUtf16(removed_sep.c_str());
+  int result = CreateDirectory(unicode, NULL) ? 0 : -1;
+  delete [] unicode;
+#elif GTEST_OS_WINDOWS
+  int result = _mkdir(pathname_.c_str());
+#else
+  int result = mkdir(pathname_.c_str(), 0777);
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+  if (result == -1) {
+    return this->DirectoryExists();  // An error is OK if the directory exists.
+  }
+  return true;  // No error.
+}
+
+// If input name has a trailing separator character, remove it and return the
+// name, otherwise return the name string unmodified.
+// On Windows platform, uses \ as the separator, other platforms use /.
+FilePath FilePath::RemoveTrailingPathSeparator() const {
+  return IsDirectory()
+      ? FilePath(pathname_.substr(0, pathname_.length() - 1))
+      : *this;
+}
+
+// Removes any redundant separators that might be in the pathname.
+// For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+// redundancies that might be in a pathname involving "." or "..".
+// TODO(wan@google.com): handle Windows network shares (e.g. \\server\share).
+void FilePath::Normalize() {
+  if (pathname_.c_str() == NULL) {
+    pathname_ = "";
+    return;
+  }
+  const char* src = pathname_.c_str();
+  char* const dest = new char[pathname_.length() + 1];
+  char* dest_ptr = dest;
+  memset(dest_ptr, 0, pathname_.length() + 1);
+
+  while (*src != '\0') {
+    *dest_ptr = *src;
+    if (!IsPathSeparator(*src)) {
+      src++;
+    } else {
+#if GTEST_HAS_ALT_PATH_SEP_
+      if (*dest_ptr == kAlternatePathSeparator) {
+        *dest_ptr = kPathSeparator;
+      }
+#endif
+      while (IsPathSeparator(*src))
+        src++;
+    }
+    dest_ptr++;
+  }
+  *dest_ptr = '\0';
+  pathname_ = dest;
+  delete[] dest;
+}
+
+}  // namespace internal
+}  // namespace testing
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#if GTEST_OS_WINDOWS_MOBILE
+# include <windows.h>  // For TerminateProcess()
+#elif GTEST_OS_WINDOWS
+# include <io.h>
+# include <sys/stat.h>
+#else
+# include <unistd.h>
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+#if GTEST_OS_MAC
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
+#endif  // GTEST_OS_MAC
+
+#if GTEST_OS_QNX
+# include <devctl.h>
+# include <sys/procfs.h>
+#endif  // GTEST_OS_QNX
+
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+namespace internal {
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC and C++Builder do not provide a definition of STDERR_FILENO.
+const int kStdOutFileno = 1;
+const int kStdErrFileno = 2;
+#else
+const int kStdOutFileno = STDOUT_FILENO;
+const int kStdErrFileno = STDERR_FILENO;
+#endif  // _MSC_VER
+
+#if GTEST_OS_MAC
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const task_t task = mach_task_self();
+  mach_msg_type_number_t thread_count;
+  thread_act_array_t thread_list;
+  const kern_return_t status = task_threads(task, &thread_list, &thread_count);
+  if (status == KERN_SUCCESS) {
+    // task_threads allocates resources in thread_list and we need to free them
+    // to avoid leaks.
+    vm_deallocate(task,
+                  reinterpret_cast<vm_address_t>(thread_list),
+                  sizeof(thread_t) * thread_count);
+    return static_cast<size_t>(thread_count);
+  } else {
+    return 0;
+  }
+}
+
+#elif GTEST_OS_QNX
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+  const int fd = open("/proc/self/as", O_RDONLY);
+  if (fd < 0) {
+    return 0;
+  }
+  procfs_info process_info;
+  const int status =
+      devctl(fd, DCMD_PROC_INFO, &process_info, sizeof(process_info), NULL);
+  close(fd);
+  if (status == EOK) {
+    return static_cast<size_t>(process_info.num_threads);
+  } else {
+    return 0;
+  }
+}
+
+#else
+
+size_t GetThreadCount() {
+  // There's no portable way to detect the number of threads, so we just
+  // return 0 to indicate that we cannot detect it.
+  return 0;
+}
+
+#endif  // GTEST_OS_MAC
+
+#if GTEST_USES_POSIX_RE
+
+// Implements RE.  Currently only needed for death tests.
+
+RE::~RE() {
+  if (is_valid_) {
+    // regfree'ing an invalid regex might crash because the content
+    // of the regex is undefined. Since the regex's are essentially
+    // the same, one cannot be valid (or invalid) without the other
+    // being so too.
+    regfree(&partial_regex_);
+    regfree(&full_regex_);
+  }
+  free(const_cast<char*>(pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.full_regex_, str, 1, &match, 0) == 0;
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  if (!re.is_valid_) return false;
+
+  regmatch_t match;
+  return regexec(&re.partial_regex_, str, 1, &match, 0) == 0;
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = posix::StrDup(regex);
+
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match.
+  const size_t full_regex_len = strlen(regex) + 10;
+  char* const full_pattern = new char[full_regex_len];
+
+  snprintf(full_pattern, full_regex_len, "^(%s)$", regex);
+  is_valid_ = regcomp(&full_regex_, full_pattern, REG_EXTENDED) == 0;
+  // We want to call regcomp(&partial_regex_, ...) even if the
+  // previous expression returns false.  Otherwise partial_regex_ may
+  // not be properly initialized can may cause trouble when it's
+  // freed.
+  //
+  // Some implementation of POSIX regex (e.g. on at least some
+  // versions of Cygwin) doesn't accept the empty string as a valid
+  // regex.  We change it to an equivalent form "()" to be safe.
+  if (is_valid_) {
+    const char* const partial_regex = (*regex == '\0') ? "()" : regex;
+    is_valid_ = regcomp(&partial_regex_, partial_regex, REG_EXTENDED) == 0;
+  }
+  EXPECT_TRUE(is_valid_)
+      << "Regular expression \"" << regex
+      << "\" is not a valid POSIX Extended regular expression.";
+
+  delete[] full_pattern;
+}
+
+#elif GTEST_USES_SIMPLE_RE
+
+// Returns true iff ch appears anywhere in str (excluding the
+// terminating '\0' character).
+bool IsInSet(char ch, const char* str) {
+  return ch != '\0' && strchr(str, ch) != NULL;
+}
+
+// Returns true iff ch belongs to the given classification.  Unlike
+// similar functions in <ctype.h>, these aren't affected by the
+// current locale.
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
+  return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
+}
+bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
+  return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
+      ('0' <= ch && ch <= '9') || ch == '_';
+}
+
+// Returns true iff "\\c" is a supported escape sequence.
+bool IsValidEscape(char c) {
+  return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+}
+
+// Returns true iff the given atom (specified by escaped and pattern)
+// matches ch.  The result is undefined if the atom is invalid.
+bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
+  if (escaped) {  // "\\p" where p is pattern_char.
+    switch (pattern_char) {
+      case 'd': return IsAsciiDigit(ch);
+      case 'D': return !IsAsciiDigit(ch);
+      case 'f': return ch == '\f';
+      case 'n': return ch == '\n';
+      case 'r': return ch == '\r';
+      case 's': return IsAsciiWhiteSpace(ch);
+      case 'S': return !IsAsciiWhiteSpace(ch);
+      case 't': return ch == '\t';
+      case 'v': return ch == '\v';
+      case 'w': return IsAsciiWordChar(ch);
+      case 'W': return !IsAsciiWordChar(ch);
+    }
+    return IsAsciiPunct(pattern_char) && pattern_char == ch;
+  }
+
+  return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
+}
+
+// Helper function used by ValidateRegex() to format error messages.
+std::string FormatRegexSyntaxError(const char* regex, int index) {
+  return (Message() << "Syntax error at index " << index
+          << " in simple regular expression \"" << regex << "\": ").GetString();
+}
+
+// Generates non-fatal failures and returns false if regex is invalid;
+// otherwise returns true.
+bool ValidateRegex(const char* regex) {
+  if (regex == NULL) {
+    // TODO(wan@google.com): fix the source file location in the
+    // assertion failures to match where the regex is used in user
+    // code.
+    ADD_FAILURE() << "NULL is not a valid simple regular expression.";
+    return false;
+  }
+
+  bool is_valid = true;
+
+  // True iff ?, *, or + can follow the previous atom.
+  bool prev_repeatable = false;
+  for (int i = 0; regex[i]; i++) {
+    if (regex[i] == '\\') {  // An escape sequence
+      i++;
+      if (regex[i] == '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "'\\' cannot appear at the end.";
+        return false;
+      }
+
+      if (!IsValidEscape(regex[i])) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i - 1)
+                      << "invalid escape sequence \"\\" << regex[i] << "\".";
+        is_valid = false;
+      }
+      prev_repeatable = true;
+    } else {  // Not an escape sequence.
+      const char ch = regex[i];
+
+      if (ch == '^' && i > 0) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'^' can only appear at the beginning.";
+        is_valid = false;
+      } else if (ch == '$' && regex[i + 1] != '\0') {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'$' can only appear at the end.";
+        is_valid = false;
+      } else if (IsInSet(ch, "()[]{}|")) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' is unsupported.";
+        is_valid = false;
+      } else if (IsRepeat(ch) && !prev_repeatable) {
+        ADD_FAILURE() << FormatRegexSyntaxError(regex, i)
+                      << "'" << ch << "' can only follow a repeatable token.";
+        is_valid = false;
+      }
+
+      prev_repeatable = !IsInSet(ch, "^$?*+");
+    }
+  }
+
+  return is_valid;
+}
+
+// Matches a repeated regex atom followed by a valid simple regular
+// expression.  The regex atom is defined as c if escaped is false,
+// or \c otherwise.  repeat is the repetition meta character (?, *,
+// or +).  The behavior is undefined if str contains too many
+// characters to be indexable by size_t, in which case the test will
+// probably time out anyway.  We are fine with this limitation as
+// std::string has it too.
+bool MatchRepetitionAndRegexAtHead(
+    bool escaped, char c, char repeat, const char* regex,
+    const char* str) {
+  const size_t min_count = (repeat == '+') ? 1 : 0;
+  const size_t max_count = (repeat == '?') ? 1 :
+      static_cast<size_t>(-1) - 1;
+  // We cannot call numeric_limits::max() as it conflicts with the
+  // max() macro on Windows.
+
+  for (size_t i = 0; i <= max_count; ++i) {
+    // We know that the atom matches each of the first i characters in str.
+    if (i >= min_count && MatchRegexAtHead(regex, str + i)) {
+      // We have enough matches at the head, and the tail matches too.
+      // Since we only care about *whether* the pattern matches str
+      // (as opposed to *how* it matches), there is no need to find a
+      // greedy match.
+      return true;
+    }
+    if (str[i] == '\0' || !AtomMatchesChar(escaped, c, str[i]))
+      return false;
+  }
+  return false;
+}
+
+// Returns true iff regex matches a prefix of str.  regex must be a
+// valid simple regular expression and not start with "^", or the
+// result is undefined.
+bool MatchRegexAtHead(const char* regex, const char* str) {
+  if (*regex == '\0')  // An empty regex matches a prefix of anything.
+    return true;
+
+  // "$" only matches the end of a string.  Note that regex being
+  // valid guarantees that there's nothing after "$" in it.
+  if (*regex == '$')
+    return *str == '\0';
+
+  // Is the first thing in regex an escape sequence?
+  const bool escaped = *regex == '\\';
+  if (escaped)
+    ++regex;
+  if (IsRepeat(regex[1])) {
+    // MatchRepetitionAndRegexAtHead() calls MatchRegexAtHead(), so
+    // here's an indirect recursion.  It terminates as the regex gets
+    // shorter in each recursion.
+    return MatchRepetitionAndRegexAtHead(
+        escaped, regex[0], regex[1], regex + 2, str);
+  } else {
+    // regex isn't empty, isn't "$", and doesn't start with a
+    // repetition.  We match the first atom of regex with the first
+    // character of str and recurse.
+    return (*str != '\0') && AtomMatchesChar(escaped, *regex, *str) &&
+        MatchRegexAtHead(regex + 1, str + 1);
+  }
+}
+
+// Returns true iff regex matches any substring of str.  regex must be
+// a valid simple regular expression, or the result is undefined.
+//
+// The algorithm is recursive, but the recursion depth doesn't exceed
+// the regex length, so we won't need to worry about running out of
+// stack space normally.  In rare cases the time complexity can be
+// exponential with respect to the regex length + the string length,
+// but usually it's must faster (often close to linear).
+bool MatchRegexAnywhere(const char* regex, const char* str) {
+  if (regex == NULL || str == NULL)
+    return false;
+
+  if (*regex == '^')
+    return MatchRegexAtHead(regex + 1, str);
+
+  // A successful match can be anywhere in str.
+  do {
+    if (MatchRegexAtHead(regex, str))
+      return true;
+  } while (*str++ != '\0');
+  return false;
+}
+
+// Implements the RE class.
+
+RE::~RE() {
+  free(const_cast<char*>(pattern_));
+  free(const_cast<char*>(full_pattern_));
+}
+
+// Returns true iff regular expression re matches the entire str.
+bool RE::FullMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.full_pattern_, str);
+}
+
+// Returns true iff regular expression re matches a substring of str
+// (including str itself).
+bool RE::PartialMatch(const char* str, const RE& re) {
+  return re.is_valid_ && MatchRegexAnywhere(re.pattern_, str);
+}
+
+// Initializes an RE from its string representation.
+void RE::Init(const char* regex) {
+  pattern_ = full_pattern_ = NULL;
+  if (regex != NULL) {
+    pattern_ = posix::StrDup(regex);
+  }
+
+  is_valid_ = ValidateRegex(regex);
+  if (!is_valid_) {
+    // No need to calculate the full pattern when the regex is invalid.
+    return;
+  }
+
+  const size_t len = strlen(regex);
+  // Reserves enough bytes to hold the regular expression used for a
+  // full match: we need space to prepend a '^', append a '$', and
+  // terminate the string with '\0'.
+  char* buffer = static_cast<char*>(malloc(len + 3));
+  full_pattern_ = buffer;
+
+  if (*regex != '^')
+    *buffer++ = '^';  // Makes sure full_pattern_ starts with '^'.
+
+  // We don't use snprintf or strncpy, as they trigger a warning when
+  // compiled with VC++ 8.0.
+  memcpy(buffer, regex, len);
+  buffer += len;
+
+  if (len == 0 || regex[len - 1] != '$')
+    *buffer++ = '$';  // Makes sure full_pattern_ ends with '$'.
+
+  *buffer = '\0';
+}
+
+#endif  // GTEST_USES_POSIX_RE
+
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+  const std::string file_name(file == NULL ? kUnknownFile : file);
+
+  if (line < 0) {
+    return file_name + ":";
+  }
+#ifdef _MSC_VER
+  return file_name + "(" + StreamableToString(line) + "):";
+#else
+  return file_name + ":" + StreamableToString(line) + ":";
+#endif  // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+    const char* file, int line) {
+  const std::string file_name(file == NULL ? kUnknownFile : file);
+
+  if (line < 0)
+    return file_name;
+  else
+    return file_name + ":" + StreamableToString(line);
+}
+
+
+GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
+    : severity_(severity) {
+  const char* const marker =
+      severity == GTEST_INFO ?    "[  INFO ]" :
+      severity == GTEST_WARNING ? "[WARNING]" :
+      severity == GTEST_ERROR ?   "[ ERROR ]" : "[ FATAL ]";
+  GetStream() << ::std::endl << marker << " "
+              << FormatFileLocation(file, line).c_str() << ": ";
+}
+
+// Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+GTestLog::~GTestLog() {
+  GetStream() << ::std::endl;
+  if (severity_ == GTEST_FATAL) {
+    fflush(stderr);
+    posix::Abort();
+  }
+}
+// Disable Microsoft deprecation warnings for POSIX functions called from
+// this class (creat, dup, dup2, and close)
+#ifdef _MSC_VER
+# pragma warning(push)
+# pragma warning(disable: 4996)
+#endif  // _MSC_VER
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Object that captures an output stream (stdout/stderr).
+class CapturedStream {
+ public:
+  // The ctor redirects the stream to a temporary file.
+  explicit CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
+# if GTEST_OS_WINDOWS
+    char temp_dir_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+    char temp_file_path[MAX_PATH + 1] = { '\0' };  // NOLINT
+
+    ::GetTempPathA(sizeof(temp_dir_path), temp_dir_path);
+    const UINT success = ::GetTempFileNameA(temp_dir_path,
+                                            "gtest_redir",
+                                            0,  // Generate unique file name.
+                                            temp_file_path);
+    GTEST_CHECK_(success != 0)
+        << "Unable to create a temporary file in " << temp_dir_path;
+    const int captured_fd = creat(temp_file_path, _S_IREAD | _S_IWRITE);
+    GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
+                                    << temp_file_path;
+    filename_ = temp_file_path;
+# else
+    // There's no guarantee that a test has write access to the current
+    // directory, so we create the temporary file in the /tmp directory
+    // instead. We use /tmp on most systems, and /sdcard on Android.
+    // That's because Android doesn't have /tmp.
+#  if GTEST_OS_LINUX_ANDROID
+    // Note: Android applications are expected to call the framework's
+    // Context.getExternalStorageDirectory() method through JNI to get
+    // the location of the world-writable SD Card directory. However,
+    // this requires a Context handle, which cannot be retrieved
+    // globally from native code. Doing so also precludes running the
+    // code as part of a regular standalone executable, which doesn't
+    // run in a Dalvik process (e.g. when running it through 'adb shell').
+    //
+    // The location /sdcard is directly accessible from native code
+    // and is the only location (unofficially) supported by the Android
+    // team. It's generally a symlink to the real SD Card mount point
+    // which can be /mnt/sdcard, /mnt/sdcard0, /system/media/sdcard, or
+    // other OEM-customized locations. Never rely on these, and always
+    // use /sdcard.
+    char name_template[] = "/sdcard/gtest_captured_stream.XXXXXX";
+#  else
+    char name_template[] = "/tmp/captured_stream.XXXXXX";
+#  endif  // GTEST_OS_LINUX_ANDROID
+    const int captured_fd = mkstemp(name_template);
+    filename_ = name_template;
+# endif  // GTEST_OS_WINDOWS
+    fflush(NULL);
+    dup2(captured_fd, fd_);
+    close(captured_fd);
+  }
+
+  ~CapturedStream() {
+    remove(filename_.c_str());
+  }
+
+  std::string GetCapturedString() {
+    if (uncaptured_fd_ != -1) {
+      // Restores the original stream.
+      fflush(NULL);
+      dup2(uncaptured_fd_, fd_);
+      close(uncaptured_fd_);
+      uncaptured_fd_ = -1;
+    }
+
+    FILE* const file = posix::FOpen(filename_.c_str(), "r");
+    const std::string content = ReadEntireFile(file);
+    posix::FClose(file);
+    return content;
+  }
+
+ private:
+  // Reads the entire content of a file as an std::string.
+  static std::string ReadEntireFile(FILE* file);
+
+  // Returns the size (in bytes) of a file.
+  static size_t GetFileSize(FILE* file);
+
+  const int fd_;  // A stream to capture.
+  int uncaptured_fd_;
+  // Name of the temporary file holding the stderr output.
+  ::std::string filename_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
+};
+
+// Returns the size (in bytes) of a file.
+size_t CapturedStream::GetFileSize(FILE* file) {
+  fseek(file, 0, SEEK_END);
+  return static_cast<size_t>(ftell(file));
+}
+
+// Reads the entire content of a file as a string.
+std::string CapturedStream::ReadEntireFile(FILE* file) {
+  const size_t file_size = GetFileSize(file);
+  char* const buffer = new char[file_size];
+
+  size_t bytes_last_read = 0;  // # of bytes read in the last fread()
+  size_t bytes_read = 0;       // # of bytes read so far
+
+  fseek(file, 0, SEEK_SET);
+
+  // Keeps reading the file until we cannot read further or the
+  // pre-determined file size is reached.
+  do {
+    bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
+    bytes_read += bytes_last_read;
+  } while (bytes_last_read > 0 && bytes_read < file_size);
+
+  const std::string content(buffer, bytes_read);
+  delete[] buffer;
+
+  return content;
+}
+
+# ifdef _MSC_VER
+#  pragma warning(pop)
+# endif  // _MSC_VER
+
+static CapturedStream* g_captured_stderr = NULL;
+static CapturedStream* g_captured_stdout = NULL;
+
+// Starts capturing an output stream (stdout/stderr).
+void CaptureStream(int fd, const char* stream_name, CapturedStream** stream) {
+  if (*stream != NULL) {
+    GTEST_LOG_(FATAL) << "Only one " << stream_name
+                      << " capturer can exist at a time.";
+  }
+  *stream = new CapturedStream(fd);
+}
+
+// Stops capturing the output stream and returns the captured string.
+std::string GetCapturedStream(CapturedStream** captured_stream) {
+  const std::string content = (*captured_stream)->GetCapturedString();
+
+  delete *captured_stream;
+  *captured_stream = NULL;
+
+  return content;
+}
+
+// Starts capturing stdout.
+void CaptureStdout() {
+  CaptureStream(kStdOutFileno, "stdout", &g_captured_stdout);
+}
+
+// Starts capturing stderr.
+void CaptureStderr() {
+  CaptureStream(kStdErrFileno, "stderr", &g_captured_stderr);
+}
+
+// Stops capturing stdout and returns the captured string.
+std::string GetCapturedStdout() {
+  return GetCapturedStream(&g_captured_stdout);
+}
+
+// Stops capturing stderr and returns the captured string.
+std::string GetCapturedStderr() {
+  return GetCapturedStream(&g_captured_stderr);
+}
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+#if GTEST_HAS_DEATH_TEST
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+::std::vector<testing::internal::string> g_argvs;
+
+static const ::std::vector<testing::internal::string>* g_injected_test_argvs =
+                                        NULL;  // Owned.
+
+void SetInjectableArgvs(const ::std::vector<testing::internal::string>* argvs) {
+  if (g_injected_test_argvs != argvs)
+    delete g_injected_test_argvs;
+  g_injected_test_argvs = argvs;
+}
+
+const ::std::vector<testing::internal::string>& GetInjectableArgvs() {
+  if (g_injected_test_argvs != NULL) {
+    return *g_injected_test_argvs;
+  }
+  return g_argvs;
+}
+#endif  // GTEST_HAS_DEATH_TEST
+
+#if GTEST_OS_WINDOWS_MOBILE
+namespace posix {
+void Abort() {
+  DebugBreak();
+  TerminateProcess(GetCurrentProcess(), 1);
+}
+}  // namespace posix
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+// Returns the name of the environment variable corresponding to the
+// given flag.  For example, FlagToEnvVar("foo") will return
+// "GTEST_FOO" in the open-source version.
+static std::string FlagToEnvVar(const char* flag) {
+  const std::string full_flag =
+      (Message() << GTEST_FLAG_PREFIX_ << flag).GetString();
+
+  Message env_var;
+  for (size_t i = 0; i != full_flag.length(); i++) {
+    env_var << ToUpper(full_flag.c_str()[i]);
+  }
+
+  return env_var.GetString();
+}
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes
+// the result to *value and returns true; otherwise leaves *value
+// unchanged and returns false.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value) {
+  // Parses the environment variable as a decimal integer.
+  char* end = NULL;
+  const long long_value = strtol(str, &end, 10);  // NOLINT
+
+  // Has strtol() consumed all characters in the string?
+  if (*end != '\0') {
+    // No - an invalid character was encountered.
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value \"" << str << "\".\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  // Is the parsed value in the range of an Int32?
+  const Int32 result = static_cast<Int32>(long_value);
+  if (long_value == LONG_MAX || long_value == LONG_MIN ||
+      // The parsed value overflows as a long.  (strtol() returns
+      // LONG_MAX or LONG_MIN when the input overflows.)
+      result != long_value
+      // The parsed value overflows as an Int32.
+      ) {
+    Message msg;
+    msg << "WARNING: " << src_text
+        << " is expected to be a 32-bit integer, but actually"
+        << " has value " << str << ", which overflows.\n";
+    printf("%s", msg.GetString().c_str());
+    fflush(stdout);
+    return false;
+  }
+
+  *value = result;
+  return true;
+}
+
+// Reads and returns the Boolean environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+//
+// The value is considered true iff it's not "0".
+bool BoolFromGTestEnv(const char* flag, bool default_value) {
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  return string_value == NULL ?
+      default_value : strcmp(string_value, "0") != 0;
+}
+
+// Reads and returns a 32-bit integer stored in the environment
+// variable corresponding to the given flag; if it isn't set or
+// doesn't represent a valid 32-bit integer, returns default_value.
+Int32 Int32FromGTestEnv(const char* flag, Int32 default_value) {
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const string_value = posix::GetEnv(env_var.c_str());
+  if (string_value == NULL) {
+    // The environment variable is not set.
+    return default_value;
+  }
+
+  Int32 result = default_value;
+  if (!ParseInt32(Message() << "Environment variable " << env_var,
+                  string_value, &result)) {
+    printf("The default value %s is used.\n",
+           (Message() << default_value).GetString().c_str());
+    fflush(stdout);
+    return default_value;
+  }
+
+  return result;
+}
+
+// Reads and returns the string environment variable corresponding to
+// the given flag; if it's not set, returns default_value.
+const char* StringFromGTestEnv(const char* flag, const char* default_value) {
+  const std::string env_var = FlagToEnvVar(flag);
+  const char* const value = posix::GetEnv(env_var.c_str());
+  return value == NULL ? default_value : value;
+}
+
+}  // namespace internal
+}  // namespace testing
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise.  A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include <ctype.h>
+#include <stdio.h>
+#include <ostream>  // NOLINT
+#include <string>
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+// Prints a segment of bytes in the given object.
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+                                size_t count, ostream* os) {
+  char text[5] = "";
+  for (size_t i = 0; i != count; i++) {
+    const size_t j = start + i;
+    if (i != 0) {
+      // Organizes the bytes into groups of 2 for easy parsing by
+      // human.
+      if ((j % 2) == 0)
+        *os << ' ';
+      else
+        *os << '-';
+    }
+    GTEST_SNPRINTF_(text, sizeof(text), "%02X", obj_bytes[j]);
+    *os << text;
+  }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+                              ostream* os) {
+  // Tells the user how big the object is.
+  *os << count << "-byte object <";
+
+  const size_t kThreshold = 132;
+  const size_t kChunkSize = 64;
+  // If the object size is bigger than kThreshold, we'll have to omit
+  // some details by printing only the first and the last kChunkSize
+  // bytes.
+  // TODO(wan): let the user control the threshold using a flag.
+  if (count < kThreshold) {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+  } else {
+    PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+    *os << " ... ";
+    // Rounds up to 2-byte boundary.
+    const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+    PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+  }
+  *os << ">";
+}
+
+}  // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object.  The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+                          ostream* os) {
+  PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+}  // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+//   - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+//   - as a hexidecimal escape sequence (e.g. '\x7F'), or
+//   - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+  kAsIs,
+  kHexEscape,
+  kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character.  We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+  return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+  switch (static_cast<wchar_t>(c)) {
+    case L'\0':
+      *os << "\\0";
+      break;
+    case L'\'':
+      *os << "\\'";
+      break;
+    case L'\\':
+      *os << "\\\\";
+      break;
+    case L'\a':
+      *os << "\\a";
+      break;
+    case L'\b':
+      *os << "\\b";
+      break;
+    case L'\f':
+      *os << "\\f";
+      break;
+    case L'\n':
+      *os << "\\n";
+      break;
+    case L'\r':
+      *os << "\\r";
+      break;
+    case L'\t':
+      *os << "\\t";
+      break;
+    case L'\v':
+      *os << "\\v";
+      break;
+    default:
+      if (IsPrintableAscii(c)) {
+        *os << static_cast<char>(c);
+        return kAsIs;
+      } else {
+        *os << "\\x" + String::FormatHexInt(static_cast<UnsignedChar>(c));
+        return kHexEscape;
+      }
+  }
+  return kSpecialEscape;
+}
+
+// Prints a wchar_t c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(wchar_t c, ostream* os) {
+  switch (c) {
+    case L'\'':
+      *os << "'";
+      return kAsIs;
+    case L'"':
+      *os << "\\\"";
+      return kSpecialEscape;
+    default:
+      return PrintAsCharLiteralTo<wchar_t>(c, os);
+  }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsStringLiteralTo(char c, ostream* os) {
+  return PrintAsStringLiteralTo(
+      static_cast<wchar_t>(static_cast<unsigned char>(c)), os);
+}
+
+// Prints a wide or narrow character c and its code.  '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence.  The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+  // First, print c as a literal in the most readable form we can find.
+  *os << ((sizeof(c) > 1) ? "L'" : "'");
+  const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+  *os << "'";
+
+  // To aid user debugging, we also print c's code in decimal, unless
+  // it's 0 (in which case c was printed as '\\0', making the code
+  // obvious).
+  if (c == 0)
+    return;
+  *os << " (" << static_cast<int>(c);
+
+  // For more convenience, we print c's code again in hexidecimal,
+  // unless c was already printed in the form '\x##' or the code is in
+  // [1, 9].
+  if (format == kHexEscape || (1 <= c && c <= 9)) {
+    // Do nothing.
+  } else {
+    *os << ", 0x" << String::FormatHexInt(static_cast<UnsignedChar>(c));
+  }
+  *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+  PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code.  L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+  PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream.  CharType must be either
+// char or wchar_t.
+// The array starts at begin, the length is len, it may include '\0' characters
+// and may not be NUL-terminated.
+template <typename CharType>
+static void PrintCharsAsStringTo(
+    const CharType* begin, size_t len, ostream* os) {
+  const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
+  *os << kQuoteBegin;
+  bool is_previous_hex = false;
+  for (size_t index = 0; index < len; ++index) {
+    const CharType cur = begin[index];
+    if (is_previous_hex && IsXDigit(cur)) {
+      // Previous character is of '\x..' form and this character can be
+      // interpreted as another hexadecimal digit in its number. Break string to
+      // disambiguate.
+      *os << "\" " << kQuoteBegin;
+    }
+    is_previous_hex = PrintAsStringLiteralTo(cur, os) == kHexEscape;
+  }
+  *os << "\"";
+}
+
+// Prints a (const) char/wchar_t array of 'len' elements, starting at address
+// 'begin'.  CharType must be either char or wchar_t.
+template <typename CharType>
+static void UniversalPrintCharArray(
+    const CharType* begin, size_t len, ostream* os) {
+  // The code
+  //   const char kFoo[] = "foo";
+  // generates an array of 4, not 3, elements, with the last one being '\0'.
+  //
+  // Therefore when printing a char array, we don't print the last element if
+  // it's '\0', such that the output matches the string literal as it's
+  // written in the source code.
+  if (len > 0 && begin[len - 1] == '\0') {
+    PrintCharsAsStringTo(begin, len - 1, os);
+    return;
+  }
+
+  // If, however, the last element in the array is not '\0', e.g.
+  //    const char kFoo[] = { 'f', 'o', 'o' };
+  // we must print the entire array.  We also print a message to indicate
+  // that the array is not NUL-terminated.
+  PrintCharsAsStringTo(begin, len, os);
+  *os << " (no terminating NUL)";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints a (const) wchar_t array of 'len' elements, starting at address
+// 'begin'.
+void UniversalPrintArray(const wchar_t* begin, size_t len, ostream* os) {
+  UniversalPrintCharArray(begin, len, os);
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, strlen(s), os);
+  }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+  if (s == NULL) {
+    *os << "NULL";
+  } else {
+    *os << ImplicitCast_<const void*>(s) << " pointing to ";
+    PrintCharsAsStringTo(s, wcslen(s), os);
+  }
+}
+#endif  // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+  PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+}  // namespace internal
+
+}  // namespace testing
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+// The Google C++ Testing Framework (Google Test)
+
+
+// Indicates that this translation unit is part of Google Test's
+// implementation.  It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error.  This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#undef GTEST_IMPLEMENTATION_
+
+namespace testing {
+
+using internal::GetUnitTestImpl;
+
+// Gets the summary of the failure message by omitting the stack trace
+// in it.
+std::string TestPartResult::ExtractSummary(const char* message) {
+  const char* const stack_trace = strstr(message, internal::kStackTraceMarker);
+  return stack_trace == NULL ? message :
+      std::string(message, stack_trace);
+}
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result) {
+  return os
+      << result.file_name() << ":" << result.line_number() << ": "
+      << (result.type() == TestPartResult::kSuccess ? "Success" :
+          result.type() == TestPartResult::kFatalFailure ? "Fatal failure" :
+          "Non-fatal failure") << ":\n"
+      << result.message() << std::endl;
+}
+
+// Appends a TestPartResult to the array.
+void TestPartResultArray::Append(const TestPartResult& result) {
+  array_.push_back(result);
+}
+
+// Returns the TestPartResult at the given index (0-based).
+const TestPartResult& TestPartResultArray::GetTestPartResult(int index) const {
+  if (index < 0 || index >= size()) {
+    printf("\nInvalid index (%d) into TestPartResultArray.\n", index);
+    internal::posix::Abort();
+  }
+
+  return array_[index];
+}
+
+// Returns the number of TestPartResult objects in the array.
+int TestPartResultArray::size() const {
+  return static_cast<int>(array_.size());
+}
+
+namespace internal {
+
+HasNewFatalFailureHelper::HasNewFatalFailureHelper()
+    : has_new_fatal_failure_(false),
+      original_reporter_(GetUnitTestImpl()->
+                         GetTestPartResultReporterForCurrentThread()) {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(this);
+}
+
+HasNewFatalFailureHelper::~HasNewFatalFailureHelper() {
+  GetUnitTestImpl()->SetTestPartResultReporterForCurrentThread(
+      original_reporter_);
+}
+
+void HasNewFatalFailureHelper::ReportTestPartResult(
+    const TestPartResult& result) {
+  if (result.fatally_failed())
+    has_new_fatal_failure_ = true;
+  original_reporter_->ReportTestPartResult(result);
+}
+
+}  // namespace internal
+
+}  // namespace testing
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+
+namespace testing {
+namespace internal {
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// Skips to the first non-space char in str. Returns an empty string if str
+// contains only whitespace characters.
+static const char* SkipSpaces(const char* str) {
+  while (IsSpace(*str))
+    str++;
+  return str;
+}
+
+// Verifies that registered_tests match the test names in
+// defined_test_names_; returns registered_tests if successful, or
+// aborts the program otherwise.
+const char* TypedTestCasePState::VerifyRegisteredTestNames(
+    const char* file, int line, const char* registered_tests) {
+  typedef ::std::set<const char*>::const_iterator DefinedTestIter;
+  registered_ = true;
+
+  // Skip initial whitespace in registered_tests since some
+  // preprocessors prefix stringizied literals with whitespace.
+  registered_tests = SkipSpaces(registered_tests);
+
+  Message errors;
+  ::std::set<std::string> tests;
+  for (const char* names = registered_tests; names != NULL;
+       names = SkipComma(names)) {
+    const std::string name = GetPrefixUntilComma(names);
+    if (tests.count(name) != 0) {
+      errors << "Test " << name << " is listed more than once.\n";
+      continue;
+    }
+
+    bool found = false;
+    for (DefinedTestIter it = defined_test_names_.begin();
+         it != defined_test_names_.end();
+         ++it) {
+      if (name == *it) {
+        found = true;
+        break;
+      }
+    }
+
+    if (found) {
+      tests.insert(name);
+    } else {
+      errors << "No test named " << name
+             << " can be found in this test case.\n";
+    }
+  }
+
+  for (DefinedTestIter it = defined_test_names_.begin();
+       it != defined_test_names_.end();
+       ++it) {
+    if (tests.count(*it) == 0) {
+      errors << "You forgot to list test " << *it << ".\n";
+    }
+  }
+
+  const std::string& errors_str = errors.GetString();
+  if (errors_str != "") {
+    fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(),
+            errors_str.c_str());
+    fflush(stderr);
+    posix::Abort();
+  }
+
+  return registered_tests;
+}
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
diff --git a/lib/kokkos/tpls/gtest/gtest/gtest-test-part.h b/lib/kokkos/tpls/gtest/gtest/gtest-test-part.h
new file mode 120000
index 0000000000..48d39090f1
--- /dev/null
+++ b/lib/kokkos/tpls/gtest/gtest/gtest-test-part.h
@@ -0,0 +1 @@
+gtest.h
\ No newline at end of file
diff --git a/lib/kokkos/tpls/gtest/gtest/gtest.h b/lib/kokkos/tpls/gtest/gtest/gtest.h
new file mode 100644
index 0000000000..c74d098fa9
--- /dev/null
+++ b/lib/kokkos/tpls/gtest/gtest/gtest.h
@@ -0,0 +1,20065 @@
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for Google Test.  It should be
+// included by any test program that uses Google Test.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+//
+// Acknowledgment: Google Test borrowed the idea of automatic test
+// registration from Barthelemy Dagenais' (barthelemy@prologique.com)
+// easyUnit framework.
+
+#ifdef __GNUC__
+#pragma GCC system_header
+#endif
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_H_
+
+#include <limits>
+#include <ostream>
+#include <vector>
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares functions and macros used internally by
+// Google Test.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Authors: wan@google.com (Zhanyong Wan)
+//
+// Low-level types and utilities for porting Google Test to various
+// platforms.  They are subject to change without notice.  DO NOT USE
+// THEM IN USER CODE.
+//
+// This file is fundamental to Google Test.  All other Google Test source
+// files are expected to #include this.  Therefore, it cannot #include
+// any other Google Test header.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+// The user can define the following macros in the build script to
+// control Google Test's behavior.  If the user doesn't define a macro
+// in this list, Google Test will define it.
+//
+//   GTEST_HAS_CLONE          - Define it to 1/0 to indicate that clone(2)
+//                              is/isn't available.
+//   GTEST_HAS_EXCEPTIONS     - Define it to 1/0 to indicate that exceptions
+//                              are enabled.
+//   GTEST_HAS_GLOBAL_STRING  - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::string, which is different to std::string).
+//   GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
+//                              is/isn't available (some systems define
+//                              ::wstring, which is different to std::wstring).
+//   GTEST_HAS_POSIX_RE       - Define it to 1/0 to indicate that POSIX regular
+//                              expressions are/aren't available.
+//   GTEST_HAS_PTHREAD        - Define it to 1/0 to indicate that <pthread.h>
+//                              is/isn't available.
+//   GTEST_HAS_RTTI           - Define it to 1/0 to indicate that RTTI is/isn't
+//                              enabled.
+//   GTEST_HAS_STD_WSTRING    - Define it to 1/0 to indicate that
+//                              std::wstring does/doesn't work (Google Test can
+//                              be used where std::wstring is unavailable).
+//   GTEST_HAS_TR1_TUPLE      - Define it to 1/0 to indicate tr1::tuple
+//                              is/isn't available.
+//   GTEST_HAS_SEH            - Define it to 1/0 to indicate whether the
+//                              compiler supports Microsoft's "Structured
+//                              Exception Handling".
+//   GTEST_HAS_STREAM_REDIRECTION
+//                            - Define it to 1/0 to indicate whether the
+//                              platform supports I/O stream redirection using
+//                              dup() and dup2().
+//   GTEST_USE_OWN_TR1_TUPLE  - Define it to 1/0 to indicate whether Google
+//                              Test's own tr1 tuple implementation should be
+//                              used.  Unused when the user sets
+//                              GTEST_HAS_TR1_TUPLE to 0.
+//   GTEST_LANG_CXX11         - Define it to 1/0 to indicate that Google Test
+//                              is building in C++11/C++98 mode.
+//   GTEST_LINKED_AS_SHARED_LIBRARY
+//                            - Define to 1 when compiling tests that use
+//                              Google Test as a shared library (known as
+//                              DLL on Windows).
+//   GTEST_CREATE_SHARED_LIBRARY
+//                            - Define to 1 when compiling Google Test itself
+//                              as a shared library.
+
+// This header defines the following utilities:
+//
+// Macros indicating the current platform (defined to 1 if compiled on
+// the given platform; otherwise undefined):
+//   GTEST_OS_AIX      - IBM AIX
+//   GTEST_OS_CYGWIN   - Cygwin
+//   GTEST_OS_HPUX     - HP-UX
+//   GTEST_OS_LINUX    - Linux
+//     GTEST_OS_LINUX_ANDROID - Google Android
+//   GTEST_OS_MAC      - Mac OS X
+//     GTEST_OS_IOS    - iOS
+//       GTEST_OS_IOS_SIMULATOR - iOS simulator
+//   GTEST_OS_NACL     - Google Native Client (NaCl)
+//   GTEST_OS_OPENBSD  - OpenBSD
+//   GTEST_OS_QNX      - QNX
+//   GTEST_OS_SOLARIS  - Sun Solaris
+//   GTEST_OS_SYMBIAN  - Symbian
+//   GTEST_OS_WINDOWS  - Windows (Desktop, MinGW, or Mobile)
+//     GTEST_OS_WINDOWS_DESKTOP  - Windows Desktop
+//     GTEST_OS_WINDOWS_MINGW    - MinGW
+//     GTEST_OS_WINDOWS_MOBILE   - Windows Mobile
+//   GTEST_OS_ZOS      - z/OS
+//
+// Among the platforms, Cygwin, Linux, Max OS X, and Windows have the
+// most stable support.  Since core members of the Google Test project
+// don't have access to other platforms, support for them may be less
+// stable.  If you notice any problems on your platform, please notify
+// googletestframework@googlegroups.com (patches for fixing them are
+// even more welcome!).
+//
+// Note that it is possible that none of the GTEST_OS_* macros are defined.
+//
+// Macros indicating available Google Test features (defined to 1 if
+// the corresponding feature is supported; otherwise undefined):
+//   GTEST_HAS_COMBINE      - the Combine() function (for value-parameterized
+//                            tests)
+//   GTEST_HAS_DEATH_TEST   - death tests
+//   GTEST_HAS_PARAM_TEST   - value-parameterized tests
+//   GTEST_HAS_TYPED_TEST   - typed tests
+//   GTEST_HAS_TYPED_TEST_P - type-parameterized tests
+//   GTEST_USES_POSIX_RE    - enhanced POSIX regex is used. Do not confuse with
+//                            GTEST_HAS_POSIX_RE (see above) which users can
+//                            define themselves.
+//   GTEST_USES_SIMPLE_RE   - our own simple regex is used;
+//                            the above two are mutually exclusive.
+//   GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
+//
+// Macros for basic C++ coding:
+//   GTEST_AMBIGUOUS_ELSE_BLOCKER_ - for disabling a gcc warning.
+//   GTEST_ATTRIBUTE_UNUSED_  - declares that a class' instances or a
+//                              variable don't have to be used.
+//   GTEST_DISALLOW_ASSIGN_   - disables operator=.
+//   GTEST_DISALLOW_COPY_AND_ASSIGN_ - disables copy ctor and operator=.
+//   GTEST_MUST_USE_RESULT_   - declares that a function's result must be used.
+//
+// Synchronization:
+//   Mutex, MutexLock, ThreadLocal, GetThreadCount()
+//                  - synchronization primitives.
+//   GTEST_IS_THREADSAFE - defined to 1 to indicate that the above
+//                         synchronization primitives have real implementations
+//                         and Google Test is thread-safe; or 0 otherwise.
+//
+// Template meta programming:
+//   is_pointer     - as in TR1; needed on Symbian and IBM XL C/C++ only.
+//   IteratorTraits - partial implementation of std::iterator_traits, which
+//                    is not available in libCstd when compiled with Sun C++.
+//
+// Smart pointers:
+//   scoped_ptr     - as in TR2.
+//
+// Regular expressions:
+//   RE             - a simple regular expression class using the POSIX
+//                    Extended Regular Expression syntax on UNIX-like
+//                    platforms, or a reduced regular exception syntax on
+//                    other platforms, including Windows.
+//
+// Logging:
+//   GTEST_LOG_()   - logs messages at the specified severity level.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+//
+// Stdout and stderr capturing:
+//   CaptureStdout()     - starts capturing stdout.
+//   GetCapturedStdout() - stops capturing stdout and returns the captured
+//                         string.
+//   CaptureStderr()     - starts capturing stderr.
+//   GetCapturedStderr() - stops capturing stderr and returns the captured
+//                         string.
+//
+// Integer types:
+//   TypeWithSize   - maps an integer to a int type.
+//   Int32, UInt32, Int64, UInt64, TimeInMillis
+//                  - integers of known sizes.
+//   BiggestInt     - the biggest signed integer type.
+//
+// Command-line utilities:
+//   GTEST_FLAG()       - references a flag.
+//   GTEST_DECLARE_*()  - declares a flag.
+//   GTEST_DEFINE_*()   - defines a flag.
+//   GetInjectableArgvs() - returns the command line as a vector of strings.
+//
+// Environment variable utilities:
+//   GetEnv()             - gets the value of an environment variable.
+//   BoolFromGTestEnv()   - parses a bool environment variable.
+//   Int32FromGTestEnv()  - parses an Int32 environment variable.
+//   StringFromGTestEnv() - parses a string environment variable.
+
+#include <ctype.h>   // for isspace, etc
+#include <stddef.h>  // for ptrdiff_t
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32_WCE
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif  // !_WIN32_WCE
+
+#if defined __APPLE__
+# include <AvailabilityMacros.h>
+# include <TargetConditionals.h>
+#endif
+
+#include <iostream>  // NOLINT
+#include <sstream>  // NOLINT
+#include <string>  // NOLINT
+
+#define GTEST_DEV_EMAIL_ "googletestframework@@googlegroups.com"
+#define GTEST_FLAG_PREFIX_ "gtest_"
+#define GTEST_FLAG_PREFIX_DASH_ "gtest-"
+#define GTEST_FLAG_PREFIX_UPPER_ "GTEST_"
+#define GTEST_NAME_ "Google Test"
+#define GTEST_PROJECT_URL_ "http://code.google.com/p/googletest/"
+
+// Determines the version of gcc that is used to compile this.
+#ifdef __GNUC__
+// 40302 means version 4.3.2.
+# define GTEST_GCC_VER_ \
+    (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
+#endif  // __GNUC__
+
+// Determines the platform on which Google Test is compiled.
+#ifdef __CYGWIN__
+# define GTEST_OS_CYGWIN 1
+#elif defined __SYMBIAN32__
+# define GTEST_OS_SYMBIAN 1
+#elif defined _WIN32
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+#  define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+#  define GTEST_OS_WINDOWS_MINGW 1
+# else
+#  define GTEST_OS_WINDOWS_DESKTOP 1
+# endif  // _WIN32_WCE
+#elif defined __APPLE__
+# define GTEST_OS_MAC 1
+# if TARGET_OS_IPHONE
+#  define GTEST_OS_IOS 1
+#  if TARGET_IPHONE_SIMULATOR
+#   define GTEST_OS_IOS_SIMULATOR 1
+#  endif
+# endif
+#elif defined __linux__
+# define GTEST_OS_LINUX 1
+# if defined __ANDROID__
+#  define GTEST_OS_LINUX_ANDROID 1
+# endif
+#elif defined __MVS__
+# define GTEST_OS_ZOS 1
+#elif defined(__sun) && defined(__SVR4)
+# define GTEST_OS_SOLARIS 1
+#elif defined(_AIX)
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
+#elif defined __OpenBSD__
+# define GTEST_OS_OPENBSD 1
+#elif defined __QNX__
+# define GTEST_OS_QNX 1
+#endif  // __CYGWIN__
+
+#ifndef GTEST_LANG_CXX11
+// gcc and clang define __GXX_EXPERIMENTAL_CXX0X__ when
+// -std={c,gnu}++{0x,11} is passed.  The C++11 standard specifies a
+// value for __cplusplus, and recent versions of clang, gcc, and
+// probably other compilers set that too in C++11 mode.
+# if __GXX_EXPERIMENTAL_CXX0X__ || __cplusplus >= 201103L
+// Compiling in at least C++11 mode.
+#  define GTEST_LANG_CXX11 1
+# else
+#  define GTEST_LANG_CXX11 0
+# endif
+#endif
+
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# include <strings.h>
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+#if GTEST_OS_LINUX_ANDROID
+// Used to define __ANDROID_API__ matching the target NDK API level.
+#  include <android/api-level.h>  // NOLINT
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# if GTEST_OS_LINUX_ANDROID
+// On Android, <regex.h> is only available starting with Gingerbread.
+#  define GTEST_HAS_POSIX_RE (__ANDROID_API__ >= 9)
+# else
+#  define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+# endif
+#endif
+
+#if GTEST_HAS_POSIX_RE
+
+// On some platforms, <regex.h> needs someone to define size_t, and
+// won't compile otherwise.  We can #include it here as we already
+// included <stdlib.h>, which is guaranteed to define size_t through
+// <stddef.h>.
+# include <regex.h>  // NOLINT
+
+# define GTEST_USES_POSIX_RE 1
+
+#elif GTEST_OS_WINDOWS
+
+// <regex.h> is not available on Windows.  Use our own simple regex
+// implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#else
+
+// <regex.h> may not be available on this platform.  Use our own
+// simple regex implementation instead.
+# define GTEST_USES_SIMPLE_RE 1
+
+#endif  // GTEST_HAS_POSIX_RE
+
+#ifndef GTEST_HAS_EXCEPTIONS
+// The user didn't tell us whether exceptions are enabled, so we need
+// to figure it out.
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
+// macro to enable exceptions, so we'll do the same.
+// Assumes that exceptions are enabled by default.
+#  ifndef _HAS_EXCEPTIONS
+#   define _HAS_EXCEPTIONS 1
+#  endif  // _HAS_EXCEPTIONS
+#  define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
+// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
+// Sun Pro CC supports exceptions.  However, there is no compile-time way of
+// detecting whether they are enabled or not.  Therefore, we assume that
+// they are enabled unless the user tells us otherwise.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
+// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
+#  define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+#  define GTEST_HAS_EXCEPTIONS 1
+# else
+// For other compilers, we assume exceptions are disabled to be
+// conservative.
+#  define GTEST_HAS_EXCEPTIONS 0
+# endif  // defined(_MSC_VER) || defined(__BORLANDC__)
+#endif  // GTEST_HAS_EXCEPTIONS
+
+#if !defined(GTEST_HAS_STD_STRING)
+// Even though we don't use this macro any longer, we keep it in case
+// some clients still depend on it.
+# define GTEST_HAS_STD_STRING 1
+#elif !GTEST_HAS_STD_STRING
+// The user told us that ::std::string isn't available.
+# error "Google Test cannot be used where ::std::string isn't available."
+#endif  // !defined(GTEST_HAS_STD_STRING)
+
+#ifndef GTEST_HAS_GLOBAL_STRING
+// The user didn't tell us whether ::string is available, so we need
+// to figure it out.
+
+# define GTEST_HAS_GLOBAL_STRING 0
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#ifndef GTEST_HAS_STD_WSTRING
+// The user didn't tell us whether ::std::wstring is available, so we need
+// to figure it out.
+// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring
+//   is available.
+
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either.  Android has
+// no support for it at least as recent as Froyo (2.2).
+# define GTEST_HAS_STD_WSTRING \
+    (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS))
+
+#endif  // GTEST_HAS_STD_WSTRING
+
+#ifndef GTEST_HAS_GLOBAL_WSTRING
+// The user didn't tell us whether ::wstring is available, so we need
+// to figure it out.
+# define GTEST_HAS_GLOBAL_WSTRING \
+    (GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// Determines whether RTTI is available.
+#ifndef GTEST_HAS_RTTI
+// The user didn't tell us whether RTTI is enabled, so we need to
+// figure it out.
+
+# ifdef _MSC_VER
+
+#  ifdef _CPPRTTI  // MSVC defines this macro iff RTTI is enabled.
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+
+#  ifdef __GXX_RTTI
+// When building against STLport with the Android NDK and with
+// -frtti -fno-exceptions, the build fails at link time with undefined
+// references to __cxa_bad_typeid. Note sure if STL or toolchain bug,
+// so disable RTTI when detected.
+#   if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR) && \
+       !defined(__EXCEPTIONS)
+#    define GTEST_HAS_RTTI 0
+#   else
+#    define GTEST_HAS_RTTI 1
+#   endif  // GTEST_OS_LINUX_ANDROID && __STLPORT_MAJOR && !__EXCEPTIONS
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif  // __GXX_RTTI
+
+// Clang defines __GXX_RTTI starting with version 3.0, but its manual recommends
+// using has_feature instead. has_feature(cxx_rtti) is supported since 2.7, the
+// first version with C++ support.
+# elif defined(__clang__)
+
+#  define GTEST_HAS_RTTI __has_feature(cxx_rtti)
+
+// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
+// both the typeid and dynamic_cast features are present.
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+
+#  ifdef __RTTI_ALL__
+#   define GTEST_HAS_RTTI 1
+#  else
+#   define GTEST_HAS_RTTI 0
+#  endif
+
+# else
+
+// For all other compilers, we assume RTTI is enabled.
+#  define GTEST_HAS_RTTI 1
+
+# endif  // _MSC_VER
+
+#endif  // GTEST_HAS_RTTI
+
+// It's this header's responsibility to #include <typeinfo> when RTTI
+// is enabled.
+#if GTEST_HAS_RTTI
+# include <typeinfo>
+#endif
+
+// Determines whether Google Test can use the pthreads library.
+#ifndef GTEST_HAS_PTHREAD
+// The user didn't tell us explicitly, so we assume pthreads support is
+// available on Linux and Mac.
+//
+// To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0
+// to your compiler flags.
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX \
+    || GTEST_OS_QNX)
+#endif  // GTEST_HAS_PTHREAD
+
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h>  // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h>  // NOLINT
+#endif
+
+// Determines whether Google Test can use tr1/tuple.  You can define
+// this macro to 0 to prevent Google Test from using tuple (any
+// feature depending on tuple with be disabled in this mode).
+#ifndef GTEST_HAS_TR1_TUPLE
+# if GTEST_OS_LINUX_ANDROID && defined(_STLPORT_MAJOR)
+// STLport, provided with the Android NDK, has neither <tr1/tuple> or <tuple>.
+#  define GTEST_HAS_TR1_TUPLE 0
+# else
+// The user didn't tell us not to do it, so we assume it's OK.
+#  define GTEST_HAS_TR1_TUPLE 1
+# endif
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether Google Test's own tr1 tuple implementation
+// should be used.
+#ifndef GTEST_USE_OWN_TR1_TUPLE
+// The user didn't tell us, so we need to figure it out.
+
+// We use our own TR1 tuple if we aren't sure the user has an
+// implementation of it already.  At this time, libstdc++ 4.0.0+ and
+// MSVC 2010 are the only mainstream standard libraries that come
+// with a TR1 tuple implementation.  NVIDIA's CUDA NVCC compiler
+// pretends to be GCC by defining __GNUC__ and friends, but cannot
+// compile GCC's tuple implementation.  MSVC 2008 (9.0) provides TR1
+// tuple in a 323 MB Feature Pack download, which we cannot assume the
+// user has.  QNX's QCC compiler is a modified GCC but it doesn't
+// support TR1 tuple.  libc++ only provides std::tuple, in C++11 mode,
+// and it can be used with some compilers that define __GNUC__.
+# if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000) \
+      && !GTEST_OS_QNX && !defined(_LIBCPP_VERSION)) || _MSC_VER >= 1600
+#  define GTEST_ENV_HAS_TR1_TUPLE_ 1
+# endif
+
+// C++11 specifies that <tuple> provides std::tuple. Use that if gtest is used
+// in C++11 mode and libstdc++ isn't very old (binaries targeting OS X 10.6
+// can build with clang but need to use gcc4.2's libstdc++).
+# if GTEST_LANG_CXX11 && (!defined(__GLIBCXX__) || __GLIBCXX__ > 20110325)
+#  define GTEST_ENV_HAS_STD_TUPLE_ 1
+# endif
+
+# if GTEST_ENV_HAS_TR1_TUPLE_ || GTEST_ENV_HAS_STD_TUPLE_
+#  define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+#  define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
+
+#endif  // GTEST_USE_OWN_TR1_TUPLE
+
+// To avoid conditional compilation everywhere, we make it
+// gtest-port.h's responsibility to #include the header implementing
+// tr1/tuple.
+#if GTEST_HAS_TR1_TUPLE
+
+# if GTEST_USE_OWN_TR1_TUPLE
+// This file was GENERATED by command:
+//     pump.py gtest-tuple.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2009 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Implements a subset of TR1 tuple needed by Google Test and Google Mock.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+
+#include <utility>  // For ::std::pair.
+
+// The compiler used in Symbian has a bug that prevents us from declaring the
+// tuple template as a friend (it complains that tuple is redefined).  This
+// hack bypasses the bug by declaring the members that should otherwise be
+// private as public.
+// Sun Studio versions < 12 also have the above bug.
+#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+#else
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+    template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
+   private:
+#endif
+
+// GTEST_n_TUPLE_(T) is the type of an n-tuple.
+#define GTEST_0_TUPLE_(T) tuple<>
+#define GTEST_1_TUPLE_(T) tuple<T##0, void, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_2_TUPLE_(T) tuple<T##0, T##1, void, void, void, void, void, \
+    void, void, void>
+#define GTEST_3_TUPLE_(T) tuple<T##0, T##1, T##2, void, void, void, void, \
+    void, void, void>
+#define GTEST_4_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, void, void, void, \
+    void, void, void>
+#define GTEST_5_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, void, void, \
+    void, void, void>
+#define GTEST_6_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, void, \
+    void, void, void>
+#define GTEST_7_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    void, void, void>
+#define GTEST_8_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, void, void>
+#define GTEST_9_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, void>
+#define GTEST_10_TUPLE_(T) tuple<T##0, T##1, T##2, T##3, T##4, T##5, T##6, \
+    T##7, T##8, T##9>
+
+// GTEST_n_TYPENAMES_(T) declares a list of n typenames.
+#define GTEST_0_TYPENAMES_(T)
+#define GTEST_1_TYPENAMES_(T) typename T##0
+#define GTEST_2_TYPENAMES_(T) typename T##0, typename T##1
+#define GTEST_3_TYPENAMES_(T) typename T##0, typename T##1, typename T##2
+#define GTEST_4_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3
+#define GTEST_5_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4
+#define GTEST_6_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5
+#define GTEST_7_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6
+#define GTEST_8_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, typename T##7
+#define GTEST_9_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8
+#define GTEST_10_TYPENAMES_(T) typename T##0, typename T##1, typename T##2, \
+    typename T##3, typename T##4, typename T##5, typename T##6, \
+    typename T##7, typename T##8, typename T##9
+
+// In theory, defining stuff in the ::std namespace is undefined
+// behavior.  We can do this as we are playing the role of a standard
+// library vendor.
+namespace std {
+namespace tr1 {
+
+template <typename T0 = void, typename T1 = void, typename T2 = void,
+    typename T3 = void, typename T4 = void, typename T5 = void,
+    typename T6 = void, typename T7 = void, typename T8 = void,
+    typename T9 = void>
+class tuple;
+
+// Anything in namespace gtest_internal is Google Test's INTERNAL
+// IMPLEMENTATION DETAIL and MUST NOT BE USED DIRECTLY in user code.
+namespace gtest_internal {
+
+// ByRef<T>::type is T if T is a reference; otherwise it's const T&.
+template <typename T>
+struct ByRef { typedef const T& type; };  // NOLINT
+template <typename T>
+struct ByRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for ByRef.
+#define GTEST_BY_REF_(T) typename ::std::tr1::gtest_internal::ByRef<T>::type
+
+// AddRef<T>::type is T if T is a reference; otherwise it's T&.  This
+// is the same as tr1::add_reference<T>::type.
+template <typename T>
+struct AddRef { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddRef<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper for AddRef.
+#define GTEST_ADD_REF_(T) typename ::std::tr1::gtest_internal::AddRef<T>::type
+
+// A helper for implementing get<k>().
+template <int k> class Get;
+
+// A helper for implementing tuple_element<k, T>.  kIndexValid is true
+// iff k < the number of fields in tuple type T.
+template <bool kIndexValid, int kIndex, class Tuple>
+struct TupleElement;
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 0, GTEST_10_TUPLE_(T) > {
+  typedef T0 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 1, GTEST_10_TUPLE_(T) > {
+  typedef T1 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 2, GTEST_10_TUPLE_(T) > {
+  typedef T2 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 3, GTEST_10_TUPLE_(T) > {
+  typedef T3 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 4, GTEST_10_TUPLE_(T) > {
+  typedef T4 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 5, GTEST_10_TUPLE_(T) > {
+  typedef T5 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 6, GTEST_10_TUPLE_(T) > {
+  typedef T6 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 7, GTEST_10_TUPLE_(T) > {
+  typedef T7 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 8, GTEST_10_TUPLE_(T) > {
+  typedef T8 type;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct TupleElement<true, 9, GTEST_10_TUPLE_(T) > {
+  typedef T9 type;
+};
+
+}  // namespace gtest_internal
+
+template <>
+class tuple<> {
+ public:
+  tuple() {}
+  tuple(const tuple& /* t */)  {}
+  tuple& operator=(const tuple& /* t */) { return *this; }
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+class GTEST_1_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0) : f0_(f0) {}
+
+  tuple(const tuple& t) : f0_(t.f0_) {}
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple(const GTEST_1_TUPLE_(U)& t) : f0_(t.f0_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_1_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_1_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_1_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    return *this;
+  }
+
+  T0 f0_;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+class GTEST_2_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1) : f0_(f0),
+      f1_(f1) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_) {}
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple(const GTEST_2_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_) {}
+  template <typename U0, typename U1>
+  tuple(const ::std::pair<U0, U1>& p) : f0_(p.first), f1_(p.second) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_2_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+  template <typename U0, typename U1>
+  tuple& operator=(const ::std::pair<U0, U1>& p) {
+    f0_ = p.first;
+    f1_ = p.second;
+    return *this;
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_2_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_2_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+class GTEST_3_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2) : f0_(f0), f1_(f1), f2_(f2) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple(const GTEST_3_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_3_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_3_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_3_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+class GTEST_4_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_) {}
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple(const GTEST_4_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_4_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_4_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_4_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+class GTEST_5_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3,
+      GTEST_BY_REF_(T4) f4) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_) {}
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple(const GTEST_5_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_5_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_5_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_5_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+class GTEST_6_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_) {}
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple(const GTEST_6_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_6_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_6_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_6_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+class GTEST_7_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple(const GTEST_7_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_7_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_7_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_7_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+class GTEST_8_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6,
+      GTEST_BY_REF_(T7) f7) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple(const GTEST_8_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_8_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_8_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_8_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+class GTEST_9_TUPLE_(T) {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8) : f0_(f0), f1_(f1), f2_(f2), f3_(f3), f4_(f4),
+      f5_(f5), f6_(f6), f7_(f7), f8_(f8) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple(const GTEST_9_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_9_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_9_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_9_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+class tuple {
+ public:
+  template <int k> friend class gtest_internal::Get;
+
+  tuple() : f0_(), f1_(), f2_(), f3_(), f4_(), f5_(), f6_(), f7_(), f8_(),
+      f9_() {}
+
+  explicit tuple(GTEST_BY_REF_(T0) f0, GTEST_BY_REF_(T1) f1,
+      GTEST_BY_REF_(T2) f2, GTEST_BY_REF_(T3) f3, GTEST_BY_REF_(T4) f4,
+      GTEST_BY_REF_(T5) f5, GTEST_BY_REF_(T6) f6, GTEST_BY_REF_(T7) f7,
+      GTEST_BY_REF_(T8) f8, GTEST_BY_REF_(T9) f9) : f0_(f0), f1_(f1), f2_(f2),
+      f3_(f3), f4_(f4), f5_(f5), f6_(f6), f7_(f7), f8_(f8), f9_(f9) {}
+
+  tuple(const tuple& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_), f3_(t.f3_),
+      f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_), f9_(t.f9_) {}
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple(const GTEST_10_TUPLE_(U)& t) : f0_(t.f0_), f1_(t.f1_), f2_(t.f2_),
+      f3_(t.f3_), f4_(t.f4_), f5_(t.f5_), f6_(t.f6_), f7_(t.f7_), f8_(t.f8_),
+      f9_(t.f9_) {}
+
+  tuple& operator=(const tuple& t) { return CopyFrom(t); }
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& operator=(const GTEST_10_TUPLE_(U)& t) {
+    return CopyFrom(t);
+  }
+
+  GTEST_DECLARE_TUPLE_AS_FRIEND_
+
+  template <GTEST_10_TYPENAMES_(U)>
+  tuple& CopyFrom(const GTEST_10_TUPLE_(U)& t) {
+    f0_ = t.f0_;
+    f1_ = t.f1_;
+    f2_ = t.f2_;
+    f3_ = t.f3_;
+    f4_ = t.f4_;
+    f5_ = t.f5_;
+    f6_ = t.f6_;
+    f7_ = t.f7_;
+    f8_ = t.f8_;
+    f9_ = t.f9_;
+    return *this;
+  }
+
+  T0 f0_;
+  T1 f1_;
+  T2 f2_;
+  T3 f3_;
+  T4 f4_;
+  T5 f5_;
+  T6 f6_;
+  T7 f7_;
+  T8 f8_;
+  T9 f9_;
+};
+
+// 6.1.3.2 Tuple creation functions.
+
+// Known limitations: we don't support passing an
+// std::tr1::reference_wrapper<T> to make_tuple().  And we don't
+// implement tie().
+
+inline tuple<> make_tuple() { return tuple<>(); }
+
+template <GTEST_1_TYPENAMES_(T)>
+inline GTEST_1_TUPLE_(T) make_tuple(const T0& f0) {
+  return GTEST_1_TUPLE_(T)(f0);
+}
+
+template <GTEST_2_TYPENAMES_(T)>
+inline GTEST_2_TUPLE_(T) make_tuple(const T0& f0, const T1& f1) {
+  return GTEST_2_TUPLE_(T)(f0, f1);
+}
+
+template <GTEST_3_TYPENAMES_(T)>
+inline GTEST_3_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2) {
+  return GTEST_3_TUPLE_(T)(f0, f1, f2);
+}
+
+template <GTEST_4_TYPENAMES_(T)>
+inline GTEST_4_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3) {
+  return GTEST_4_TUPLE_(T)(f0, f1, f2, f3);
+}
+
+template <GTEST_5_TYPENAMES_(T)>
+inline GTEST_5_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4) {
+  return GTEST_5_TUPLE_(T)(f0, f1, f2, f3, f4);
+}
+
+template <GTEST_6_TYPENAMES_(T)>
+inline GTEST_6_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5) {
+  return GTEST_6_TUPLE_(T)(f0, f1, f2, f3, f4, f5);
+}
+
+template <GTEST_7_TYPENAMES_(T)>
+inline GTEST_7_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6) {
+  return GTEST_7_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6);
+}
+
+template <GTEST_8_TYPENAMES_(T)>
+inline GTEST_8_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7) {
+  return GTEST_8_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7);
+}
+
+template <GTEST_9_TYPENAMES_(T)>
+inline GTEST_9_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8) {
+  return GTEST_9_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
+}
+
+template <GTEST_10_TYPENAMES_(T)>
+inline GTEST_10_TUPLE_(T) make_tuple(const T0& f0, const T1& f1, const T2& f2,
+    const T3& f3, const T4& f4, const T5& f5, const T6& f6, const T7& f7,
+    const T8& f8, const T9& f9) {
+  return GTEST_10_TUPLE_(T)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
+}
+
+// 6.1.3.3 Tuple helper classes.
+
+template <typename Tuple> struct tuple_size;
+
+template <GTEST_0_TYPENAMES_(T)>
+struct tuple_size<GTEST_0_TUPLE_(T) > {
+  static const int value = 0;
+};
+
+template <GTEST_1_TYPENAMES_(T)>
+struct tuple_size<GTEST_1_TUPLE_(T) > {
+  static const int value = 1;
+};
+
+template <GTEST_2_TYPENAMES_(T)>
+struct tuple_size<GTEST_2_TUPLE_(T) > {
+  static const int value = 2;
+};
+
+template <GTEST_3_TYPENAMES_(T)>
+struct tuple_size<GTEST_3_TUPLE_(T) > {
+  static const int value = 3;
+};
+
+template <GTEST_4_TYPENAMES_(T)>
+struct tuple_size<GTEST_4_TUPLE_(T) > {
+  static const int value = 4;
+};
+
+template <GTEST_5_TYPENAMES_(T)>
+struct tuple_size<GTEST_5_TUPLE_(T) > {
+  static const int value = 5;
+};
+
+template <GTEST_6_TYPENAMES_(T)>
+struct tuple_size<GTEST_6_TUPLE_(T) > {
+  static const int value = 6;
+};
+
+template <GTEST_7_TYPENAMES_(T)>
+struct tuple_size<GTEST_7_TUPLE_(T) > {
+  static const int value = 7;
+};
+
+template <GTEST_8_TYPENAMES_(T)>
+struct tuple_size<GTEST_8_TUPLE_(T) > {
+  static const int value = 8;
+};
+
+template <GTEST_9_TYPENAMES_(T)>
+struct tuple_size<GTEST_9_TUPLE_(T) > {
+  static const int value = 9;
+};
+
+template <GTEST_10_TYPENAMES_(T)>
+struct tuple_size<GTEST_10_TUPLE_(T) > {
+  static const int value = 10;
+};
+
+template <int k, class Tuple>
+struct tuple_element {
+  typedef typename gtest_internal::TupleElement<
+      k < (tuple_size<Tuple>::value), k, Tuple>::type type;
+};
+
+#define GTEST_TUPLE_ELEMENT_(k, Tuple) typename tuple_element<k, Tuple >::type
+
+// 6.1.3.4 Element access.
+
+namespace gtest_internal {
+
+template <>
+class Get<0> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  Field(Tuple& t) { return t.f0_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(0, Tuple))
+  ConstField(const Tuple& t) { return t.f0_; }
+};
+
+template <>
+class Get<1> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  Field(Tuple& t) { return t.f1_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(1, Tuple))
+  ConstField(const Tuple& t) { return t.f1_; }
+};
+
+template <>
+class Get<2> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  Field(Tuple& t) { return t.f2_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(2, Tuple))
+  ConstField(const Tuple& t) { return t.f2_; }
+};
+
+template <>
+class Get<3> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  Field(Tuple& t) { return t.f3_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(3, Tuple))
+  ConstField(const Tuple& t) { return t.f3_; }
+};
+
+template <>
+class Get<4> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  Field(Tuple& t) { return t.f4_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(4, Tuple))
+  ConstField(const Tuple& t) { return t.f4_; }
+};
+
+template <>
+class Get<5> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  Field(Tuple& t) { return t.f5_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(5, Tuple))
+  ConstField(const Tuple& t) { return t.f5_; }
+};
+
+template <>
+class Get<6> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  Field(Tuple& t) { return t.f6_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(6, Tuple))
+  ConstField(const Tuple& t) { return t.f6_; }
+};
+
+template <>
+class Get<7> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  Field(Tuple& t) { return t.f7_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(7, Tuple))
+  ConstField(const Tuple& t) { return t.f7_; }
+};
+
+template <>
+class Get<8> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  Field(Tuple& t) { return t.f8_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(8, Tuple))
+  ConstField(const Tuple& t) { return t.f8_; }
+};
+
+template <>
+class Get<9> {
+ public:
+  template <class Tuple>
+  static GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  Field(Tuple& t) { return t.f9_; }  // NOLINT
+
+  template <class Tuple>
+  static GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(9, Tuple))
+  ConstField(const Tuple& t) { return t.f9_; }
+};
+
+}  // namespace gtest_internal
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_ADD_REF_(GTEST_TUPLE_ELEMENT_(k, GTEST_10_TUPLE_(T)))
+get(GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::Field(t);
+}
+
+template <int k, GTEST_10_TYPENAMES_(T)>
+GTEST_BY_REF_(GTEST_TUPLE_ELEMENT_(k,  GTEST_10_TUPLE_(T)))
+get(const GTEST_10_TUPLE_(T)& t) {
+  return gtest_internal::Get<k>::ConstField(t);
+}
+
+// 6.1.3.5 Relational operators
+
+// We only implement == and !=, as we don't have a need for the rest yet.
+
+namespace gtest_internal {
+
+// SameSizeTuplePrefixComparator<k, k>::Eq(t1, t2) returns true if the
+// first k fields of t1 equals the first k fields of t2.
+// SameSizeTuplePrefixComparator(k1, k2) would be a compiler error if
+// k1 != k2.
+template <int kSize1, int kSize2>
+struct SameSizeTuplePrefixComparator;
+
+template <>
+struct SameSizeTuplePrefixComparator<0, 0> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& /* t1 */, const Tuple2& /* t2 */) {
+    return true;
+  }
+};
+
+template <int k>
+struct SameSizeTuplePrefixComparator<k, k> {
+  template <class Tuple1, class Tuple2>
+  static bool Eq(const Tuple1& t1, const Tuple2& t2) {
+    return SameSizeTuplePrefixComparator<k - 1, k - 1>::Eq(t1, t2) &&
+        ::std::tr1::get<k - 1>(t1) == ::std::tr1::get<k - 1>(t2);
+  }
+};
+
+}  // namespace gtest_internal
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator==(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) {
+  return gtest_internal::SameSizeTuplePrefixComparator<
+      tuple_size<GTEST_10_TUPLE_(T) >::value,
+      tuple_size<GTEST_10_TUPLE_(U) >::value>::Eq(t, u);
+}
+
+template <GTEST_10_TYPENAMES_(T), GTEST_10_TYPENAMES_(U)>
+inline bool operator!=(const GTEST_10_TUPLE_(T)& t,
+                       const GTEST_10_TUPLE_(U)& u) { return !(t == u); }
+
+// 6.1.4 Pairs.
+// Unimplemented.
+
+}  // namespace tr1
+}  // namespace std
+
+#undef GTEST_0_TUPLE_
+#undef GTEST_1_TUPLE_
+#undef GTEST_2_TUPLE_
+#undef GTEST_3_TUPLE_
+#undef GTEST_4_TUPLE_
+#undef GTEST_5_TUPLE_
+#undef GTEST_6_TUPLE_
+#undef GTEST_7_TUPLE_
+#undef GTEST_8_TUPLE_
+#undef GTEST_9_TUPLE_
+#undef GTEST_10_TUPLE_
+
+#undef GTEST_0_TYPENAMES_
+#undef GTEST_1_TYPENAMES_
+#undef GTEST_2_TYPENAMES_
+#undef GTEST_3_TYPENAMES_
+#undef GTEST_4_TYPENAMES_
+#undef GTEST_5_TYPENAMES_
+#undef GTEST_6_TYPENAMES_
+#undef GTEST_7_TYPENAMES_
+#undef GTEST_8_TYPENAMES_
+#undef GTEST_9_TYPENAMES_
+#undef GTEST_10_TYPENAMES_
+
+#undef GTEST_DECLARE_TUPLE_AS_FRIEND_
+#undef GTEST_BY_REF_
+#undef GTEST_ADD_REF_
+#undef GTEST_TUPLE_ELEMENT_
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TUPLE_H_
+# elif GTEST_ENV_HAS_STD_TUPLE_
+#  include <tuple>
+// C++11 puts its tuple into the ::std namespace rather than
+// ::std::tr1.  gtest expects tuple to live in ::std::tr1, so put it there.
+// This causes undefined behavior, but supported compilers react in
+// the way we intend.
+namespace std {
+namespace tr1 {
+using ::std::get;
+using ::std::make_tuple;
+using ::std::tuple;
+using ::std::tuple_element;
+using ::std::tuple_size;
+}
+}
+
+# elif GTEST_OS_SYMBIAN
+
+// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
+// use STLport's tuple implementation, which unfortunately doesn't
+// work as the copy of STLport distributed with Symbian is incomplete.
+// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
+// use its own tuple implementation.
+#  ifdef BOOST_HAS_TR1_TUPLE
+#   undef BOOST_HAS_TR1_TUPLE
+#  endif  // BOOST_HAS_TR1_TUPLE
+
+// This prevents <boost/tr1/detail/config.hpp>, which defines
+// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
+#  define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+#  include <tuple>
+
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header.  This does
+// not conform to the TR1 spec, which requires the header to be <tuple>.
+
+#  if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
+// which is #included by <tr1/tuple>, to not compile when RTTI is
+// disabled.  _TR1_FUNCTIONAL is the header guard for
+// <tr1/functional>.  Hence the following #define is a hack to prevent
+// <tr1/functional> from being included.
+#   define _TR1_FUNCTIONAL 1
+#   include <tr1/tuple>
+#   undef _TR1_FUNCTIONAL  // Allows the user to #include
+                        // <tr1/functional> if he chooses to.
+#  else
+#   include <tr1/tuple>  // NOLINT
+#  endif  // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+
+# else
+// If the compiler is not GCC 4.0+, we assume the user is using a
+// spec-conforming TR1 implementation.
+#  include <tuple>  // NOLINT
+# endif  // GTEST_USE_OWN_TR1_TUPLE
+
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Determines whether clone(2) is supported.
+// Usually it will only be available on Linux, excluding
+// Linux on the Itanium architecture.
+// Also see http://linux.die.net/man/2/clone.
+#ifndef GTEST_HAS_CLONE
+// The user didn't tell us, so we need to figure it out.
+
+# if GTEST_OS_LINUX && !defined(__ia64__)
+#  if GTEST_OS_LINUX_ANDROID
+// On Android, clone() is only available on ARM starting with Gingerbread.
+#    if defined(__arm__) && __ANDROID_API__ >= 9
+#     define GTEST_HAS_CLONE 1
+#    else
+#     define GTEST_HAS_CLONE 0
+#    endif
+#  else
+#   define GTEST_HAS_CLONE 1
+#  endif
+# else
+#  define GTEST_HAS_CLONE 0
+# endif  // GTEST_OS_LINUX && !defined(__ia64__)
+
+#endif  // GTEST_HAS_CLONE
+
+// Determines whether to support stream redirection. This is used to test
+// output correctness and to implement death tests.
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+#  define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+#  define GTEST_HAS_STREAM_REDIRECTION 1
+# endif  // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+// Determines whether to support death tests.
+// Google Test does not support death tests for VC 7.1 and earlier as
+// abort() in a VC 7.1 application compiled as GUI in debug config
+// pops up a dialog window that cannot be suppressed programmatically.
+#if (GTEST_OS_LINUX || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \
+     (GTEST_OS_MAC && !GTEST_OS_IOS) || GTEST_OS_IOS_SIMULATOR || \
+     (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \
+     GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX || \
+     GTEST_OS_OPENBSD || GTEST_OS_QNX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector>  // NOLINT
+#endif
+
+// We don't support MSVC 7.1 with exceptions disabled now.  Therefore
+// all the compilers we care about are adequate for supporting
+// value-parameterized tests.
+#define GTEST_HAS_PARAM_TEST 1
+
+// Determines whether to support type-driven tests.
+
+// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
+#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
+    defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
+#endif
+
+// Determines whether to support Combine(). This only makes sense when
+// value-parameterized tests are enabled.  The implementation doesn't
+// work on Sun Studio since it doesn't understand templated conversion
+// operators.
+#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
+# define GTEST_HAS_COMBINE 1
+#endif
+
+// Determines whether the system compiler uses UTF-16 for encoding wide strings.
+#define GTEST_WIDE_STRING_USES_UTF16_ \
+    (GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
+// Defines some utility macros.
+
+// The GNU compiler emits a warning if nested "if" statements are followed by
+// an "else" statement and braces are not used to explicitly disambiguate the
+// "else" binding.  This leads to problems with code like:
+//
+//   if (gate)
+//     ASSERT_*(condition) << "Some message";
+//
+// The "switch (0) case 0:" idiom is used to suppress this.
+#ifdef __INTEL_COMPILER
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+#else
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default:  // NOLINT
+#endif
+
+// Use this annotation at the end of a struct/class definition to
+// prevent the compiler from optimizing away instances that are never
+// used.  This is useful when all interesting logic happens inside the
+// c'tor and / or d'tor.  Example:
+//
+//   struct Foo {
+//     Foo() { ... }
+//   } GTEST_ATTRIBUTE_UNUSED_;
+//
+// Also use it after a variable or parameter declaration to tell the
+// compiler the variable/parameter does not have to be used.
+#if defined(__GNUC__) && !defined(COMPILER_ICC)
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+#else
+# define GTEST_ATTRIBUTE_UNUSED_
+#endif
+
+// A macro to disallow operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_ASSIGN_(type)\
+  void operator=(type const &)
+
+// A macro to disallow copy constructor and operator=
+// This should be used in the private: declarations for a class.
+#define GTEST_DISALLOW_COPY_AND_ASSIGN_(type)\
+  type(type const &);\
+  GTEST_DISALLOW_ASSIGN_(type)
+
+// Tell the compiler to warn about unused return values for functions declared
+// with this macro.  The macro should be used on function declarations
+// following the argument list:
+//
+//   Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
+#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+#else
+# define GTEST_MUST_USE_RESULT_
+#endif  // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
+
+// Determine whether the compiler supports Microsoft's Structured Exception
+// Handling.  This is supported by several Windows compilers but generally
+// does not exist on any other system.
+#ifndef GTEST_HAS_SEH
+// The user didn't tell us, so we need to figure it out.
+
+# if defined(_MSC_VER) || defined(__BORLANDC__)
+// These two compilers are known to support SEH.
+#  define GTEST_HAS_SEH 1
+# else
+// Assume no SEH.
+#  define GTEST_HAS_SEH 0
+# endif
+
+#endif  // GTEST_HAS_SEH
+
+#ifdef _MSC_VER
+
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+#  define GTEST_API_ __declspec(dllexport)
+# endif
+
+#endif  // _MSC_VER
+
+#ifndef GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
+#endif
+
+// _LIBCPP_VERSION is defined by the libc++ library from the LLVM project.
+#if defined(__GLIBCXX__) || defined(_LIBCPP_VERSION)
+# define GTEST_HAS_CXXABI_H_ 1
+#else
+# define GTEST_HAS_CXXABI_H_ 0
+#endif
+
+namespace testing {
+
+class Message;
+
+namespace internal {
+
+// A secret type that Google Test users don't know about.  It has no
+// definition on purpose.  Therefore it's impossible to create a
+// Secret object, which is what we want.
+class Secret;
+
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+//   GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+//                         content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+//   GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+  typedef ::testing::internal::CompileAssert<(static_cast<bool>(expr))> \
+      msg[static_cast<bool>(expr) ? 1 : -1] GTEST_ATTRIBUTE_UNUSED_
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+//   elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+//    #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+//   does not work, as gcc supports variable-length arrays whose sizes
+//   are determined at run-time (this is gcc's extension and not part
+//   of the C++ standard).  As a result, gcc fails to reject the
+//   following code with the simple definition:
+//
+//     int foo;
+//     GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+//                                      // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+//   expr is a compile-time constant.  (Template arguments must be
+//   determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+//   to work around a bug in gcc 3.4.4 and 4.0.1.  If we had written
+//
+//     CompileAssert<bool(expr)>
+//
+//   instead, these compilers will refuse to compile
+//
+//     GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+//   (They seem to think the ">" in "5 > 0" marks the end of the
+//   template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+//     ((expr) ? 1 : -1).
+//
+//   This is to avoid running into a bug in MS VC 7.1, which
+//   causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+// A helper for suppressing warnings on constant condition.  It just
+// returns 'condition'.
+GTEST_API_ bool IsTrue(bool condition);
+
+// Defines scoped_ptr.
+
+// This implementation of scoped_ptr is PARTIAL - it only contains
+// enough stuff to satisfy Google Test's need.
+template <typename T>
+class scoped_ptr {
+ public:
+  typedef T element_type;
+
+  explicit scoped_ptr(T* p = NULL) : ptr_(p) {}
+  ~scoped_ptr() { reset(); }
+
+  T& operator*() const { return *ptr_; }
+  T* operator->() const { return ptr_; }
+  T* get() const { return ptr_; }
+
+  T* release() {
+    T* const ptr = ptr_;
+    ptr_ = NULL;
+    return ptr;
+  }
+
+  void reset(T* p = NULL) {
+    if (p != ptr_) {
+      if (IsTrue(sizeof(T) > 0)) {  // Makes sure T is a complete type.
+        delete ptr_;
+      }
+      ptr_ = p;
+    }
+  }
+
+ private:
+  T* ptr_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(scoped_ptr);
+};
+
+// Defines RE.
+
+// A simple C++ wrapper for <regex.h>.  It uses the POSIX Extended
+// Regular Expression syntax.
+class GTEST_API_ RE {
+ public:
+  // A copy constructor is required by the Standard to initialize object
+  // references from r-values.
+  RE(const RE& other) { Init(other.pattern()); }
+
+  // Constructs an RE from a string.
+  RE(const ::std::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  RE(const ::string& regex) { Init(regex.c_str()); }  // NOLINT
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  RE(const char* regex) { Init(regex); }  // NOLINT
+  ~RE();
+
+  // Returns the string representation of the regex.
+  const char* pattern() const { return pattern_; }
+
+  // FullMatch(str, re) returns true iff regular expression re matches
+  // the entire str.
+  // PartialMatch(str, re) returns true iff regular expression re
+  // matches a substring of str (including str itself).
+  //
+  // TODO(wan@google.com): make FullMatch() and PartialMatch() work
+  // when str contains NUL characters.
+  static bool FullMatch(const ::std::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::std::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#if GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const ::string& str, const RE& re) {
+    return FullMatch(str.c_str(), re);
+  }
+  static bool PartialMatch(const ::string& str, const RE& re) {
+    return PartialMatch(str.c_str(), re);
+  }
+
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+  static bool FullMatch(const char* str, const RE& re);
+  static bool PartialMatch(const char* str, const RE& re);
+
+ private:
+  void Init(const char* regex);
+
+  // We use a const char* instead of an std::string, as Google Test used to be
+  // used where std::string is not available.  TODO(wan@google.com): change to
+  // std::string.
+  const char* pattern_;
+  bool is_valid_;
+
+#if GTEST_USES_POSIX_RE
+
+  regex_t full_regex_;     // For FullMatch().
+  regex_t partial_regex_;  // For PartialMatch().
+
+#else  // GTEST_USES_SIMPLE_RE
+
+  const char* full_pattern_;  // For FullMatch();
+
+#endif
+
+  GTEST_DISALLOW_ASSIGN_(RE);
+};
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+                                                               int line);
+
+// Defines logging utilities:
+//   GTEST_LOG_(severity) - logs messages at the specified severity level. The
+//                          message itself is streamed into the macro.
+//   LogToStderr()  - directs all log messages to stderr.
+//   FlushInfoLog() - flushes informational log messages.
+
+enum GTestLogSeverity {
+  GTEST_INFO,
+  GTEST_WARNING,
+  GTEST_ERROR,
+  GTEST_FATAL
+};
+
+// Formats log entry severity, provides a stream object for streaming the
+// log message, and terminates the message with a newline when going out of
+// scope.
+class GTEST_API_ GTestLog {
+ public:
+  GTestLog(GTestLogSeverity severity, const char* file, int line);
+
+  // Flushes the buffers and, if severity is GTEST_FATAL, aborts the program.
+  ~GTestLog();
+
+  ::std::ostream& GetStream() { return ::std::cerr; }
+
+ private:
+  const GTestLogSeverity severity_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestLog);
+};
+
+#define GTEST_LOG_(severity) \
+    ::testing::internal::GTestLog(::testing::internal::GTEST_##severity, \
+                                  __FILE__, __LINE__).GetStream()
+
+inline void LogToStderr() {}
+inline void FlushInfoLog() { fflush(NULL); }
+
+// INTERNAL IMPLEMENTATION - DO NOT USE.
+//
+// GTEST_CHECK_ is an all-mode assert. It aborts the program if the condition
+// is not satisfied.
+//  Synopsys:
+//    GTEST_CHECK_(boolean_condition);
+//     or
+//    GTEST_CHECK_(boolean_condition) << "Additional message";
+//
+//    This checks the condition and if the condition is not satisfied
+//    it prints message about the condition violation, including the
+//    condition itself, plus additional message streamed into it, if any,
+//    and then it aborts the program. It aborts the program irrespective of
+//    whether it is built in the debug mode or not.
+#define GTEST_CHECK_(condition) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::IsTrue(condition)) \
+      ; \
+    else \
+      GTEST_LOG_(FATAL) << "Condition " #condition " failed. "
+
+// An all-mode assert to verify that the given POSIX-style function
+// call returns 0 (indicating success).  Known limitation: this
+// doesn't expand to a balanced 'if' statement, so enclose the macro
+// in {} if you need to use it as the only statement in an 'if'
+// branch.
+#define GTEST_CHECK_POSIX_SUCCESS_(posix_call) \
+  if (const int gtest_error = (posix_call)) \
+    GTEST_LOG_(FATAL) << #posix_call << "failed with error " \
+                      << gtest_error
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*).  When you use ImplicitCast_, the compiler checks that
+// the cast is safe.  Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+//   ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late.  It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed.  When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo?  It
+// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
+// when you downcast, you should use this macro.  In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not).  In normal mode, we do the efficient static_cast<>
+// instead.  Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+//    This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From>  // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) {  // so we only accept pointers
+  // Ensures that To is a sub-type of From *.  This test is here only
+  // for compile-time type checking, and has no overhead in an
+  // optimized build at run-time, as it will be optimized away
+  // completely.
+  if (false) {
+    const To to = NULL;
+    ::testing::internal::ImplicitCast_<From*>(to);
+  }
+
+#if GTEST_HAS_RTTI
+  // RTTI: debug mode only!
+  GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+  return static_cast<To>(f);
+}
+
+// Downcasts the pointer of type Base to Derived.
+// Derived must be a subclass of Base. The parameter MUST
+// point to a class of type Derived, not any subclass of it.
+// When RTTI is available, the function performs a runtime
+// check to enforce this.
+template <class Derived, class Base>
+Derived* CheckedDowncastToActualType(Base* base) {
+#if GTEST_HAS_RTTI
+  GTEST_CHECK_(typeid(*base) == typeid(Derived));
+  return dynamic_cast<Derived*>(base);  // NOLINT
+#else
+  return static_cast<Derived*>(base);  // Poor man's downcast.
+#endif
+}
+
+#if GTEST_HAS_STREAM_REDIRECTION
+
+// Defines the stderr capturer:
+//   CaptureStdout     - starts capturing stdout.
+//   GetCapturedStdout - stops capturing stdout and returns the captured string.
+//   CaptureStderr     - starts capturing stderr.
+//   GetCapturedStderr - stops capturing stderr and returns the captured string.
+//
+GTEST_API_ void CaptureStdout();
+GTEST_API_ std::string GetCapturedStdout();
+GTEST_API_ void CaptureStderr();
+GTEST_API_ std::string GetCapturedStderr();
+
+#endif  // GTEST_HAS_STREAM_REDIRECTION
+
+
+#if GTEST_HAS_DEATH_TEST
+
+const ::std::vector<testing::internal::string>& GetInjectableArgvs();
+void SetInjectableArgvs(const ::std::vector<testing::internal::string>*
+                             new_argvs);
+
+// A copy of all command line arguments.  Set by InitGoogleTest().
+extern ::std::vector<testing::internal::string> g_argvs;
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+// Defines synchronization primitives.
+
+#if GTEST_HAS_PTHREAD
+
+// Sleeps for (roughly) n milli-seconds.  This function is only for
+// testing Google Test's own constructs.  Don't use it in user tests,
+// either directly or indirectly.
+inline void SleepMilliseconds(int n) {
+  const timespec time = {
+    0,                  // 0 seconds.
+    n * 1000L * 1000L,  // And n ms.
+  };
+  nanosleep(&time, NULL);
+}
+
+// Allows a controller thread to pause execution of newly created
+// threads until notified.  Instances of this class must be created
+// and destroyed in the controller thread.
+//
+// This class is only for testing Google Test's own constructs. Do not
+// use it in user tests, either directly or indirectly.
+class Notification {
+ public:
+  Notification() : notified_(false) {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+  }
+  ~Notification() {
+    pthread_mutex_destroy(&mutex_);
+  }
+
+  // Notifies all threads created with this notification to start. Must
+  // be called from the controller thread.
+  void Notify() {
+    pthread_mutex_lock(&mutex_);
+    notified_ = true;
+    pthread_mutex_unlock(&mutex_);
+  }
+
+  // Blocks until the controller thread notifies. Must be called from a test
+  // thread.
+  void WaitForNotification() {
+    for (;;) {
+      pthread_mutex_lock(&mutex_);
+      const bool notified = notified_;
+      pthread_mutex_unlock(&mutex_);
+      if (notified)
+        break;
+      SleepMilliseconds(10);
+    }
+  }
+
+ private:
+  pthread_mutex_t mutex_;
+  bool notified_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Notification);
+};
+
+// As a C-function, ThreadFuncWithCLinkage cannot be templated itself.
+// Consequently, it cannot select a correct instantiation of ThreadWithParam
+// in order to call its Run(). Introducing ThreadWithParamBase as a
+// non-templated base class for ThreadWithParam allows us to bypass this
+// problem.
+class ThreadWithParamBase {
+ public:
+  virtual ~ThreadWithParamBase() {}
+  virtual void Run() = 0;
+};
+
+// pthread_create() accepts a pointer to a function type with the C linkage.
+// According to the Standard (7.5/1), function types with different linkages
+// are different even if they are otherwise identical.  Some compilers (for
+// example, SunStudio) treat them as different types.  Since class methods
+// cannot be defined with C-linkage we need to define a free C-function to
+// pass into pthread_create().
+extern "C" inline void* ThreadFuncWithCLinkage(void* thread) {
+  static_cast<ThreadWithParamBase*>(thread)->Run();
+  return NULL;
+}
+
+// Helper class for testing Google Test's multi-threading constructs.
+// To use it, write:
+//
+//   void ThreadFunc(int param) { /* Do things with param */ }
+//   Notification thread_can_start;
+//   ...
+//   // The thread_can_start parameter is optional; you can supply NULL.
+//   ThreadWithParam<int> thread(&ThreadFunc, 5, &thread_can_start);
+//   thread_can_start.Notify();
+//
+// These classes are only for testing Google Test's own constructs. Do
+// not use them in user tests, either directly or indirectly.
+template <typename T>
+class ThreadWithParam : public ThreadWithParamBase {
+ public:
+  typedef void (*UserThreadFunc)(T);
+
+  ThreadWithParam(
+      UserThreadFunc func, T param, Notification* thread_can_start)
+      : func_(func),
+        param_(param),
+        thread_can_start_(thread_can_start),
+        finished_(false) {
+    ThreadWithParamBase* const base = this;
+    // The thread can be created only after all fields except thread_
+    // have been initialized.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_create(&thread_, 0, &ThreadFuncWithCLinkage, base));
+  }
+  ~ThreadWithParam() { Join(); }
+
+  void Join() {
+    if (!finished_) {
+      GTEST_CHECK_POSIX_SUCCESS_(pthread_join(thread_, 0));
+      finished_ = true;
+    }
+  }
+
+  virtual void Run() {
+    if (thread_can_start_ != NULL)
+      thread_can_start_->WaitForNotification();
+    func_(param_);
+  }
+
+ private:
+  const UserThreadFunc func_;  // User-supplied thread function.
+  const T param_;  // User-supplied parameter to the thread function.
+  // When non-NULL, used to block execution until the controller thread
+  // notifies.
+  Notification* const thread_can_start_;
+  bool finished_;  // true iff we know that the thread function has finished.
+  pthread_t thread_;  // The native thread object.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
+};
+
+// MutexBase and Mutex implement mutex on pthreads-based platforms. They
+// are used in conjunction with class MutexLock:
+//
+//   Mutex mutex;
+//   ...
+//   MutexLock lock(&mutex);  // Acquires the mutex and releases it at the end
+//                            // of the current scope.
+//
+// MutexBase implements behavior for both statically and dynamically
+// allocated mutexes.  Do not use MutexBase directly.  Instead, write
+// the following to define a static mutex:
+//
+//   GTEST_DEFINE_STATIC_MUTEX_(g_some_mutex);
+//
+// You can forward declare a static mutex like this:
+//
+//   GTEST_DECLARE_STATIC_MUTEX_(g_some_mutex);
+//
+// To create a dynamic mutex, just define an object of type Mutex.
+class MutexBase {
+ public:
+  // Acquires this mutex.
+  void Lock() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&mutex_));
+    owner_ = pthread_self();
+    has_owner_ = true;
+  }
+
+  // Releases this mutex.
+  void Unlock() {
+    // Since the lock is being released the owner_ field should no longer be
+    // considered valid. We don't protect writing to has_owner_ here, as it's
+    // the caller's responsibility to ensure that the current thread holds the
+    // mutex when this is called.
+    has_owner_ = false;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&mutex_));
+  }
+
+  // Does nothing if the current thread holds the mutex. Otherwise, crashes
+  // with high probability.
+  void AssertHeld() const {
+    GTEST_CHECK_(has_owner_ && pthread_equal(owner_, pthread_self()))
+        << "The current thread is not holding the mutex @" << this;
+  }
+
+  // A static mutex may be used before main() is entered.  It may even
+  // be used before the dynamic initialization stage.  Therefore we
+  // must be able to initialize a static mutex object at link time.
+  // This means MutexBase has to be a POD and its member variables
+  // have to be public.
+ public:
+  pthread_mutex_t mutex_;  // The underlying pthread mutex.
+  // has_owner_ indicates whether the owner_ field below contains a valid thread
+  // ID and is therefore safe to inspect (e.g., to use in pthread_equal()). All
+  // accesses to the owner_ field should be protected by a check of this field.
+  // An alternative might be to memset() owner_ to all zeros, but there's no
+  // guarantee that a zero'd pthread_t is necessarily invalid or even different
+  // from pthread_self().
+  bool has_owner_;
+  pthread_t owner_;  // The thread holding the mutex.
+};
+
+// Forward-declares a static mutex.
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+    extern ::testing::internal::MutexBase mutex
+
+// Defines and statically (i.e. at link time) initializes a static mutex.
+// The initialization list here does not explicitly initialize each field,
+// instead relying on default initialization for the unspecified fields. In
+// particular, the owner_ field (a pthread_t) is not explicitly initialized.
+// This allows initialization to work whether pthread_t is a scalar or struct.
+// The flag -Wmissing-field-initializers must not be specified for this to work.
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+    ::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, false }
+
+// The Mutex class can only be used for mutexes created at runtime. It
+// shares its API with MutexBase otherwise.
+class Mutex : public MutexBase {
+ public:
+  Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_init(&mutex_, NULL));
+    has_owner_ = false;
+  }
+  ~Mutex() {
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&mutex_));
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Mutex);
+};
+
+// We cannot name this class MutexLock as the ctor declaration would
+// conflict with a macro named MutexLock, which is defined on some
+// platforms.  Hence the typedef trick below.
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(MutexBase* mutex)
+      : mutex_(mutex) { mutex_->Lock(); }
+
+  ~GTestMutexLock() { mutex_->Unlock(); }
+
+ private:
+  MutexBase* const mutex_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(GTestMutexLock);
+};
+
+typedef GTestMutexLock MutexLock;
+
+// Helpers for ThreadLocal.
+
+// pthread_key_create() requires DeleteThreadLocalValue() to have
+// C-linkage.  Therefore it cannot be templatized to access
+// ThreadLocal<T>.  Hence the need for class
+// ThreadLocalValueHolderBase.
+class ThreadLocalValueHolderBase {
+ public:
+  virtual ~ThreadLocalValueHolderBase() {}
+};
+
+// Called by pthread to delete thread-local data stored by
+// pthread_setspecific().
+extern "C" inline void DeleteThreadLocalValue(void* value_holder) {
+  delete static_cast<ThreadLocalValueHolderBase*>(value_holder);
+}
+
+// Implements thread-local storage on pthreads-based systems.
+//
+//   // Thread 1
+//   ThreadLocal<int> tl(100);  // 100 is the default value for each thread.
+//
+//   // Thread 2
+//   tl.set(150);  // Changes the value for thread 2 only.
+//   EXPECT_EQ(150, tl.get());
+//
+//   // Thread 1
+//   EXPECT_EQ(100, tl.get());  // In thread 1, tl has the original value.
+//   tl.set(200);
+//   EXPECT_EQ(200, tl.get());
+//
+// The template type argument T must have a public copy constructor.
+// In addition, the default ThreadLocal constructor requires T to have
+// a public default constructor.
+//
+// An object managed for a thread by a ThreadLocal instance is deleted
+// when the thread exits.  Or, if the ThreadLocal instance dies in
+// that thread, when the ThreadLocal dies.  It's the user's
+// responsibility to ensure that all other threads using a ThreadLocal
+// have exited when it dies, or the per-thread objects for those
+// threads will not be deleted.
+//
+// Google Test only uses global ThreadLocal objects.  That means they
+// will die after main() has returned.  Therefore, no per-thread
+// object managed by Google Test will be leaked as long as all threads
+// using Google Test have exited when main() returns.
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : key_(CreateKey()),
+                  default_() {}
+  explicit ThreadLocal(const T& value) : key_(CreateKey()),
+                                         default_(value) {}
+
+  ~ThreadLocal() {
+    // Destroys the managed object for the current thread, if any.
+    DeleteThreadLocalValue(pthread_getspecific(key_));
+
+    // Releases resources associated with the key.  This will *not*
+    // delete managed objects for other threads.
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_key_delete(key_));
+  }
+
+  T* pointer() { return GetOrCreateValue(); }
+  const T* pointer() const { return GetOrCreateValue(); }
+  const T& get() const { return *pointer(); }
+  void set(const T& value) { *pointer() = value; }
+
+ private:
+  // Holds a value of type T.
+  class ValueHolder : public ThreadLocalValueHolderBase {
+   public:
+    explicit ValueHolder(const T& value) : value_(value) {}
+
+    T* pointer() { return &value_; }
+
+   private:
+    T value_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ValueHolder);
+  };
+
+  static pthread_key_t CreateKey() {
+    pthread_key_t key;
+    // When a thread exits, DeleteThreadLocalValue() will be called on
+    // the object managed for that thread.
+    GTEST_CHECK_POSIX_SUCCESS_(
+        pthread_key_create(&key, &DeleteThreadLocalValue));
+    return key;
+  }
+
+  T* GetOrCreateValue() const {
+    ThreadLocalValueHolderBase* const holder =
+        static_cast<ThreadLocalValueHolderBase*>(pthread_getspecific(key_));
+    if (holder != NULL) {
+      return CheckedDowncastToActualType<ValueHolder>(holder)->pointer();
+    }
+
+    ValueHolder* const new_holder = new ValueHolder(default_);
+    ThreadLocalValueHolderBase* const holder_base = new_holder;
+    GTEST_CHECK_POSIX_SUCCESS_(pthread_setspecific(key_, holder_base));
+    return new_holder->pointer();
+  }
+
+  // A key pthreads uses for looking up per-thread values.
+  const pthread_key_t key_;
+  const T default_;  // The default value for each thread.
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
+};
+
+# define GTEST_IS_THREADSAFE 1
+
+#else  // GTEST_HAS_PTHREAD
+
+// A dummy implementation of synchronization primitives (mutex, lock,
+// and thread-local variable).  Necessary for compiling Google Test where
+// mutex is not supported - using Google Test in multiple threads is not
+// supported on such platforms.
+
+class Mutex {
+ public:
+  Mutex() {}
+  void Lock() {}
+  void Unlock() {}
+  void AssertHeld() const {}
+};
+
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+  extern ::testing::internal::Mutex mutex
+
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+
+class GTestMutexLock {
+ public:
+  explicit GTestMutexLock(Mutex*) {}  // NOLINT
+};
+
+typedef GTestMutexLock MutexLock;
+
+template <typename T>
+class ThreadLocal {
+ public:
+  ThreadLocal() : value_() {}
+  explicit ThreadLocal(const T& value) : value_(value) {}
+  T* pointer() { return &value_; }
+  const T* pointer() const { return &value_; }
+  const T& get() const { return value_; }
+  void set(const T& value) { value_ = value; }
+ private:
+  T value_;
+};
+
+// The above synchronization primitives have dummy implementations.
+// Therefore Google Test is not thread-safe.
+# define GTEST_IS_THREADSAFE 0
+
+#endif  // GTEST_HAS_PTHREAD
+
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+GTEST_API_ size_t GetThreadCount();
+
+// Passing non-POD classes through ellipsis (...) crashes the ARM
+// compiler and generates a warning in Sun Studio.  The Nokia Symbian
+// and the IBM XL C/C++ compiler try to instantiate a copy constructor
+// for objects passed through ellipsis (...), failing for uncopyable
+// objects.  We define this to ensure that only POD is passed through
+// ellipsis on these systems.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
+#else
+# define GTEST_CAN_COMPARE_NULL 1
+#endif
+
+// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
+// const T& and const T* in a function template.  These compilers
+// _can_ decide between class template specializations for T and T*,
+// so a tr1::type_traits-like is_pointer works.
+#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
+# define GTEST_NEEDS_IS_POINTER_ 1
+#endif
+
+template <bool bool_value>
+struct bool_constant {
+  typedef bool_constant<bool_value> type;
+  static const bool value = bool_value;
+};
+template <bool bool_value> const bool bool_constant<bool_value>::value;
+
+typedef bool_constant<false> false_type;
+typedef bool_constant<true> true_type;
+
+template <typename T>
+struct is_pointer : public false_type {};
+
+template <typename T>
+struct is_pointer<T*> : public true_type {};
+
+template <typename Iterator>
+struct IteratorTraits {
+  typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+  typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+  typedef T value_type;
+};
+
+#if GTEST_OS_WINDOWS
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
+// The biggest signed integer type the compiler supports.
+typedef __int64 BiggestInt;
+#else
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
+typedef long long BiggestInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF.  char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+  return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+  return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+  return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+  return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+  return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+  return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+  return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(wchar_t ch) {
+  const unsigned char low_byte = static_cast<unsigned char>(ch);
+  return ch == low_byte && isxdigit(low_byte) != 0;
+}
+
+inline char ToLower(char ch) {
+  return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+  return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
+// The testing::internal::posix namespace holds wrappers for common
+// POSIX functions.  These wrappers hide the differences between
+// Windows/MSVC and POSIX systems.  Since some compilers define these
+// standard functions as macros, the wrapper cannot have the same name
+// as the wrapped function.
+
+namespace posix {
+
+// Functions with a different name on Windows.
+
+#if GTEST_OS_WINDOWS
+
+typedef struct _stat StatStruct;
+
+# ifdef __BORLANDC__
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+# else  // !__BORLANDC__
+#  if GTEST_OS_WINDOWS_MOBILE
+inline int IsATTY(int /* fd */) { return 0; }
+#  else
+inline int IsATTY(int fd) { return _isatty(fd); }
+#  endif  // GTEST_OS_WINDOWS_MOBILE
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return _stricmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return _strdup(src); }
+# endif  // __BORLANDC__
+
+# if GTEST_OS_WINDOWS_MOBILE
+inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
+// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
+// time and thus not defined there.
+# else
+inline int FileNo(FILE* file) { return _fileno(file); }
+inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
+inline int RmDir(const char* dir) { return _rmdir(dir); }
+inline bool IsDir(const StatStruct& st) {
+  return (_S_IFDIR & st.st_mode) != 0;
+}
+# endif  // GTEST_OS_WINDOWS_MOBILE
+
+#else
+
+typedef struct stat StatStruct;
+
+inline int FileNo(FILE* file) { return fileno(file); }
+inline int IsATTY(int fd) { return isatty(fd); }
+inline int Stat(const char* path, StatStruct* buf) { return stat(path, buf); }
+inline int StrCaseCmp(const char* s1, const char* s2) {
+  return strcasecmp(s1, s2);
+}
+inline char* StrDup(const char* src) { return strdup(src); }
+inline int RmDir(const char* dir) { return rmdir(dir); }
+inline bool IsDir(const StatStruct& st) { return S_ISDIR(st.st_mode); }
+
+#endif  // GTEST_OS_WINDOWS
+
+// Functions deprecated by MSVC 8.0.
+
+#ifdef _MSC_VER
+// Temporarily disable warning 4996 (deprecated function).
+# pragma warning(push)
+# pragma warning(disable:4996)
+#endif
+
+inline const char* StrNCpy(char* dest, const char* src, size_t n) {
+  return strncpy(dest, src, n);
+}
+
+// ChDir(), FReopen(), FDOpen(), Read(), Write(), Close(), and
+// StrError() aren't needed on Windows CE at this time and thus not
+// defined there.
+
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int ChDir(const char* dir) { return chdir(dir); }
+#endif
+inline FILE* FOpen(const char* path, const char* mode) {
+  return fopen(path, mode);
+}
+#if !GTEST_OS_WINDOWS_MOBILE
+inline FILE *FReopen(const char* path, const char* mode, FILE* stream) {
+  return freopen(path, mode, stream);
+}
+inline FILE* FDOpen(int fd, const char* mode) { return fdopen(fd, mode); }
+#endif
+inline int FClose(FILE* fp) { return fclose(fp); }
+#if !GTEST_OS_WINDOWS_MOBILE
+inline int Read(int fd, void* buf, unsigned int count) {
+  return static_cast<int>(read(fd, buf, count));
+}
+inline int Write(int fd, const void* buf, unsigned int count) {
+  return static_cast<int>(write(fd, buf, count));
+}
+inline int Close(int fd) { return close(fd); }
+inline const char* StrError(int errnum) { return strerror(errnum); }
+#endif
+inline const char* GetEnv(const char* name) {
+#if GTEST_OS_WINDOWS_MOBILE
+  // We are on Windows CE, which has no environment variables.
+  return NULL;
+#elif defined(__BORLANDC__) || defined(__SunOS_5_8) || defined(__SunOS_5_9)
+  // Environment variables which we programmatically clear will be set to the
+  // empty string rather than unset (NULL).  Handle that case.
+  const char* const env = getenv(name);
+  return (env != NULL && env[0] != '\0') ? env : NULL;
+#else
+  return getenv(name);
+#endif
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)  // Restores the warning state.
+#endif
+
+#if GTEST_OS_WINDOWS_MOBILE
+// Windows CE has no C library. The abort() function is used in
+// several places in Google Test. This implementation provides a reasonable
+// imitation of standard behaviour.
+void Abort();
+#else
+inline void Abort() { abort(); }
+#endif  // GTEST_OS_WINDOWS_MOBILE
+
+}  // namespace posix
+
+// MSVC "deprecates" snprintf and issues warnings wherever it is used.  In
+// order to avoid these warnings, we need to use _snprintf or _snprintf_s on
+// MSVC-based platforms.  We map the GTEST_SNPRINTF_ macro to the appropriate
+// function in order to achieve that.  We use macro definition here because
+// snprintf is a variadic function.
+#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+// MSVC 2005 and above support variadic macros.
+# define GTEST_SNPRINTF_(buffer, size, format, ...) \
+     _snprintf_s(buffer, size, size, format, __VA_ARGS__)
+#elif defined(_MSC_VER)
+// Windows CE does not define _snprintf_s and MSVC prior to 2005 doesn't
+// complain about _snprintf.
+# define GTEST_SNPRINTF_ _snprintf
+#else
+# define GTEST_SNPRINTF_ snprintf
+#endif
+
+// The maximum number a BiggestInt can represent.  This definition
+// works no matter BiggestInt is represented in one's complement or
+// two's complement.
+//
+// We cannot rely on numeric_limits in STL, as __int64 and long long
+// are not part of standard C++ and numeric_limits doesn't need to be
+// defined for them.
+const BiggestInt kMaxBiggestInt =
+    ~(static_cast<BiggestInt>(1) << (8*sizeof(BiggestInt) - 1));
+
+// This template class serves as a compile-time function from size to
+// type.  It maps a size in bytes to a primitive type with that
+// size. e.g.
+//
+//   TypeWithSize<4>::UInt
+//
+// is typedef-ed to be unsigned int (unsigned integer made up of 4
+// bytes).
+//
+// Such functionality should belong to STL, but I cannot find it
+// there.
+//
+// Google Test uses this class in the implementation of floating-point
+// comparison.
+//
+// For now it only handles UInt (unsigned int) as that's all Google Test
+// needs.  Other types can be easily added in the future if need
+// arises.
+template <size_t size>
+class TypeWithSize {
+ public:
+  // This prevents the user from using TypeWithSize<N> with incorrect
+  // values of N.
+  typedef void UInt;
+};
+
+// The specialization for size 4.
+template <>
+class TypeWithSize<4> {
+ public:
+  // unsigned int has size 4 in both gcc and MSVC.
+  //
+  // As base/basictypes.h doesn't compile on Windows, we cannot use
+  // uint32, uint64, and etc here.
+  typedef int Int;
+  typedef unsigned int UInt;
+};
+
+// The specialization for size 8.
+template <>
+class TypeWithSize<8> {
+ public:
+#if GTEST_OS_WINDOWS
+  typedef __int64 Int;
+  typedef unsigned __int64 UInt;
+#else
+  typedef long long Int;  // NOLINT
+  typedef unsigned long long UInt;  // NOLINT
+#endif  // GTEST_OS_WINDOWS
+};
+
+// Integer types of known sizes.
+typedef TypeWithSize<4>::Int Int32;
+typedef TypeWithSize<4>::UInt UInt32;
+typedef TypeWithSize<8>::Int Int64;
+typedef TypeWithSize<8>::UInt UInt64;
+typedef TypeWithSize<8>::Int TimeInMillis;  // Represents time in milliseconds.
+
+// Utilities for command line flags and environment variables.
+
+// Macro for referencing flags.
+#define GTEST_FLAG(name) FLAGS_gtest_##name
+
+// Macros for declaring flags.
+#define GTEST_DECLARE_bool_(name) GTEST_API_ extern bool GTEST_FLAG(name)
+#define GTEST_DECLARE_int32_(name) \
+    GTEST_API_ extern ::testing::internal::Int32 GTEST_FLAG(name)
+#define GTEST_DECLARE_string_(name) \
+    GTEST_API_ extern ::std::string GTEST_FLAG(name)
+
+// Macros for defining flags.
+#define GTEST_DEFINE_bool_(name, default_val, doc) \
+    GTEST_API_ bool GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_int32_(name, default_val, doc) \
+    GTEST_API_ ::testing::internal::Int32 GTEST_FLAG(name) = (default_val)
+#define GTEST_DEFINE_string_(name, default_val, doc) \
+    GTEST_API_ ::std::string GTEST_FLAG(name) = (default_val)
+
+// Thread annotations
+#define GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
+#define GTEST_LOCK_EXCLUDED_(locks)
+
+// Parses 'str' for a 32-bit signed integer.  If successful, writes the result
+// to *value and returns true; otherwise leaves *value unchanged and returns
+// false.
+// TODO(chandlerc): Find a better way to refactor flag and environment parsing
+// out of both gtest-port.cc and gtest.cc to avoid exporting this utility
+// function.
+bool ParseInt32(const Message& src_text, const char* str, Int32* value);
+
+// Parses a bool/Int32/string from the environment variable
+// corresponding to the given Google Test flag.
+bool BoolFromGTestEnv(const char* flag, bool default_val);
+GTEST_API_ Int32 Int32FromGTestEnv(const char* flag, Int32 default_val);
+const char* StringFromGTestEnv(const char* flag, const char* default_val);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_H_
+
+#if GTEST_OS_LINUX
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+#endif  // GTEST_OS_LINUX
+
+#if GTEST_HAS_EXCEPTIONS
+# include <stdexcept>
+#endif
+
+#include <ctype.h>
+#include <float.h>
+#include <string.h>
+#include <iomanip>
+#include <limits>
+#include <set>
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the Message class.
+//
+// IMPORTANT NOTE: Due to limitation of the C++ language, we have to
+// leave some internal implementation details in this header file.
+// They are clearly marked by comments like this:
+//
+//   // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+//
+// Such code is NOT meant to be used by a user directly, and is subject
+// to CHANGE WITHOUT NOTICE.  Therefore DO NOT DEPEND ON IT in a user
+// program!
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+#define GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+
+#include <limits>
+
+
+// Ensures that there is at least one operator<< in the global namespace.
+// See Message& operator<<(...) below for why.
+void operator<<(const testing::internal::Secret&, int);
+
+namespace testing {
+
+// The Message class works like an ostream repeater.
+//
+// Typical usage:
+//
+//   1. You stream a bunch of values to a Message object.
+//      It will remember the text in a stringstream.
+//   2. Then you stream the Message object to an ostream.
+//      This causes the text in the Message to be streamed
+//      to the ostream.
+//
+// For example;
+//
+//   testing::Message foo;
+//   foo << 1 << " != " << 2;
+//   std::cout << foo;
+//
+// will print "1 != 2".
+//
+// Message is not intended to be inherited from.  In particular, its
+// destructor is not virtual.
+//
+// Note that stringstream behaves differently in gcc and in MSVC.  You
+// can stream a NULL char pointer to it in the former, but not in the
+// latter (it causes an access violation if you do).  The Message
+// class hides this difference by treating a NULL char pointer as
+// "(null)".
+class GTEST_API_ Message {
+ private:
+  // The type of basic IO manipulators (endl, ends, and flush) for
+  // narrow streams.
+  typedef std::ostream& (*BasicNarrowIoManip)(std::ostream&);
+
+ public:
+  // Constructs an empty Message.
+  Message();
+
+  // Copy constructor.
+  Message(const Message& msg) : ss_(new ::std::stringstream) {  // NOLINT
+    *ss_ << msg.GetString();
+  }
+
+  // Constructs a Message from a C-string.
+  explicit Message(const char* str) : ss_(new ::std::stringstream) {
+    *ss_ << str;
+  }
+
+#if GTEST_OS_SYMBIAN
+  // Streams a value (either a pointer or not) to this object.
+  template <typename T>
+  inline Message& operator <<(const T& value) {
+    StreamHelper(typename internal::is_pointer<T>::type(), value);
+    return *this;
+  }
+#else
+  // Streams a non-pointer value to this object.
+  template <typename T>
+  inline Message& operator <<(const T& val) {
+    // Some libraries overload << for STL containers.  These
+    // overloads are defined in the global namespace instead of ::std.
+    //
+    // C++'s symbol lookup rule (i.e. Koenig lookup) says that these
+    // overloads are visible in either the std namespace or the global
+    // namespace, but not other namespaces, including the testing
+    // namespace which Google Test's Message class is in.
+    //
+    // To allow STL containers (and other types that has a << operator
+    // defined in the global namespace) to be used in Google Test
+    // assertions, testing::Message must access the custom << operator
+    // from the global namespace.  With this using declaration,
+    // overloads of << defined in the global namespace and those
+    // visible via Koenig lookup are both exposed in this function.
+    using ::operator <<;
+    *ss_ << val;
+    return *this;
+  }
+
+  // Streams a pointer value to this object.
+  //
+  // This function is an overload of the previous one.  When you
+  // stream a pointer to a Message, this definition will be used as it
+  // is more specialized.  (The C++ Standard, section
+  // [temp.func.order].)  If you stream a non-pointer, then the
+  // previous definition will be used.
+  //
+  // The reason for this overload is that streaming a NULL pointer to
+  // ostream is undefined behavior.  Depending on the compiler, you
+  // may get "0", "(nil)", "(null)", or an access violation.  To
+  // ensure consistent result across compilers, we always treat NULL
+  // as "(null)".
+  template <typename T>
+  inline Message& operator <<(T* const& pointer) {  // NOLINT
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      *ss_ << pointer;
+    }
+    return *this;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // Since the basic IO manipulators are overloaded for both narrow
+  // and wide streams, we have to provide this specialized definition
+  // of operator <<, even though its body is the same as the
+  // templatized version above.  Without this definition, streaming
+  // endl or other basic IO manipulators to Message will confuse the
+  // compiler.
+  Message& operator <<(BasicNarrowIoManip val) {
+    *ss_ << val;
+    return *this;
+  }
+
+  // Instead of 1/0, we want to see true/false for bool values.
+  Message& operator <<(bool b) {
+    return *this << (b ? "true" : "false");
+  }
+
+  // These two overloads allow streaming a wide C string to a Message
+  // using the UTF-8 encoding.
+  Message& operator <<(const wchar_t* wide_c_str);
+  Message& operator <<(wchar_t* wide_c_str);
+
+#if GTEST_HAS_STD_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::std::wstring& wstr);
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+  // Converts the given wide string to a narrow string using the UTF-8
+  // encoding, and streams the result to this Message object.
+  Message& operator <<(const ::wstring& wstr);
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+  // Gets the text streamed to this object so far as an std::string.
+  // Each '\0' character in the buffer is replaced with "\\0".
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  std::string GetString() const;
+
+ private:
+
+#if GTEST_OS_SYMBIAN
+  // These are needed as the Nokia Symbian Compiler cannot decide between
+  // const T& and const T* in a function template. The Nokia compiler _can_
+  // decide between class template specializations for T and T*, so a
+  // tr1::type_traits-like is_pointer works, and we can overload on that.
+  template <typename T>
+  inline void StreamHelper(internal::true_type /*is_pointer*/, T* pointer) {
+    if (pointer == NULL) {
+      *ss_ << "(null)";
+    } else {
+      *ss_ << pointer;
+    }
+  }
+  template <typename T>
+  inline void StreamHelper(internal::false_type /*is_pointer*/,
+                           const T& value) {
+    // See the comments in Message& operator <<(const T&) above for why
+    // we need this using statement.
+    using ::operator <<;
+    *ss_ << value;
+  }
+#endif  // GTEST_OS_SYMBIAN
+
+  // We'll hold the text streamed to this object here.
+  const internal::scoped_ptr< ::std::stringstream> ss_;
+
+  // We declare (but don't implement) this to prevent the compiler
+  // from implementing the assignment operator.
+  void operator=(const Message&);
+};
+
+// Streams a Message to an ostream.
+inline std::ostream& operator <<(std::ostream& os, const Message& sb) {
+  return os << sb.GetString();
+}
+
+namespace internal {
+
+// Converts a streamable value to an std::string.  A NULL pointer is
+// converted to "(null)".  When the input value is a ::string,
+// ::std::string, ::wstring, or ::std::wstring object, each NUL
+// character in it is replaced with "\\0".
+template <typename T>
+std::string StreamableToString(const T& streamable) {
+  return (Message() << streamable).GetString();
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_MESSAGE_H_
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file declares the String class and functions used internally by
+// Google Test.  They are subject to change without notice. They should not used
+// by code external to Google Test.
+//
+// This header file is #included by <gtest/internal/gtest-internal.h>.
+// It should not be #included by other files.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+
+#ifdef __BORLANDC__
+// string.h is not guaranteed to provide strcpy on C++ Builder.
+# include <mem.h>
+#endif
+
+#include <string.h>
+#include <string>
+
+
+namespace testing {
+namespace internal {
+
+// String - an abstract class holding static string utilities.
+class GTEST_API_ String {
+ public:
+  // Static utility methods
+
+  // Clones a 0-terminated C string, allocating memory using new.  The
+  // caller is responsible for deleting the return value using
+  // delete[].  Returns the cloned string, or NULL if the input is
+  // NULL.
+  //
+  // This is different from strdup() in string.h, which allocates
+  // memory using malloc().
+  static const char* CloneCString(const char* c_str);
+
+#if GTEST_OS_WINDOWS_MOBILE
+  // Windows CE does not have the 'ANSI' versions of Win32 APIs. To be
+  // able to pass strings to Win32 APIs on CE we need to convert them
+  // to 'Unicode', UTF-16.
+
+  // Creates a UTF-16 wide string from the given ANSI string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the wide string, or NULL if the
+  // input is NULL.
+  //
+  // The wide string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static LPCWSTR AnsiToUtf16(const char* c_str);
+
+  // Creates an ANSI string from the given wide string, allocating
+  // memory using new. The caller is responsible for deleting the return
+  // value using delete[]. Returns the ANSI string, or NULL if the
+  // input is NULL.
+  //
+  // The returned string is created using the ANSI codepage (CP_ACP) to
+  // match the behaviour of the ANSI versions of Win32 calls and the
+  // C runtime.
+  static const char* Utf16ToAnsi(LPCWSTR utf16_str);
+#endif
+
+  // Compares two C strings.  Returns true iff they have the same content.
+  //
+  // Unlike strcmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CStringEquals(const char* lhs, const char* rhs);
+
+  // Converts a wide C string to a String using the UTF-8 encoding.
+  // NULL will be converted to "(null)".  If an error occurred during
+  // the conversion, "(failed to convert from wide string)" is
+  // returned.
+  static std::string ShowWideCString(const wchar_t* wide_c_str);
+
+  // Compares two wide C strings.  Returns true iff they have the same
+  // content.
+  //
+  // Unlike wcscmp(), this function can handle NULL argument(s).  A
+  // NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool WideCStringEquals(const wchar_t* lhs, const wchar_t* rhs);
+
+  // Compares two C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike strcasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL C string,
+  // including the empty string.
+  static bool CaseInsensitiveCStringEquals(const char* lhs,
+                                           const char* rhs);
+
+  // Compares two wide C strings, ignoring case.  Returns true iff they
+  // have the same content.
+  //
+  // Unlike wcscasecmp(), this function can handle NULL argument(s).
+  // A NULL C string is considered different to any non-NULL wide C string,
+  // including the empty string.
+  // NB: The implementations on different platforms slightly differ.
+  // On windows, this method uses _wcsicmp which compares according to LC_CTYPE
+  // environment variable. On GNU platform this method uses wcscasecmp
+  // which compares according to LC_CTYPE category of the current locale.
+  // On MacOS X, it uses towlower, which also uses LC_CTYPE category of the
+  // current locale.
+  static bool CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
+                                               const wchar_t* rhs);
+
+  // Returns true iff the given string ends with the given suffix, ignoring
+  // case. Any string is considered to end with an empty suffix.
+  static bool EndsWithCaseInsensitive(
+      const std::string& str, const std::string& suffix);
+
+  // Formats an int value as "%02d".
+  static std::string FormatIntWidth2(int value);  // "%02d" for width == 2
+
+  // Formats an int value as "%X".
+  static std::string FormatHexInt(int value);
+
+  // Formats a byte as "%02X".
+  static std::string FormatByte(unsigned char value);
+
+ private:
+  String();  // Not meant to be instantiated.
+};  // class String
+
+// Gets the content of the stringstream's buffer as an std::string.  Each '\0'
+// character in the buffer is replaced with "\\0".
+GTEST_API_ std::string StringStreamToString(::std::stringstream* stream);
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_STRING_H_
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: keith.ray@gmail.com (Keith Ray)
+//
+// Google Test filepath utilities
+//
+// This header file declares classes and functions used internally by
+// Google Test.  They are subject to change without notice.
+//
+// This file is #included in <gtest/internal/gtest-internal.h>.
+// Do not include this header file separately!
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+
+
+namespace testing {
+namespace internal {
+
+// FilePath - a class for file and directory pathname manipulation which
+// handles platform-specific conventions (like the pathname separator).
+// Used for helper functions for naming files in a directory for xml output.
+// Except for Set methods, all methods are const or static, which provides an
+// "immutable value object" -- useful for peace of mind.
+// A FilePath with a value ending in a path separator ("like/this/") represents
+// a directory, otherwise it is assumed to represent a file. In either case,
+// it may or may not represent an actual file or directory in the file system.
+// Names are NOT checked for syntax correctness -- no checking for illegal
+// characters, malformed paths, etc.
+
+class GTEST_API_ FilePath {
+ public:
+  FilePath() : pathname_("") { }
+  FilePath(const FilePath& rhs) : pathname_(rhs.pathname_) { }
+
+  explicit FilePath(const std::string& pathname) : pathname_(pathname) {
+    Normalize();
+  }
+
+  FilePath& operator=(const FilePath& rhs) {
+    Set(rhs);
+    return *this;
+  }
+
+  void Set(const FilePath& rhs) {
+    pathname_ = rhs.pathname_;
+  }
+
+  const std::string& string() const { return pathname_; }
+  const char* c_str() const { return pathname_.c_str(); }
+
+  // Returns the current working directory, or "" if unsuccessful.
+  static FilePath GetCurrentDir();
+
+  // Given directory = "dir", base_name = "test", number = 0,
+  // extension = "xml", returns "dir/test.xml". If number is greater
+  // than zero (e.g., 12), returns "dir/test_12.xml".
+  // On Windows platform, uses \ as the separator rather than /.
+  static FilePath MakeFileName(const FilePath& directory,
+                               const FilePath& base_name,
+                               int number,
+                               const char* extension);
+
+  // Given directory = "dir", relative_path = "test.xml",
+  // returns "dir/test.xml".
+  // On Windows, uses \ as the separator rather than /.
+  static FilePath ConcatPaths(const FilePath& directory,
+                              const FilePath& relative_path);
+
+  // Returns a pathname for a file that does not currently exist. The pathname
+  // will be directory/base_name.extension or
+  // directory/base_name_<number>.extension if directory/base_name.extension
+  // already exists. The number will be incremented until a pathname is found
+  // that does not already exist.
+  // Examples: 'dir/foo_test.xml' or 'dir/foo_test_1.xml'.
+  // There could be a race condition if two or more processes are calling this
+  // function at the same time -- they could both pick the same filename.
+  static FilePath GenerateUniqueFileName(const FilePath& directory,
+                                         const FilePath& base_name,
+                                         const char* extension);
+
+  // Returns true iff the path is "".
+  bool IsEmpty() const { return pathname_.empty(); }
+
+  // If input name has a trailing separator character, removes it and returns
+  // the name, otherwise return the name string unmodified.
+  // On Windows platform, uses \ as the separator, other platforms use /.
+  FilePath RemoveTrailingPathSeparator() const;
+
+  // Returns a copy of the FilePath with the directory part removed.
+  // Example: FilePath("path/to/file").RemoveDirectoryName() returns
+  // FilePath("file"). If there is no directory part ("just_a_file"), it returns
+  // the FilePath unmodified. If there is no file part ("just_a_dir/") it
+  // returns an empty FilePath ("").
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveDirectoryName() const;
+
+  // RemoveFileName returns the directory path with the filename removed.
+  // Example: FilePath("path/to/file").RemoveFileName() returns "path/to/".
+  // If the FilePath is "a_file" or "/a_file", RemoveFileName returns
+  // FilePath("./") or, on Windows, FilePath(".\\"). If the filepath does
+  // not have a file, like "just/a/dir/", it returns the FilePath unmodified.
+  // On Windows platform, '\' is the path separator, otherwise it is '/'.
+  FilePath RemoveFileName() const;
+
+  // Returns a copy of the FilePath with the case-insensitive extension removed.
+  // Example: FilePath("dir/file.exe").RemoveExtension("EXE") returns
+  // FilePath("dir/file"). If a case-insensitive extension is not
+  // found, returns a copy of the original FilePath.
+  FilePath RemoveExtension(const char* extension) const;
+
+  // Creates directories so that path exists. Returns true if successful or if
+  // the directories already exist; returns false if unable to create
+  // directories for any reason. Will also return false if the FilePath does
+  // not represent a directory (that is, it doesn't end with a path separator).
+  bool CreateDirectoriesRecursively() const;
+
+  // Create the directory so that path exists. Returns true if successful or
+  // if the directory already exists; returns false if unable to create the
+  // directory for any reason, including if the parent directory does not
+  // exist. Not named "CreateDirectory" because that's a macro on Windows.
+  bool CreateFolder() const;
+
+  // Returns true if FilePath describes something in the file-system,
+  // either a file, directory, or whatever, and that something exists.
+  bool FileOrDirectoryExists() const;
+
+  // Returns true if pathname describes a directory in the file-system
+  // that exists.
+  bool DirectoryExists() const;
+
+  // Returns true if FilePath ends with a path separator, which indicates that
+  // it is intended to represent a directory. Returns false otherwise.
+  // This does NOT check that a directory (or file) actually exists.
+  bool IsDirectory() const;
+
+  // Returns true if pathname describes a root directory. (Windows has one
+  // root directory per disk drive.)
+  bool IsRootDirectory() const;
+
+  // Returns true if pathname describes an absolute path.
+  bool IsAbsolutePath() const;
+
+ private:
+  // Replaces multiple consecutive separators with a single separator.
+  // For example, "bar///foo" becomes "bar/foo". Does not eliminate other
+  // redundancies that might be in a pathname involving "." or "..".
+  //
+  // A pathname with multiple consecutive separators may occur either through
+  // user error or as a result of some scripts or APIs that generate a pathname
+  // with a trailing separator. On other platforms the same API or script
+  // may NOT generate a pathname with a trailing "/". Then elsewhere that
+  // pathname may have another "/" and pathname components added to it,
+  // without checking for the separator already being there.
+  // The script language and operating system may allow paths like "foo//bar"
+  // but some of the functions in FilePath will not handle that correctly. In
+  // particular, RemoveTrailingPathSeparator() only removes one separator, and
+  // it is called in CreateDirectoriesRecursively() assuming that it will change
+  // a pathname from directory syntax (trailing separator) to filename syntax.
+  //
+  // On Windows this method also replaces the alternate path separator '/' with
+  // the primary path separator '\\', so that for example "bar\\/\\foo" becomes
+  // "bar\\foo".
+
+  void Normalize();
+
+  // Returns a pointer to the last occurence of a valid path separator in
+  // the FilePath. On Windows, for example, both '/' and '\' are valid path
+  // separators. Returns NULL if no path separator was found.
+  const char* FindLastPathSeparator() const;
+
+  std::string pathname_;
+};  // class FilePath
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
+// This file was GENERATED by command:
+//     pump.py gtest-type-util.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Type utilities needed for implementing typed and type-parameterized
+// tests.  This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently we support at most 50 types in a list, and at most 50
+// type-parameterized tests in one type-parameterized test case.
+// Please contact googletestframework@googlegroups.com if you need
+// more.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+
+// #ifdef __GNUC__ is too general here.  It is possible to use gcc without using
+// libstdc++ (which is where cxxabi.h comes from).
+# if GTEST_HAS_CXXABI_H_
+#  include <cxxabi.h>
+# elif defined(__HP_aCC)
+#  include <acxx_demangle.h>
+# endif  // GTEST_HASH_CXXABI_H_
+
+namespace testing {
+namespace internal {
+
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+# if GTEST_HAS_RTTI
+
+  const char* const name = typeid(T).name();
+#  if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+  int status = 0;
+  // gcc's implementation of typeid(T).name() mangles the type name,
+  // so we have to demangle it.
+#   if GTEST_HAS_CXXABI_H_
+  using abi::__cxa_demangle;
+#   endif  // GTEST_HAS_CXXABI_H_
+  char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+  const std::string name_str(status == 0 ? readable_name : name);
+  free(readable_name);
+  return name_str;
+#  else
+  return name;
+#  endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
+
+# else
+
+  return "<type>";
+
+# endif  // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
+// type.  This can be used as a compile-time assertion to ensure that
+// two types are equal.
+
+template <typename T1, typename T2>
+struct AssertTypeEq;
+
+template <typename T>
+struct AssertTypeEq<T, T> {
+  typedef bool type;
+};
+
+// A unique type used as the default value for the arguments of class
+// template Types.  This allows us to simulate variadic templates
+// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
+// support directly.
+struct None {};
+
+// The following family of struct and struct templates are used to
+// represent type lists.  In particular, TypesN<T1, T2, ..., TN>
+// represents a type list with N types (T1, T2, ..., and TN) in it.
+// Except for Types0, every struct in the family has two member types:
+// Head for the first type in the list, and Tail for the rest of the
+// list.
+
+// The empty type list.
+struct Types0 {};
+
+// Type lists of length 1, 2, 3, and so on.
+
+template <typename T1>
+struct Types1 {
+  typedef T1 Head;
+  typedef Types0 Tail;
+};
+template <typename T1, typename T2>
+struct Types2 {
+  typedef T1 Head;
+  typedef Types1<T2> Tail;
+};
+
+template <typename T1, typename T2, typename T3>
+struct Types3 {
+  typedef T1 Head;
+  typedef Types2<T2, T3> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types4 {
+  typedef T1 Head;
+  typedef Types3<T2, T3, T4> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types5 {
+  typedef T1 Head;
+  typedef Types4<T2, T3, T4, T5> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types6 {
+  typedef T1 Head;
+  typedef Types5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types7 {
+  typedef T1 Head;
+  typedef Types6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types8 {
+  typedef T1 Head;
+  typedef Types7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types9 {
+  typedef T1 Head;
+  typedef Types8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types10 {
+  typedef T1 Head;
+  typedef Types9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types11 {
+  typedef T1 Head;
+  typedef Types10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types12 {
+  typedef T1 Head;
+  typedef Types11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types13 {
+  typedef T1 Head;
+  typedef Types12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types14 {
+  typedef T1 Head;
+  typedef Types13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types15 {
+  typedef T1 Head;
+  typedef Types14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types16 {
+  typedef T1 Head;
+  typedef Types15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types17 {
+  typedef T1 Head;
+  typedef Types16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types18 {
+  typedef T1 Head;
+  typedef Types17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types19 {
+  typedef T1 Head;
+  typedef Types18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types20 {
+  typedef T1 Head;
+  typedef Types19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types21 {
+  typedef T1 Head;
+  typedef Types20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types22 {
+  typedef T1 Head;
+  typedef Types21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types23 {
+  typedef T1 Head;
+  typedef Types22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types24 {
+  typedef T1 Head;
+  typedef Types23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types25 {
+  typedef T1 Head;
+  typedef Types24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types26 {
+  typedef T1 Head;
+  typedef Types25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types27 {
+  typedef T1 Head;
+  typedef Types26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types28 {
+  typedef T1 Head;
+  typedef Types27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types29 {
+  typedef T1 Head;
+  typedef Types28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types30 {
+  typedef T1 Head;
+  typedef Types29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types31 {
+  typedef T1 Head;
+  typedef Types30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types32 {
+  typedef T1 Head;
+  typedef Types31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types33 {
+  typedef T1 Head;
+  typedef Types32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types34 {
+  typedef T1 Head;
+  typedef Types33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types35 {
+  typedef T1 Head;
+  typedef Types34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types36 {
+  typedef T1 Head;
+  typedef Types35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types37 {
+  typedef T1 Head;
+  typedef Types36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types38 {
+  typedef T1 Head;
+  typedef Types37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types39 {
+  typedef T1 Head;
+  typedef Types38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types40 {
+  typedef T1 Head;
+  typedef Types39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types41 {
+  typedef T1 Head;
+  typedef Types40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types42 {
+  typedef T1 Head;
+  typedef Types41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types43 {
+  typedef T1 Head;
+  typedef Types42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types44 {
+  typedef T1 Head;
+  typedef Types43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types45 {
+  typedef T1 Head;
+  typedef Types44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types46 {
+  typedef T1 Head;
+  typedef Types45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types47 {
+  typedef T1 Head;
+  typedef Types46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types48 {
+  typedef T1 Head;
+  typedef Types47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types49 {
+  typedef T1 Head;
+  typedef Types48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct Types50 {
+  typedef T1 Head;
+  typedef Types49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+      T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+      T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+      T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+}  // namespace internal
+
+// We don't want to require the users to write TypesN<...> directly,
+// as that would require them to count the length.  Types<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Types<int>
+// will appear as Types<int, None, None, ..., None> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Types<T1, ..., TN>, and Google Test will translate
+// that to TypesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Types template.
+template <typename T1 = internal::None, typename T2 = internal::None,
+    typename T3 = internal::None, typename T4 = internal::None,
+    typename T5 = internal::None, typename T6 = internal::None,
+    typename T7 = internal::None, typename T8 = internal::None,
+    typename T9 = internal::None, typename T10 = internal::None,
+    typename T11 = internal::None, typename T12 = internal::None,
+    typename T13 = internal::None, typename T14 = internal::None,
+    typename T15 = internal::None, typename T16 = internal::None,
+    typename T17 = internal::None, typename T18 = internal::None,
+    typename T19 = internal::None, typename T20 = internal::None,
+    typename T21 = internal::None, typename T22 = internal::None,
+    typename T23 = internal::None, typename T24 = internal::None,
+    typename T25 = internal::None, typename T26 = internal::None,
+    typename T27 = internal::None, typename T28 = internal::None,
+    typename T29 = internal::None, typename T30 = internal::None,
+    typename T31 = internal::None, typename T32 = internal::None,
+    typename T33 = internal::None, typename T34 = internal::None,
+    typename T35 = internal::None, typename T36 = internal::None,
+    typename T37 = internal::None, typename T38 = internal::None,
+    typename T39 = internal::None, typename T40 = internal::None,
+    typename T41 = internal::None, typename T42 = internal::None,
+    typename T43 = internal::None, typename T44 = internal::None,
+    typename T45 = internal::None, typename T46 = internal::None,
+    typename T47 = internal::None, typename T48 = internal::None,
+    typename T49 = internal::None, typename T50 = internal::None>
+struct Types {
+  typedef internal::Types50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Types<internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types0 type;
+};
+template <typename T1>
+struct Types<T1, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types1<T1> type;
+};
+template <typename T1, typename T2>
+struct Types<T1, T2, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types2<T1, T2> type;
+};
+template <typename T1, typename T2, typename T3>
+struct Types<T1, T2, T3, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types3<T1, T2, T3> type;
+};
+template <typename T1, typename T2, typename T3, typename T4>
+struct Types<T1, T2, T3, T4, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types4<T1, T2, T3, T4> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+struct Types<T1, T2, T3, T4, T5, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types5<T1, T2, T3, T4, T5> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+struct Types<T1, T2, T3, T4, T5, T6, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types6<T1, T2, T3, T4, T5, T6> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+struct Types<T1, T2, T3, T4, T5, T6, T7, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, internal::None,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None, internal::None> {
+  typedef internal::Types43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None, internal::None> {
+  typedef internal::Types44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    internal::None, internal::None, internal::None, internal::None,
+    internal::None> {
+  typedef internal::Types45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, internal::None, internal::None, internal::None, internal::None> {
+  typedef internal::Types46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, internal::None, internal::None, internal::None> {
+  typedef internal::Types47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, internal::None, internal::None> {
+  typedef internal::Types48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+struct Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15,
+    T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30,
+    T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44, T45,
+    T46, T47, T48, T49, internal::None> {
+  typedef internal::Types49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+namespace internal {
+
+# define GTEST_TEMPLATE_ template <typename T> class
+
+// The template "selector" struct TemplateSel<Tmpl> is used to
+// represent Tmpl, which must be a class template with one type
+// parameter, as a type.  TemplateSel<Tmpl>::Bind<T>::type is defined
+// as the type Tmpl<T>.  This allows us to actually instantiate the
+// template "selected" by TemplateSel<Tmpl>.
+//
+// This trick is necessary for simulating typedef for class templates,
+// which C++ doesn't support directly.
+template <GTEST_TEMPLATE_ Tmpl>
+struct TemplateSel {
+  template <typename T>
+  struct Bind {
+    typedef Tmpl<T> type;
+  };
+};
+
+# define GTEST_BIND_(TmplSel, T) \
+  TmplSel::template Bind<T>::type
+
+// A unique struct template used as the default value for the
+// arguments of class template Templates.  This allows us to simulate
+// variadic templates (e.g. Templates<int>, Templates<int, double>,
+// and etc), which C++ doesn't support directly.
+template <typename T>
+struct NoneT {};
+
+// The following family of struct and struct templates are used to
+// represent template lists.  In particular, TemplatesN<T1, T2, ...,
+// TN> represents a list of N templates (T1, T2, ..., and TN).  Except
+// for Templates0, every struct in the family has two member types:
+// Head for the selector of the first template in the list, and Tail
+// for the rest of the list.
+
+// The empty template list.
+struct Templates0 {};
+
+// Template lists of length 1, 2, 3, and so on.
+
+template <GTEST_TEMPLATE_ T1>
+struct Templates1 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates0 Tail;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates2 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates1<T2> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates3 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates2<T2, T3> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates4 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates3<T2, T3, T4> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates5 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates4<T2, T3, T4, T5> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates6 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates5<T2, T3, T4, T5, T6> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates7 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates6<T2, T3, T4, T5, T6, T7> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates8 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates7<T2, T3, T4, T5, T6, T7, T8> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates9 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates8<T2, T3, T4, T5, T6, T7, T8, T9> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates10 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates9<T2, T3, T4, T5, T6, T7, T8, T9, T10> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates11 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates10<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates12 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates11<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates13 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates12<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates14 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates13<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates15 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates14<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates16 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates15<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates17 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates16<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates18 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates17<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates19 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates18<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates20 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates19<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates21 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates20<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates22 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates21<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates23 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates22<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates24 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates23<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates25 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates24<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates26 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates25<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates27 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates26<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates28 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates27<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates29 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates28<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates30 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates29<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates31 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates30<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates32 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates31<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates33 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates32<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates34 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates33<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates35 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates34<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates36 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates35<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates37 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates36<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates38 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates37<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates39 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates38<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates40 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates39<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates41 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates40<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates42 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates41<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates43 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates42<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates44 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates43<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates45 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates44<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates46 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates45<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates47 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates46<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates48 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates47<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates49 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates48<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49> Tail;
+};
+
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49, GTEST_TEMPLATE_ T50>
+struct Templates50 {
+  typedef TemplateSel<T1> Head;
+  typedef Templates49<T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+      T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+      T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+      T43, T44, T45, T46, T47, T48, T49, T50> Tail;
+};
+
+
+// We don't want to require the users to write TemplatesN<...> directly,
+// as that would require them to count the length.  Templates<...> is much
+// easier to write, but generates horrible messages when there is a
+// compiler error, as gcc insists on printing out each template
+// argument, even if it has the default value (this means Templates<list>
+// will appear as Templates<list, NoneT, NoneT, ..., NoneT> in the compiler
+// errors).
+//
+// Our solution is to combine the best part of the two approaches: a
+// user would write Templates<T1, ..., TN>, and Google Test will translate
+// that to TemplatesN<T1, ..., TN> internally to make error messages
+// readable.  The translation is done by the 'type' member of the
+// Templates template.
+template <GTEST_TEMPLATE_ T1 = NoneT, GTEST_TEMPLATE_ T2 = NoneT,
+    GTEST_TEMPLATE_ T3 = NoneT, GTEST_TEMPLATE_ T4 = NoneT,
+    GTEST_TEMPLATE_ T5 = NoneT, GTEST_TEMPLATE_ T6 = NoneT,
+    GTEST_TEMPLATE_ T7 = NoneT, GTEST_TEMPLATE_ T8 = NoneT,
+    GTEST_TEMPLATE_ T9 = NoneT, GTEST_TEMPLATE_ T10 = NoneT,
+    GTEST_TEMPLATE_ T11 = NoneT, GTEST_TEMPLATE_ T12 = NoneT,
+    GTEST_TEMPLATE_ T13 = NoneT, GTEST_TEMPLATE_ T14 = NoneT,
+    GTEST_TEMPLATE_ T15 = NoneT, GTEST_TEMPLATE_ T16 = NoneT,
+    GTEST_TEMPLATE_ T17 = NoneT, GTEST_TEMPLATE_ T18 = NoneT,
+    GTEST_TEMPLATE_ T19 = NoneT, GTEST_TEMPLATE_ T20 = NoneT,
+    GTEST_TEMPLATE_ T21 = NoneT, GTEST_TEMPLATE_ T22 = NoneT,
+    GTEST_TEMPLATE_ T23 = NoneT, GTEST_TEMPLATE_ T24 = NoneT,
+    GTEST_TEMPLATE_ T25 = NoneT, GTEST_TEMPLATE_ T26 = NoneT,
+    GTEST_TEMPLATE_ T27 = NoneT, GTEST_TEMPLATE_ T28 = NoneT,
+    GTEST_TEMPLATE_ T29 = NoneT, GTEST_TEMPLATE_ T30 = NoneT,
+    GTEST_TEMPLATE_ T31 = NoneT, GTEST_TEMPLATE_ T32 = NoneT,
+    GTEST_TEMPLATE_ T33 = NoneT, GTEST_TEMPLATE_ T34 = NoneT,
+    GTEST_TEMPLATE_ T35 = NoneT, GTEST_TEMPLATE_ T36 = NoneT,
+    GTEST_TEMPLATE_ T37 = NoneT, GTEST_TEMPLATE_ T38 = NoneT,
+    GTEST_TEMPLATE_ T39 = NoneT, GTEST_TEMPLATE_ T40 = NoneT,
+    GTEST_TEMPLATE_ T41 = NoneT, GTEST_TEMPLATE_ T42 = NoneT,
+    GTEST_TEMPLATE_ T43 = NoneT, GTEST_TEMPLATE_ T44 = NoneT,
+    GTEST_TEMPLATE_ T45 = NoneT, GTEST_TEMPLATE_ T46 = NoneT,
+    GTEST_TEMPLATE_ T47 = NoneT, GTEST_TEMPLATE_ T48 = NoneT,
+    GTEST_TEMPLATE_ T49 = NoneT, GTEST_TEMPLATE_ T50 = NoneT>
+struct Templates {
+  typedef Templates50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49, T50> type;
+};
+
+template <>
+struct Templates<NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates0 type;
+};
+template <GTEST_TEMPLATE_ T1>
+struct Templates<T1, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates1<T1> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2>
+struct Templates<T1, T2, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates2<T1, T2> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3>
+struct Templates<T1, T2, T3, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates3<T1, T2, T3> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4>
+struct Templates<T1, T2, T3, T4, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates4<T1, T2, T3, T4> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5>
+struct Templates<T1, T2, T3, T4, T5, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates5<T1, T2, T3, T4, T5> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6>
+struct Templates<T1, T2, T3, T4, T5, T6, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates6<T1, T2, T3, T4, T5, T6> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates7<T1, T2, T3, T4, T5, T6, T7> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates8<T1, T2, T3, T4, T5, T6, T7, T8> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates9<T1, T2, T3, T4, T5, T6, T7, T8, T9> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT> {
+  typedef Templates24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT> {
+  typedef Templates28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT> {
+  typedef Templates29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, NoneT, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, NoneT, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, NoneT, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, NoneT, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, NoneT,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    NoneT, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, NoneT, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, NoneT, NoneT, NoneT, NoneT> {
+  typedef Templates46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, NoneT, NoneT, NoneT> {
+  typedef Templates47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, NoneT, NoneT> {
+  typedef Templates48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48> type;
+};
+template <GTEST_TEMPLATE_ T1, GTEST_TEMPLATE_ T2, GTEST_TEMPLATE_ T3,
+    GTEST_TEMPLATE_ T4, GTEST_TEMPLATE_ T5, GTEST_TEMPLATE_ T6,
+    GTEST_TEMPLATE_ T7, GTEST_TEMPLATE_ T8, GTEST_TEMPLATE_ T9,
+    GTEST_TEMPLATE_ T10, GTEST_TEMPLATE_ T11, GTEST_TEMPLATE_ T12,
+    GTEST_TEMPLATE_ T13, GTEST_TEMPLATE_ T14, GTEST_TEMPLATE_ T15,
+    GTEST_TEMPLATE_ T16, GTEST_TEMPLATE_ T17, GTEST_TEMPLATE_ T18,
+    GTEST_TEMPLATE_ T19, GTEST_TEMPLATE_ T20, GTEST_TEMPLATE_ T21,
+    GTEST_TEMPLATE_ T22, GTEST_TEMPLATE_ T23, GTEST_TEMPLATE_ T24,
+    GTEST_TEMPLATE_ T25, GTEST_TEMPLATE_ T26, GTEST_TEMPLATE_ T27,
+    GTEST_TEMPLATE_ T28, GTEST_TEMPLATE_ T29, GTEST_TEMPLATE_ T30,
+    GTEST_TEMPLATE_ T31, GTEST_TEMPLATE_ T32, GTEST_TEMPLATE_ T33,
+    GTEST_TEMPLATE_ T34, GTEST_TEMPLATE_ T35, GTEST_TEMPLATE_ T36,
+    GTEST_TEMPLATE_ T37, GTEST_TEMPLATE_ T38, GTEST_TEMPLATE_ T39,
+    GTEST_TEMPLATE_ T40, GTEST_TEMPLATE_ T41, GTEST_TEMPLATE_ T42,
+    GTEST_TEMPLATE_ T43, GTEST_TEMPLATE_ T44, GTEST_TEMPLATE_ T45,
+    GTEST_TEMPLATE_ T46, GTEST_TEMPLATE_ T47, GTEST_TEMPLATE_ T48,
+    GTEST_TEMPLATE_ T49>
+struct Templates<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
+    T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29,
+    T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44,
+    T45, T46, T47, T48, T49, NoneT> {
+  typedef Templates49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+      T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+      T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+      T42, T43, T44, T45, T46, T47, T48, T49> type;
+};
+
+// The TypeList template makes it possible to use either a single type
+// or a Types<...> list in TYPED_TEST_CASE() and
+// INSTANTIATE_TYPED_TEST_CASE_P().
+
+template <typename T>
+struct TypeList {
+  typedef Types1<T> type;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+struct TypeList<Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> > {
+  typedef typename Types<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+      T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+      T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+      T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
+
+// Due to C++ preprocessor weirdness, we need double indirection to
+// concatenate two tokens when one of them is __LINE__.  Writing
+//
+//   foo ## __LINE__
+//
+// will result in the token foo__LINE__, instead of foo followed by
+// the current line number.  For more details, see
+// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
+#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar)
+#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar
+
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
+namespace testing {
+
+// Forward declarations.
+
+class AssertionResult;                 // Result of an assertion.
+class Message;                         // Represents a failure message.
+class Test;                            // Represents a test.
+class TestInfo;                        // Information about a test.
+class TestPartResult;                  // Result of a test part.
+class UnitTest;                        // A collection of test cases.
+
+template <typename T>
+::std::string PrintToString(const T& value);
+
+namespace internal {
+
+struct TraceInfo;                      // Information about a trace point.
+class ScopedTrace;                     // Implements scoped trace.
+class TestInfoImpl;                    // Opaque implementation of TestInfo
+class UnitTestImpl;                    // Opaque implementation of UnitTest
+
+// How many times InitGoogleTest() has been called.
+GTEST_API_ extern int g_init_gtest_count;
+
+// The text used in failure messages to indicate the start of the
+// stack trace.
+GTEST_API_ extern const char kStackTraceMarker[];
+
+// Two overloaded helpers for checking at compile time whether an
+// expression is a null pointer literal (i.e. NULL or any 0-valued
+// compile-time integral constant).  Their return values have
+// different sizes, so we can use sizeof() to test which version is
+// picked by the compiler.  These helpers have no implementations, as
+// we only need their signatures.
+//
+// Given IsNullLiteralHelper(x), the compiler will pick the first
+// version if x can be implicitly converted to Secret*, and pick the
+// second version otherwise.  Since Secret is a secret and incomplete
+// type, the only expression a user can write that has type Secret* is
+// a null pointer literal.  Therefore, we know that x is a null
+// pointer literal if and only if the first version is picked by the
+// compiler.
+char IsNullLiteralHelper(Secret* p);
+char (&IsNullLiteralHelper(...))[2];  // NOLINT
+
+// A compile-time bool constant that is true if and only if x is a
+// null pointer literal (i.e. NULL or any 0-valued compile-time
+// integral constant).
+#ifdef GTEST_ELLIPSIS_NEEDS_POD_
+// We lose support for NULL detection where the compiler doesn't like
+// passing non-POD classes through ellipsis (...).
+# define GTEST_IS_NULL_LITERAL_(x) false
+#else
+# define GTEST_IS_NULL_LITERAL_(x) \
+    (sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
+#endif  // GTEST_ELLIPSIS_NEEDS_POD_
+
+// Appends the user-supplied message to the Google-Test-generated message.
+GTEST_API_ std::string AppendUserMessage(
+    const std::string& gtest_msg, const Message& user_msg);
+
+#if GTEST_HAS_EXCEPTIONS
+
+// This exception is thrown by (and only by) a failed Google Test
+// assertion when GTEST_FLAG(throw_on_failure) is true (if exceptions
+// are enabled).  We derive it from std::runtime_error, which is for
+// errors presumably detectable only at run time.  Since
+// std::runtime_error inherits from std::exception, many testing
+// frameworks know how to extract and print the message inside it.
+class GTEST_API_ GoogleTestFailureException : public ::std::runtime_error {
+ public:
+  explicit GoogleTestFailureException(const TestPartResult& failure);
+};
+
+#endif  // GTEST_HAS_EXCEPTIONS
+
+// A helper class for creating scoped traces in user programs.
+class GTEST_API_ ScopedTrace {
+ public:
+  // The c'tor pushes the given source file location and message onto
+  // a trace stack maintained by Google Test.
+  ScopedTrace(const char* file, int line, const Message& message);
+
+  // The d'tor pops the info pushed by the c'tor.
+  //
+  // Note that the d'tor is not virtual in order to be efficient.
+  // Don't inherit from ScopedTrace!
+  ~ScopedTrace();
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ScopedTrace);
+} GTEST_ATTRIBUTE_UNUSED_;  // A ScopedTrace object does its job in its
+                            // c'tor and d'tor.  Therefore it doesn't
+                            // need to be used otherwise.
+
+// Constructs and returns the message for an equality assertion
+// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
+//
+// The first four parameters are the expressions used in the assertion
+// and their values, as strings.  For example, for ASSERT_EQ(foo, bar)
+// where foo is 5 and bar is 6, we have:
+//
+//   expected_expression: "foo"
+//   actual_expression:   "bar"
+//   expected_value:      "5"
+//   actual_value:        "6"
+//
+// The ignoring_case parameter is true iff the assertion is a
+// *_STRCASEEQ*.  When it's true, the string " (ignoring case)" will
+// be inserted into the message.
+GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
+                                     const char* actual_expression,
+                                     const std::string& expected_value,
+                                     const std::string& actual_value,
+                                     bool ignoring_case);
+
+// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
+GTEST_API_ std::string GetBoolAssertionFailureMessage(
+    const AssertionResult& assertion_result,
+    const char* expression_text,
+    const char* actual_predicate_value,
+    const char* expected_predicate_value);
+
+// This template class represents an IEEE floating-point number
+// (either single-precision or double-precision, depending on the
+// template parameters).
+//
+// The purpose of this class is to do more sophisticated number
+// comparison.  (Due to round-off error, etc, it's very unlikely that
+// two floating-points will be equal exactly.  Hence a naive
+// comparison by the == operation often doesn't work.)
+//
+// Format of IEEE floating-point:
+//
+//   The most-significant bit being the leftmost, an IEEE
+//   floating-point looks like
+//
+//     sign_bit exponent_bits fraction_bits
+//
+//   Here, sign_bit is a single bit that designates the sign of the
+//   number.
+//
+//   For float, there are 8 exponent bits and 23 fraction bits.
+//
+//   For double, there are 11 exponent bits and 52 fraction bits.
+//
+//   More details can be found at
+//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+template <typename RawType>
+class FloatingPoint {
+ public:
+  // Defines the unsigned integer type that has the same size as the
+  // floating point number.
+  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;
+
+  // Constants.
+
+  // # of bits in a number.
+  static const size_t kBitCount = 8*sizeof(RawType);
+
+  // # of fraction bits in a number.
+  static const size_t kFractionBitCount =
+    std::numeric_limits<RawType>::digits - 1;
+
+  // # of exponent bits in a number.
+  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;
+
+  // The mask for the sign bit.
+  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);
+
+  // The mask for the fraction bits.
+  static const Bits kFractionBitMask =
+    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);
+
+  // The mask for the exponent bits.
+  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);
+
+  // How many ULP's (Units in the Last Place) we want to tolerate when
+  // comparing two numbers.  The larger the value, the more error we
+  // allow.  A 0 value means that two numbers must be exactly the same
+  // to be considered equal.
+  //
+  // The maximum error of a single floating-point operation is 0.5
+  // units in the last place.  On Intel CPU's, all floating-point
+  // calculations are done with 80-bit precision, while double has 64
+  // bits.  Therefore, 4 should be enough for ordinary use.
+  //
+  // See the following article for more details on ULP:
+  // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
+  static const size_t kMaxUlps = 4;
+
+  // Constructs a FloatingPoint from a raw floating-point number.
+  //
+  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
+  // around may change its bits, although the new value is guaranteed
+  // to be also a NAN.  Therefore, don't expect this constructor to
+  // preserve the bits in x when x is a NAN.
+  explicit FloatingPoint(const RawType& x) { u_.value_ = x; }
+
+  // Static methods
+
+  // Reinterprets a bit pattern as a floating-point number.
+  //
+  // This function is needed to test the AlmostEquals() method.
+  static RawType ReinterpretBits(const Bits bits) {
+    FloatingPoint fp(0);
+    fp.u_.bits_ = bits;
+    return fp.u_.value_;
+  }
+
+  // Returns the floating-point number that represent positive infinity.
+  static RawType Infinity() {
+    return ReinterpretBits(kExponentBitMask);
+  }
+
+  // Returns the maximum representable finite floating-point number.
+  static RawType Max();
+
+  // Non-static methods
+
+  // Returns the bits that represents this number.
+  const Bits &bits() const { return u_.bits_; }
+
+  // Returns the exponent bits of this number.
+  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }
+
+  // Returns the fraction bits of this number.
+  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }
+
+  // Returns the sign bit of this number.
+  Bits sign_bit() const { return kSignBitMask & u_.bits_; }
+
+  // Returns true iff this is NAN (not a number).
+  bool is_nan() const {
+    // It's a NAN if the exponent bits are all ones and the fraction
+    // bits are not entirely zeros.
+    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
+  }
+
+  // Returns true iff this number is at most kMaxUlps ULP's away from
+  // rhs.  In particular, this function:
+  //
+  //   - returns false if either number is (or both are) NAN.
+  //   - treats really large numbers as almost equal to infinity.
+  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
+  bool AlmostEquals(const FloatingPoint& rhs) const {
+    // The IEEE standard says that any comparison operation involving
+    // a NAN must return false.
+    if (is_nan() || rhs.is_nan()) return false;
+
+    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
+        <= kMaxUlps;
+  }
+
+ private:
+  // The data type used to store the actual floating-point number.
+  union FloatingPointUnion {
+    RawType value_;  // The raw floating-point number.
+    Bits bits_;      // The bits that represent the number.
+  };
+
+  // Converts an integer from the sign-and-magnitude representation to
+  // the biased representation.  More precisely, let N be 2 to the
+  // power of (kBitCount - 1), an integer x is represented by the
+  // unsigned number x + N.
+  //
+  // For instance,
+  //
+  //   -N + 1 (the most negative number representable using
+  //          sign-and-magnitude) is represented by 1;
+  //   0      is represented by N; and
+  //   N - 1  (the biggest number representable using
+  //          sign-and-magnitude) is represented by 2N - 1.
+  //
+  // Read http://en.wikipedia.org/wiki/Signed_number_representations
+  // for more details on signed number representations.
+  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
+    if (kSignBitMask & sam) {
+      // sam represents a negative number.
+      return ~sam + 1;
+    } else {
+      // sam represents a positive number.
+      return kSignBitMask | sam;
+    }
+  }
+
+  // Given two numbers in the sign-and-magnitude representation,
+  // returns the distance between them as an unsigned number.
+  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
+                                                     const Bits &sam2) {
+    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
+    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
+    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
+  }
+
+  FloatingPointUnion u_;
+};
+
+// We cannot use std::numeric_limits<T>::max() as it clashes with the max()
+// macro defined by <windows.h>.
+template <>
+inline float FloatingPoint<float>::Max() { return FLT_MAX; }
+template <>
+inline double FloatingPoint<double>::Max() { return DBL_MAX; }
+
+// Typedefs the instances of the FloatingPoint template class that we
+// care to use.
+typedef FloatingPoint<float> Float;
+typedef FloatingPoint<double> Double;
+
+// In order to catch the mistake of putting tests that use different
+// test fixture classes in the same test case, we need to assign
+// unique IDs to fixture classes and compare them.  The TypeId type is
+// used to hold such IDs.  The user should treat TypeId as an opaque
+// type: the only operation allowed on TypeId values is to compare
+// them for equality using the == operator.
+typedef const void* TypeId;
+
+template <typename T>
+class TypeIdHelper {
+ public:
+  // dummy_ must not have a const type.  Otherwise an overly eager
+  // compiler (e.g. MSVC 7.1 & 8.0) may try to merge
+  // TypeIdHelper<T>::dummy_ for different Ts as an "optimization".
+  static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
+
+// GetTypeId<T>() returns the ID of type T.  Different values will be
+// returned for different types.  Calling the function twice with the
+// same type argument is guaranteed to return the same ID.
+template <typename T>
+TypeId GetTypeId() {
+  // The compiler is required to allocate a different
+  // TypeIdHelper<T>::dummy_ variable for each T used to instantiate
+  // the template.  Therefore, the address of dummy_ is guaranteed to
+  // be unique.
+  return &(TypeIdHelper<T>::dummy_);
+}
+
+// Returns the type ID of ::testing::Test.  Always call this instead
+// of GetTypeId< ::testing::Test>() to get the type ID of
+// ::testing::Test, as the latter may give the wrong result due to a
+// suspected linker bug when compiling Google Test as a Mac OS X
+// framework.
+GTEST_API_ TypeId GetTestTypeId();
+
+// Defines the abstract factory interface that creates instances
+// of a Test object.
+class TestFactoryBase {
+ public:
+  virtual ~TestFactoryBase() {}
+
+  // Creates a test instance to run. The instance is both created and destroyed
+  // within TestInfoImpl::Run()
+  virtual Test* CreateTest() = 0;
+
+ protected:
+  TestFactoryBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestFactoryBase);
+};
+
+// This class provides implementation of TeastFactoryBase interface.
+// It is used in TEST and TEST_F macros.
+template <class TestClass>
+class TestFactoryImpl : public TestFactoryBase {
+ public:
+  virtual Test* CreateTest() { return new TestClass; }
+};
+
+#if GTEST_OS_WINDOWS
+
+// Predicate-formatters for implementing the HRESULT checking macros
+// {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}
+// We pass a long instead of HRESULT to avoid causing an
+// include dependency for the HRESULT type.
+GTEST_API_ AssertionResult IsHRESULTSuccess(const char* expr,
+                                            long hr);  // NOLINT
+GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
+                                            long hr);  // NOLINT
+
+#endif  // GTEST_OS_WINDOWS
+
+// Types of SetUpTestCase() and TearDownTestCase() functions.
+typedef void (*SetUpTestCaseFunc)();
+typedef void (*TearDownTestCaseFunc)();
+
+// Creates a new TestInfo object and registers it with Google Test;
+// returns the created object.
+//
+// Arguments:
+//
+//   test_case_name:   name of the test case
+//   name:             name of the test
+//   type_param        the name of the test's type parameter, or NULL if
+//                     this is not a typed or a type-parameterized test.
+//   value_param       text representation of the test's value parameter,
+//                     or NULL if this is not a type-parameterized test.
+//   fixture_class_id: ID of the test fixture class
+//   set_up_tc:        pointer to the function that sets up the test case
+//   tear_down_tc:     pointer to the function that tears down the test case
+//   factory:          pointer to the factory that creates a test object.
+//                     The newly created TestInfo instance will assume
+//                     ownership of the factory object.
+GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
+    const char* test_case_name,
+    const char* name,
+    const char* type_param,
+    const char* value_param,
+    TypeId fixture_class_id,
+    SetUpTestCaseFunc set_up_tc,
+    TearDownTestCaseFunc tear_down_tc,
+    TestFactoryBase* factory);
+
+// If *pstr starts with the given prefix, modifies *pstr to be right
+// past the prefix and returns true; otherwise leaves *pstr unchanged
+// and returns false.  None of pstr, *pstr, and prefix can be NULL.
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// State of the definition of a type-parameterized test case.
+class GTEST_API_ TypedTestCasePState {
+ public:
+  TypedTestCasePState() : registered_(false) {}
+
+  // Adds the given test name to defined_test_names_ and return true
+  // if the test case hasn't been registered; otherwise aborts the
+  // program.
+  bool AddTestName(const char* file, int line, const char* case_name,
+                   const char* test_name) {
+    if (registered_) {
+      fprintf(stderr, "%s Test %s must be defined before "
+              "REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
+              FormatFileLocation(file, line).c_str(), test_name, case_name);
+      fflush(stderr);
+      posix::Abort();
+    }
+    defined_test_names_.insert(test_name);
+    return true;
+  }
+
+  // Verifies that registered_tests match the test names in
+  // defined_test_names_; returns registered_tests if successful, or
+  // aborts the program otherwise.
+  const char* VerifyRegisteredTestNames(
+      const char* file, int line, const char* registered_tests);
+
+ private:
+  bool registered_;
+  ::std::set<const char*> defined_test_names_;
+};
+
+// Skips to the first non-space char after the first comma in 'str';
+// returns NULL if no comma is found in 'str'.
+inline const char* SkipComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  if (comma == NULL) {
+    return NULL;
+  }
+  while (IsSpace(*(++comma))) {}
+  return comma;
+}
+
+// Returns the prefix of 'str' before the first comma in it; returns
+// the entire string if it contains no comma.
+inline std::string GetPrefixUntilComma(const char* str) {
+  const char* comma = strchr(str, ',');
+  return comma == NULL ? str : std::string(str, comma);
+}
+
+// TypeParameterizedTest<Fixture, TestSel, Types>::Register()
+// registers a list of type-parameterized tests with Google Test.  The
+// return value is insignificant - we just need to return something
+// such that we can call this function in a namespace scope.
+//
+// Implementation note: The GTEST_TEMPLATE_ macro declares a template
+// template parameter.  It's defined in gtest-type-util.h.
+template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
+class TypeParameterizedTest {
+ public:
+  // 'index' is the index of the test in the type list 'Types'
+  // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
+  // Types).  Valid values for 'index' are [0, N - 1] where N is the
+  // length of Types.
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names, int index) {
+    typedef typename Types::Head Type;
+    typedef Fixture<Type> FixtureClass;
+    typedef typename GTEST_BIND_(TestSel, Type) TestClass;
+
+    // First, registers the first type-parameterized test in the type
+    // list.
+    MakeAndRegisterTestInfo(
+        (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/"
+         + StreamableToString(index)).c_str(),
+        GetPrefixUntilComma(test_names).c_str(),
+        GetTypeName<Type>().c_str(),
+        NULL,  // No value parameter.
+        GetTypeId<FixtureClass>(),
+        TestClass::SetUpTestCase,
+        TestClass::TearDownTestCase,
+        new TestFactoryImpl<TestClass>);
+
+    // Next, recurses (at compile time) with the tail of the type list.
+    return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
+        ::Register(prefix, case_name, test_names, index + 1);
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, class TestSel>
+class TypeParameterizedTest<Fixture, TestSel, Types0> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/, int /*index*/) {
+    return true;
+  }
+};
+
+// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
+// registers *all combinations* of 'Tests' and 'Types' with Google
+// Test.  The return value is insignificant - we just need to return
+// something such that we can call this function in a namespace scope.
+template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
+class TypeParameterizedTestCase {
+ public:
+  static bool Register(const char* prefix, const char* case_name,
+                       const char* test_names) {
+    typedef typename Tests::Head Head;
+
+    // First, register the first test in 'Test' for each type in 'Types'.
+    TypeParameterizedTest<Fixture, Head, Types>::Register(
+        prefix, case_name, test_names, 0);
+
+    // Next, recurses (at compile time) with the tail of the test list.
+    return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
+        ::Register(prefix, case_name, SkipComma(test_names));
+  }
+};
+
+// The base case for the compile time recursion.
+template <GTEST_TEMPLATE_ Fixture, typename Types>
+class TypeParameterizedTestCase<Fixture, Templates0, Types> {
+ public:
+  static bool Register(const char* /*prefix*/, const char* /*case_name*/,
+                       const char* /*test_names*/) {
+    return true;
+  }
+};
+
+#endif  // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
+// Returns the current OS stack trace as an std::string.
+//
+// The maximum number of stack frames to be included is specified by
+// the gtest_stack_trace_depth flag.  The skip_count parameter
+// specifies the number of top frames to be skipped, which doesn't
+// count against the number of frames to be included.
+//
+// For example, if Foo() calls Bar(), which in turn calls
+// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in
+// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't.
+GTEST_API_ std::string GetCurrentOsStackTraceExceptTop(
+    UnitTest* unit_test, int skip_count);
+
+// Helpers for suppressing warnings on unreachable code or constant
+// condition.
+
+// Always returns true.
+GTEST_API_ bool AlwaysTrue();
+
+// Always returns false.
+inline bool AlwaysFalse() { return !AlwaysTrue(); }
+
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+  ConstCharPtr(const char* str) : value(str) {}
+  operator bool() const { return true; }
+  const char* value;
+};
+
+// A simple Linear Congruential Generator for generating random
+// numbers with a uniform distribution.  Unlike rand() and srand(), it
+// doesn't use global state (and therefore can't interfere with user
+// code).  Unlike rand_r(), it's portable.  An LCG isn't very random,
+// but it's good enough for our purposes.
+class GTEST_API_ Random {
+ public:
+  static const UInt32 kMaxRange = 1u << 31;
+
+  explicit Random(UInt32 seed) : state_(seed) {}
+
+  void Reseed(UInt32 seed) { state_ = seed; }
+
+  // Generates a random number from [0, range).  Crashes if 'range' is
+  // 0 or greater than kMaxRange.
+  UInt32 Generate(UInt32 range);
+
+ private:
+  UInt32 state_;
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
+};
+
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; };  // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+    typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged.  This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; };  // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; };  // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'.  The following specialization works around the bug.
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+
+#if defined(_MSC_VER) && _MSC_VER < 1400
+// This is the only specialization that allows VC++ 7.1 to remove const in
+// 'const int[3] and 'const int[3][4]'.  However, it causes trouble with GCC
+// and thus needs to be conditionally compiled.
+template <typename T, size_t N>
+struct RemoveConst<T[N]> {
+  typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+    typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+    GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged.  This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; };  // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; };  // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+    typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary.  For example,
+// it transforms
+//
+//   char         ==> const char&
+//   const char   ==> const char&
+//   char&        ==> const char&
+//   const char&  ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+    GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+  // We need the following helper functions only for their types.
+  // They have no implementations.
+
+  // MakeFrom() is an expression whose type is From.  We cannot simply
+  // use From(), as the type From may not have a public default
+  // constructor.
+  static From MakeFrom();
+
+  // These two functions are overloaded.  Given an expression
+  // Helper(x), the compiler will pick the first version if x can be
+  // implicitly converted to type To; otherwise it will pick the
+  // second version.
+  //
+  // The first version returns a value of size 1, and the second
+  // version returns a value of size 2.  Therefore, by checking the
+  // size of Helper(x), which can be done at compile time, we can tell
+  // which version of Helper() is used, and hence whether x can be
+  // implicitly converted to type To.
+  static char Helper(To);
+  static char (&Helper(...))[2];  // NOLINT
+
+  // We have to put the 'public' section after the 'private' section,
+  // or MSVC refuses to compile the code.
+ public:
+  // MSVC warns about implicitly converting from double to int for
+  // possible loss of data, so we need to temporarily disable the
+  // warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4244)  // Temporarily disables warning 4244.
+
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop)           // Restores the warning state.
+#elif defined(__BORLANDC__)
+  // C++Builder cannot use member overload resolution during template
+  // instantiation.  The simplest workaround is to use its C++0x type traits
+  // functions (C++Builder 2009 and above only).
+  static const bool value = __is_convertible(From, To);
+#else
+  static const bool value =
+      sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif  // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+    : public bool_constant<
+  ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+  ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them).  It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0.  If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked.  Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator.  The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator').  If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+                            typename C::iterator* /* it */ = NULL,
+                            typename C::const_iterator* /* const_it */ = NULL) {
+  return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false.  To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; };  // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0.  When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+  return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+  for (size_t i = 0; i != size; i++) {
+    if (!internal::ArrayEq(lhs[i], rhs[i]))
+      return false;
+  }
+  return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem.  Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+  for (Iter it = begin; it != end; ++it) {
+    if (internal::ArrayEq(*it, elem))
+      return it;
+  }
+  return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0.  When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+  internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat.  If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+  for (size_t i = 0; i != size; i++) {
+    internal::CopyArray(from[i], to + i);
+  }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+  kReference,  // The NativeArray references the native array.
+  kCopy        // The NativeArray makes a copy of the native array and
+               // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container.  Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers.  New members
+// should be added as needed.  To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier).  It's the client's responsibility to satisfy
+// this requirement.  Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+  // STL-style container typedefs.
+  typedef Element value_type;
+  typedef Element* iterator;
+  typedef const Element* const_iterator;
+
+  // Constructs from a native array.
+  NativeArray(const Element* array, size_t count, RelationToSource relation) {
+    Init(array, count, relation);
+  }
+
+  // Copy constructor.
+  NativeArray(const NativeArray& rhs) {
+    Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+  }
+
+  ~NativeArray() {
+    // Ensures that the user doesn't instantiate NativeArray with a
+    // const or reference type.
+    static_cast<void>(StaticAssertTypeEqHelper<Element,
+        GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+    if (relation_to_source_ == kCopy)
+      delete[] array_;
+  }
+
+  // STL-style container methods.
+  size_t size() const { return size_; }
+  const_iterator begin() const { return array_; }
+  const_iterator end() const { return array_ + size_; }
+  bool operator==(const NativeArray& rhs) const {
+    return size() == rhs.size() &&
+        ArrayEq(begin(), size(), rhs.begin());
+  }
+
+ private:
+  // Initializes this object; makes a copy of the input array if
+  // 'relation' is kCopy.
+  void Init(const Element* array, size_t a_size, RelationToSource relation) {
+    if (relation == kReference) {
+      array_ = array;
+    } else {
+      Element* const copy = new Element[a_size];
+      CopyArray(array, a_size, copy);
+      array_ = copy;
+    }
+    size_ = a_size;
+    relation_to_source_ = relation;
+  }
+
+  const Element* array_;
+  size_t size_;
+  RelationToSource relation_to_source_;
+
+  GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+  ::testing::internal::AssertHelper(result_type, file, line, message) \
+    = ::testing::Message()
+
+#define GTEST_MESSAGE_(message, result_type) \
+  GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
+#define GTEST_FATAL_FAILURE_(message) \
+  return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
+
+#define GTEST_NONFATAL_FAILURE_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kNonFatalFailure)
+
+#define GTEST_SUCCESS_(message) \
+  GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
+
+// Suppresses MSVC warnings 4072 (unreachable code) for the code following
+// statement if it returns or throws (or doesn't return or throw in some
+// situations).
+#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
+  if (::testing::internal::AlwaysTrue()) { statement; }
+
+#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::ConstCharPtr gtest_msg = "") { \
+    bool gtest_caught_expected = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (expected_exception const&) { \
+      gtest_caught_expected = true; \
+    } \
+    catch (...) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws a different type."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+    if (!gtest_caught_expected) { \
+      gtest_msg.value = \
+          "Expected: " #statement " throws an exception of type " \
+          #expected_exception ".\n  Actual: it throws nothing."; \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
+      fail(gtest_msg.value)
+
+#define GTEST_TEST_NO_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
+      fail("Expected: " #statement " doesn't throw an exception.\n" \
+           "  Actual: it throws.")
+
+#define GTEST_TEST_ANY_THROW_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    bool gtest_caught_any = false; \
+    try { \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    } \
+    catch (...) { \
+      gtest_caught_any = true; \
+    } \
+    if (!gtest_caught_any) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
+      fail("Expected: " #statement " throws an exception.\n" \
+           "  Actual: it doesn't.")
+
+
+// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
+// either a boolean expression or an AssertionResult. text is a textual
+// represenation of expression as it was passed into the EXPECT_TRUE.
+#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar_ = \
+      ::testing::AssertionResult(expression)) \
+    ; \
+  else \
+    fail(::testing::internal::GetBoolAssertionFailureMessage(\
+        gtest_ar_, text, #actual, #expected).c_str())
+
+#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    ::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+    if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
+      fail("Expected: " #statement " doesn't generate new fatal " \
+           "failures in the current thread.\n" \
+           "  Actual: it does.")
+
+// Expands to the name of the class that implements the given test.
+#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+  test_case_name##_##test_name##_Test
+
+// Helper macro for defining tests.
+#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
+class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
+ public:\
+  GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
+ private:\
+  virtual void TestBody();\
+  static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
+};\
+\
+::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
+  ::test_info_ =\
+    ::testing::internal::MakeAndRegisterTestInfo(\
+        #test_case_name, #test_name, NULL, NULL, \
+        (parent_id), \
+        parent_class::SetUpTestCase, \
+        parent_class::TearDownTestCase, \
+        new ::testing::internal::TestFactoryImpl<\
+            GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
+void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines the public API for death tests.  It is
+// #included by gtest.h so a user doesn't need to include this
+// directly.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+
+// Copyright 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This header file defines internal utilities needed for implementing
+// death tests.  They are subject to change without notice.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+
+#include <stdio.h>
+
+namespace testing {
+namespace internal {
+
+GTEST_DECLARE_string_(internal_run_death_test);
+
+// Names of the flags (needed for parsing Google Test flags).
+const char kDeathTestStyleFlag[] = "death_test_style";
+const char kDeathTestUseFork[] = "death_test_use_fork";
+const char kInternalRunDeathTestFlag[] = "internal_run_death_test";
+
+#if GTEST_HAS_DEATH_TEST
+
+// DeathTest is a class that hides much of the complexity of the
+// GTEST_DEATH_TEST_ macro.  It is abstract; its static Create method
+// returns a concrete class that depends on the prevailing death test
+// style, as defined by the --gtest_death_test_style and/or
+// --gtest_internal_run_death_test flags.
+
+// In describing the results of death tests, these terms are used with
+// the corresponding definitions:
+//
+// exit status:  The integer exit information in the format specified
+//               by wait(2)
+// exit code:    The integer code passed to exit(3), _exit(2), or
+//               returned from main()
+class GTEST_API_ DeathTest {
+ public:
+  // Create returns false if there was an error determining the
+  // appropriate action to take for the current death test; for example,
+  // if the gtest_death_test_style flag is set to an invalid value.
+  // The LastMessage method will return a more detailed message in that
+  // case.  Otherwise, the DeathTest pointer pointed to by the "test"
+  // argument is set.  If the death test should be skipped, the pointer
+  // is set to NULL; otherwise, it is set to the address of a new concrete
+  // DeathTest object that controls the execution of the current test.
+  static bool Create(const char* statement, const RE* regex,
+                     const char* file, int line, DeathTest** test);
+  DeathTest();
+  virtual ~DeathTest() { }
+
+  // A helper class that aborts a death test when it's deleted.
+  class ReturnSentinel {
+   public:
+    explicit ReturnSentinel(DeathTest* test) : test_(test) { }
+    ~ReturnSentinel() { test_->Abort(TEST_ENCOUNTERED_RETURN_STATEMENT); }
+   private:
+    DeathTest* const test_;
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(ReturnSentinel);
+  } GTEST_ATTRIBUTE_UNUSED_;
+
+  // An enumeration of possible roles that may be taken when a death
+  // test is encountered.  EXECUTE means that the death test logic should
+  // be executed immediately.  OVERSEE means that the program should prepare
+  // the appropriate environment for a child process to execute the death
+  // test, then wait for it to complete.
+  enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
+
+  // An enumeration of the three reasons that a test might be aborted.
+  enum AbortReason {
+    TEST_ENCOUNTERED_RETURN_STATEMENT,
+    TEST_THREW_EXCEPTION,
+    TEST_DID_NOT_DIE
+  };
+
+  // Assumes one of the above roles.
+  virtual TestRole AssumeRole() = 0;
+
+  // Waits for the death test to finish and returns its status.
+  virtual int Wait() = 0;
+
+  // Returns true if the death test passed; that is, the test process
+  // exited during the test, its exit status matches a user-supplied
+  // predicate, and its stderr output matches a user-supplied regular
+  // expression.
+  // The user-supplied predicate may be a macro expression rather
+  // than a function pointer or functor, or else Wait and Passed could
+  // be combined.
+  virtual bool Passed(bool exit_status_ok) = 0;
+
+  // Signals that the death test did not die as expected.
+  virtual void Abort(AbortReason reason) = 0;
+
+  // Returns a human-readable outcome message regarding the outcome of
+  // the last death test.
+  static const char* LastMessage();
+
+  static void set_last_death_test_message(const std::string& message);
+
+ private:
+  // A string containing a description of the outcome of the last death test.
+  static std::string last_death_test_message_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(DeathTest);
+};
+
+// Factory interface for death tests.  May be mocked out for testing.
+class DeathTestFactory {
+ public:
+  virtual ~DeathTestFactory() { }
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test) = 0;
+};
+
+// A concrete DeathTestFactory implementation for normal use.
+class DefaultDeathTestFactory : public DeathTestFactory {
+ public:
+  virtual bool Create(const char* statement, const RE* regex,
+                      const char* file, int line, DeathTest** test);
+};
+
+// Returns true if exit_status describes a process that was terminated
+// by a signal, or exited normally with a nonzero exit code.
+GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  try { \
+    GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } catch (const ::std::exception& gtest_exception) { \
+    fprintf(\
+        stderr, \
+        "\n%s: Caught std::exception-derived exception escaping the " \
+        "death test statement. Exception message: %s\n", \
+        ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+        gtest_exception.what()); \
+    fflush(stderr); \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  } catch (...) { \
+    death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+  }
+
+# else
+#  define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+  GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
+// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
+// ASSERT_EXIT*, and EXPECT_EXIT*.
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+    const ::testing::internal::RE& gtest_regex = (regex); \
+    ::testing::internal::DeathTest* gtest_dt; \
+    if (!::testing::internal::DeathTest::Create(#statement, &gtest_regex, \
+        __FILE__, __LINE__, &gtest_dt)) { \
+      goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+    } \
+    if (gtest_dt != NULL) { \
+      ::testing::internal::scoped_ptr< ::testing::internal::DeathTest> \
+          gtest_dt_ptr(gtest_dt); \
+      switch (gtest_dt->AssumeRole()) { \
+        case ::testing::internal::DeathTest::OVERSEE_TEST: \
+          if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
+            goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
+          } \
+          break; \
+        case ::testing::internal::DeathTest::EXECUTE_TEST: { \
+          ::testing::internal::DeathTest::ReturnSentinel \
+              gtest_sentinel(gtest_dt); \
+          GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
+          gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
+          break; \
+        } \
+        default: \
+          break; \
+      } \
+    } \
+  } else \
+    GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__): \
+      fail(::testing::internal::DeathTest::LastMessage())
+// The symbol "fail" here expands to something into which a message
+// can be streamed.
+
+// This macro is for implementing ASSERT/EXPECT_DEBUG_DEATH when compiled in
+// NDEBUG mode. In this case we need the statements to be executed, the regex is
+// ignored, and the macro must accept a streamed message even though the message
+// is never printed.
+# define GTEST_EXECUTE_STATEMENT_(statement, regex) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (::testing::internal::AlwaysTrue()) { \
+     GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+  } else \
+    ::testing::Message()
+
+// A class representing the parsed contents of the
+// --gtest_internal_run_death_test flag, as it existed when
+// RUN_ALL_TESTS was called.
+class InternalRunDeathTestFlag {
+ public:
+  InternalRunDeathTestFlag(const std::string& a_file,
+                           int a_line,
+                           int an_index,
+                           int a_write_fd)
+      : file_(a_file), line_(a_line), index_(an_index),
+        write_fd_(a_write_fd) {}
+
+  ~InternalRunDeathTestFlag() {
+    if (write_fd_ >= 0)
+      posix::Close(write_fd_);
+  }
+
+  const std::string& file() const { return file_; }
+  int line() const { return line_; }
+  int index() const { return index_; }
+  int write_fd() const { return write_fd_; }
+
+ private:
+  std::string file_;
+  int line_;
+  int index_;
+  int write_fd_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(InternalRunDeathTestFlag);
+};
+
+// Returns a newly created InternalRunDeathTestFlag object with fields
+// initialized from the GTEST_FLAG(internal_run_death_test) flag if
+// the flag is specified; otherwise returns NULL.
+InternalRunDeathTestFlag* ParseInternalRunDeathTestFlag();
+
+#else  // GTEST_HAS_DEATH_TEST
+
+// This macro is used for implementing macros such as
+// EXPECT_DEATH_IF_SUPPORTED and ASSERT_DEATH_IF_SUPPORTED on systems where
+// death tests are not supported. Those macros must compile on such systems
+// iff EXPECT_DEATH and ASSERT_DEATH compile with the same parameters on
+// systems that support death tests. This allows one to write such a macro
+// on a system that does not support death tests and be sure that it will
+// compile on a death-test supporting system.
+//
+// Parameters:
+//   statement -  A statement that a macro such as EXPECT_DEATH would test
+//                for program termination. This macro has to make sure this
+//                statement is compiled but not executed, to ensure that
+//                EXPECT_DEATH_IF_SUPPORTED compiles with a certain
+//                parameter iff EXPECT_DEATH compiles with it.
+//   regex     -  A regex that a macro such as EXPECT_DEATH would use to test
+//                the output of statement.  This parameter has to be
+//                compiled but not evaluated by this macro, to ensure that
+//                this macro only accepts expressions that a macro such as
+//                EXPECT_DEATH would accept.
+//   terminator - Must be an empty statement for EXPECT_DEATH_IF_SUPPORTED
+//                and a return statement for ASSERT_DEATH_IF_SUPPORTED.
+//                This ensures that ASSERT_DEATH_IF_SUPPORTED will not
+//                compile inside functions where ASSERT_DEATH doesn't
+//                compile.
+//
+//  The branch that has an always false condition is used to ensure that
+//  statement and regex are compiled (and thus syntactically correct) but
+//  never executed. The unreachable code macro protects the terminator
+//  statement from generating an 'unreachable code' warning in case
+//  statement unconditionally returns or throws. The Message constructor at
+//  the end allows the syntax of streaming additional messages into the
+//  macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+    GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+    if (::testing::internal::AlwaysTrue()) { \
+      GTEST_LOG_(WARNING) \
+          << "Death tests are not supported on this platform.\n" \
+          << "Statement '" #statement "' cannot be verified."; \
+    } else if (::testing::internal::AlwaysFalse()) { \
+      ::testing::internal::RE::PartialMatch(".*", (regex)); \
+      GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+      terminator; \
+    } else \
+      ::testing::Message()
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
+
+namespace testing {
+
+// This flag controls the style of death tests.  Valid values are "threadsafe",
+// meaning that the death test child process will re-execute the test binary
+// from the start, running only a single death test, or "fast",
+// meaning that the child process will execute the test logic immediately
+// after forking.
+GTEST_DECLARE_string_(death_test_style);
+
+#if GTEST_HAS_DEATH_TEST
+
+namespace internal {
+
+// Returns a Boolean value indicating whether the caller is currently
+// executing in the context of the death test child process.  Tools such as
+// Valgrind heap checkers may need this to modify their behavior in death
+// tests.  IMPORTANT: This is an internal utility.  Using it may break the
+// implementation of death tests.  User code MUST NOT use it.
+GTEST_API_ bool InDeathTestChild();
+
+}  // namespace internal
+
+// The following macros are useful for writing death tests.
+
+// Here's what happens when an ASSERT_DEATH* or EXPECT_DEATH* is
+// executed:
+//
+//   1. It generates a warning if there is more than one active
+//   thread.  This is because it's safe to fork() or clone() only
+//   when there is a single thread.
+//
+//   2. The parent process clone()s a sub-process and runs the death
+//   test in it; the sub-process exits with code 0 at the end of the
+//   death test, if it hasn't exited already.
+//
+//   3. The parent process waits for the sub-process to terminate.
+//
+//   4. The parent process checks the exit code and error message of
+//   the sub-process.
+//
+// Examples:
+//
+//   ASSERT_DEATH(server.SendMessage(56, "Hello"), "Invalid port number");
+//   for (int i = 0; i < 5; i++) {
+//     EXPECT_DEATH(server.ProcessRequest(i),
+//                  "Invalid request .* in ProcessRequest()")
+//                  << "Failed to die on request " << i;
+//   }
+//
+//   ASSERT_EXIT(server.ExitNow(), ::testing::ExitedWithCode(0), "Exiting");
+//
+//   bool KilledBySIGHUP(int exit_code) {
+//     return WIFSIGNALED(exit_code) && WTERMSIG(exit_code) == SIGHUP;
+//   }
+//
+//   ASSERT_EXIT(client.HangUpServer(), KilledBySIGHUP, "Hanging up!");
+//
+// On the regular expressions used in death tests:
+//
+//   On POSIX-compliant systems (*nix), we use the <regex.h> library,
+//   which uses the POSIX extended regex syntax.
+//
+//   On other platforms (e.g. Windows), we only support a simple regex
+//   syntax implemented as part of Google Test.  This limited
+//   implementation should be enough most of the time when writing
+//   death tests; though it lacks many features you can find in PCRE
+//   or POSIX extended regex syntax.  For example, we don't support
+//   union ("x|y"), grouping ("(xy)"), brackets ("[xy]"), and
+//   repetition count ("x{5,7}"), among others.
+//
+//   Below is the syntax that we do support.  We chose it to be a
+//   subset of both PCRE and POSIX extended regex, so it's easy to
+//   learn wherever you come from.  In the following: 'A' denotes a
+//   literal character, period (.), or a single \\ escape sequence;
+//   'x' and 'y' denote regular expressions; 'm' and 'n' are for
+//   natural numbers.
+//
+//     c     matches any literal character c
+//     \\d   matches any decimal digit
+//     \\D   matches any character that's not a decimal digit
+//     \\f   matches \f
+//     \\n   matches \n
+//     \\r   matches \r
+//     \\s   matches any ASCII whitespace, including \n
+//     \\S   matches any character that's not a whitespace
+//     \\t   matches \t
+//     \\v   matches \v
+//     \\w   matches any letter, _, or decimal digit
+//     \\W   matches any character that \\w doesn't match
+//     \\c   matches any literal character c, which must be a punctuation
+//     .     matches any single character except \n
+//     A?    matches 0 or 1 occurrences of A
+//     A*    matches 0 or many occurrences of A
+//     A+    matches 1 or many occurrences of A
+//     ^     matches the beginning of a string (not that of each line)
+//     $     matches the end of a string (not that of each line)
+//     xy    matches x followed by y
+//
+//   If you accidentally use PCRE or POSIX extended regex features
+//   not implemented by us, you will get a run-time failure.  In that
+//   case, please try to rewrite your regular expression within the
+//   above syntax.
+//
+//   This implementation is *not* meant to be as highly tuned or robust
+//   as a compiled regex library, but should perform well enough for a
+//   death test, which already incurs significant overhead by launching
+//   a child process.
+//
+// Known caveats:
+//
+//   A "threadsafe" style death test obtains the path to the test
+//   program from argv[0] and re-executes it in the sub-process.  For
+//   simplicity, the current implementation doesn't search the PATH
+//   when launching the sub-process.  This means that the user must
+//   invoke the test program via a path that contains at least one
+//   path separator (e.g. path/to/foo_test and
+//   /absolute/path/to/bar_test are fine, but foo_test is not).  This
+//   is rarely a problem as people usually don't put the test binary
+//   directory in PATH.
+//
+// TODO(wan@google.com): make thread-safe death tests search the PATH.
+
+// Asserts that a given statement causes the program to exit, with an
+// integer exit status that satisfies predicate, and emitting error output
+// that matches regex.
+# define ASSERT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+
+// Like ASSERT_EXIT, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_EXIT(statement, predicate, regex) \
+    GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+
+// Asserts that a given statement causes the program to exit, either by
+// explicitly exiting with a nonzero exit code or being killed by a
+// signal, and emitting error output that matches regex.
+# define ASSERT_DEATH(statement, regex) \
+    ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Like ASSERT_DEATH, but continues on to successive tests in the
+// test case, if any:
+# define EXPECT_DEATH(statement, regex) \
+    EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+
+// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
+
+// Tests that an exit code describes a normal exit with a given exit code.
+class GTEST_API_ ExitedWithCode {
+ public:
+  explicit ExitedWithCode(int exit_code);
+  bool operator()(int exit_status) const;
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ExitedWithCode& other);
+
+  const int exit_code_;
+};
+
+# if !GTEST_OS_WINDOWS
+// Tests that an exit code describes an exit due to termination by a
+// given signal.
+class GTEST_API_ KilledBySignal {
+ public:
+  explicit KilledBySignal(int signum);
+  bool operator()(int exit_status) const;
+ private:
+  const int signum_;
+};
+# endif  // !GTEST_OS_WINDOWS
+
+// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
+// The death testing framework causes this to have interesting semantics,
+// since the sideeffects of the call are only visible in opt mode, and not
+// in debug mode.
+//
+// In practice, this can be used to test functions that utilize the
+// LOG(DFATAL) macro using the following style:
+//
+// int DieInDebugOr12(int* sideeffect) {
+//   if (sideeffect) {
+//     *sideeffect = 12;
+//   }
+//   LOG(DFATAL) << "death";
+//   return 12;
+// }
+//
+// TEST(TestCase, TestDieOr12WorksInDgbAndOpt) {
+//   int sideeffect = 0;
+//   // Only asserts in dbg.
+//   EXPECT_DEBUG_DEATH(DieInDebugOr12(&sideeffect), "death");
+//
+// #ifdef NDEBUG
+//   // opt-mode has sideeffect visible.
+//   EXPECT_EQ(12, sideeffect);
+// #else
+//   // dbg-mode no visible sideeffect.
+//   EXPECT_EQ(0, sideeffect);
+// #endif
+// }
+//
+// This will assert that DieInDebugReturn12InOpt() crashes in debug
+// mode, usually due to a DCHECK or LOG(DFATAL), but returns the
+// appropriate fallback value (12 in this case) in opt mode. If you
+// need to test that a function has appropriate side-effects in opt
+// mode, include assertions against the side-effects.  A general
+// pattern for this is:
+//
+// EXPECT_DEBUG_DEATH({
+//   // Side-effects here will have an effect after this statement in
+//   // opt mode, but none in debug mode.
+//   EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
+// }, "death");
+//
+# ifdef NDEBUG
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  GTEST_EXECUTE_STATEMENT_(statement, regex)
+
+# else
+
+#  define EXPECT_DEBUG_DEATH(statement, regex) \
+  EXPECT_DEATH(statement, regex)
+
+#  define ASSERT_DEBUG_DEATH(statement, regex) \
+  ASSERT_DEATH(statement, regex)
+
+# endif  // NDEBUG for EXPECT_DEBUG_DEATH
+#endif  // GTEST_HAS_DEATH_TEST
+
+// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
+// ASSERT_DEATH_IF_SUPPORTED(statement, regex) expand to real death tests if
+// death tests are supported; otherwise they just issue a warning.  This is
+// useful when you are combining death test assertions with normal test
+// assertions in one test.
+#if GTEST_HAS_DEATH_TEST
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    EXPECT_DEATH(statement, regex)
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    ASSERT_DEATH(statement, regex)
+#else
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+    GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
+#endif
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
+// This file was GENERATED by command:
+//     pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Authors: vladl@google.com (Vlad Losev)
+//
+// Macros and functions for implementing parameterized tests
+// in Google C++ Testing Framework (Google Test)
+//
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+
+
+// Value-parameterized tests allow you to test your code with different
+// parameters without writing multiple copies of the same test.
+//
+// Here is how you use value-parameterized tests:
+
+#if 0
+
+// To write value-parameterized tests, first you should define a fixture
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
+
+class FooTest : public ::testing::TestWithParam<const char*> {
+  // You can implement all the usual class fixture members here.
+};
+
+// Then, use the TEST_P macro to define as many parameterized tests
+// for this fixture as you want. The _P suffix is for "parameterized"
+// or "pattern", whichever you prefer to think.
+
+TEST_P(FooTest, DoesBlah) {
+  // Inside a test, access the test parameter with the GetParam() method
+  // of the TestWithParam<T> class:
+  EXPECT_TRUE(foo.Blah(GetParam()));
+  ...
+}
+
+TEST_P(FooTest, HasBlahBlah) {
+  ...
+}
+
+// Finally, you can use INSTANTIATE_TEST_CASE_P to instantiate the test
+// case with any set of parameters you want. Google Test defines a number
+// of functions for generating test parameters. They return what we call
+// (surprise!) parameter generators. Here is a  summary of them, which
+// are all in the testing namespace:
+//
+//
+//  Range(begin, end [, step]) - Yields values {begin, begin+step,
+//                               begin+step+step, ...}. The values do not
+//                               include end. step defaults to 1.
+//  Values(v1, v2, ..., vN)    - Yields values {v1, v2, ..., vN}.
+//  ValuesIn(container)        - Yields values from a C-style array, an STL
+//  ValuesIn(begin,end)          container, or an iterator range [begin, end).
+//  Bool()                     - Yields sequence {false, true}.
+//  Combine(g1, g2, ..., gN)   - Yields all combinations (the Cartesian product
+//                               for the math savvy) of the values generated
+//                               by the N generators.
+//
+// For more details, see comments at the definitions of these functions below
+// in this file.
+//
+// The following statement will instantiate tests from the FooTest test case
+// each with parameter values "meeny", "miny", and "moe".
+
+INSTANTIATE_TEST_CASE_P(InstantiationName,
+                        FooTest,
+                        Values("meeny", "miny", "moe"));
+
+// To distinguish different instances of the pattern, (yes, you
+// can instantiate it more then once) the first argument to the
+// INSTANTIATE_TEST_CASE_P macro is a prefix that will be added to the
+// actual test case name. Remember to pick unique prefixes for different
+// instantiations. The tests from the instantiation above will have
+// these names:
+//
+//    * InstantiationName/FooTest.DoesBlah/0 for "meeny"
+//    * InstantiationName/FooTest.DoesBlah/1 for "miny"
+//    * InstantiationName/FooTest.DoesBlah/2 for "moe"
+//    * InstantiationName/FooTest.HasBlahBlah/0 for "meeny"
+//    * InstantiationName/FooTest.HasBlahBlah/1 for "miny"
+//    * InstantiationName/FooTest.HasBlahBlah/2 for "moe"
+//
+// You can use these names in --gtest_filter.
+//
+// This statement will instantiate all tests from FooTest again, each
+// with parameter values "cat" and "dog":
+
+const char* pets[] = {"cat", "dog"};
+INSTANTIATE_TEST_CASE_P(AnotherInstantiationName, FooTest, ValuesIn(pets));
+
+// The tests from the instantiation above will have these names:
+//
+//    * AnotherInstantiationName/FooTest.DoesBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.DoesBlah/1 for "dog"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/0 for "cat"
+//    * AnotherInstantiationName/FooTest.HasBlahBlah/1 for "dog"
+//
+// Please note that INSTANTIATE_TEST_CASE_P will instantiate all tests
+// in the given test case, whether their definitions come before or
+// AFTER the INSTANTIATE_TEST_CASE_P statement.
+//
+// Please also note that generator expressions (including parameters to the
+// generators) are evaluated in InitGoogleTest(), after main() has started.
+// This allows the user on one hand, to adjust generator parameters in order
+// to dynamically determine a set of tests to run and on the other hand,
+// give the user a chance to inspect the generated tests with Google Test
+// reflection API before RUN_ALL_TESTS() is executed.
+//
+// You can see samples/sample7_unittest.cc and samples/sample8_unittest.cc
+// for more examples.
+//
+// In the future, we plan to publish the API for defining new parameter
+// generators. But for now this interface remains part of the internal
+// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+  // You can inherit all the usual members for a non-parameterized test
+  // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+  // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+  // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+  // GetParam works just the same here as if you inherit from TestWithParam.
+  EXPECT_TRUE(foo.Blah(GetParam()));
+}
+
+#endif  // 0
+
+
+#if !GTEST_OS_SYMBIAN
+# include <utility>
+#endif
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+// Copyright 2003 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Authors: Dan Egnor (egnor@google.com)
+//
+// A "smart" pointer type with reference tracking.  Every pointer to a
+// particular object is kept on a circular linked list.  When the last pointer
+// to an object is destroyed or reassigned, the object is deleted.
+//
+// Used properly, this deletes the object when the last reference goes away.
+// There are several caveats:
+// - Like all reference counting schemes, cycles lead to leaks.
+// - Each smart pointer is actually two pointers (8 bytes instead of 4).
+// - Every time a pointer is assigned, the entire list of pointers to that
+//   object is traversed.  This class is therefore NOT SUITABLE when there
+//   will often be more than two or three pointers to a particular object.
+// - References are only tracked as long as linked_ptr<> objects are copied.
+//   If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS
+//   will happen (double deletion).
+//
+// A good use of this class is storing object references in STL containers.
+// You can safely put linked_ptr<> in a vector<>.
+// Other uses may not be as good.
+//
+// Note: If you use an incomplete type with linked_ptr<>, the class
+// *containing* linked_ptr<> must have a constructor and destructor (even
+// if they do nothing!).
+//
+// Bill Gibbons suggested we use something like this.
+//
+// Thread Safety:
+//   Unlike other linked_ptr implementations, in this implementation
+//   a linked_ptr object is thread-safe in the sense that:
+//     - it's safe to copy linked_ptr objects concurrently,
+//     - it's safe to copy *from* a linked_ptr and read its underlying
+//       raw pointer (e.g. via get()) concurrently, and
+//     - it's safe to write to two linked_ptrs that point to the same
+//       shared object concurrently.
+// TODO(wan@google.com): rename this to safe_linked_ptr to avoid
+// confusion with normal linked_ptr.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+
+namespace testing {
+namespace internal {
+
+// Protects copying of all linked_ptr objects.
+GTEST_API_ GTEST_DECLARE_STATIC_MUTEX_(g_linked_ptr_mutex);
+
+// This is used internally by all instances of linked_ptr<>.  It needs to be
+// a non-template class because different types of linked_ptr<> can refer to
+// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)).
+// So, it needs to be possible for different types of linked_ptr to participate
+// in the same circular linked list, so we need a single class type here.
+//
+// DO NOT USE THIS CLASS DIRECTLY YOURSELF.  Use linked_ptr<T>.
+class linked_ptr_internal {
+ public:
+  // Create a new circle that includes only this instance.
+  void join_new() {
+    next_ = this;
+  }
+
+  // Many linked_ptr operations may change p.link_ for some linked_ptr
+  // variable p in the same circle as this object.  Therefore we need
+  // to prevent two such operations from occurring concurrently.
+  //
+  // Note that different types of linked_ptr objects can coexist in a
+  // circle (e.g. linked_ptr<Base>, linked_ptr<Derived1>, and
+  // linked_ptr<Derived2>).  Therefore we must use a single mutex to
+  // protect all linked_ptr objects.  This can create serious
+  // contention in production code, but is acceptable in a testing
+  // framework.
+
+  // Join an existing circle.
+  void join(linked_ptr_internal const* ptr)
+      GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    linked_ptr_internal const* p = ptr;
+    while (p->next_ != ptr) p = p->next_;
+    p->next_ = this;
+    next_ = ptr;
+  }
+
+  // Leave whatever circle we're part of.  Returns true if we were the
+  // last member of the circle.  Once this is done, you can join() another.
+  bool depart()
+      GTEST_LOCK_EXCLUDED_(g_linked_ptr_mutex) {
+    MutexLock lock(&g_linked_ptr_mutex);
+
+    if (next_ == this) return true;
+    linked_ptr_internal const* p = next_;
+    while (p->next_ != this) p = p->next_;
+    p->next_ = next_;
+    return false;
+  }
+
+ private:
+  mutable linked_ptr_internal const* next_;
+};
+
+template <typename T>
+class linked_ptr {
+ public:
+  typedef T element_type;
+
+  // Take over ownership of a raw pointer.  This should happen as soon as
+  // possible after the object is created.
+  explicit linked_ptr(T* ptr = NULL) { capture(ptr); }
+  ~linked_ptr() { depart(); }
+
+  // Copy an existing linked_ptr<>, adding ourselves to the list of references.
+  template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); }
+  linked_ptr(linked_ptr const& ptr) {  // NOLINT
+    assert(&ptr != this);
+    copy(&ptr);
+  }
+
+  // Assignment releases the old value and acquires the new.
+  template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) {
+    depart();
+    copy(&ptr);
+    return *this;
+  }
+
+  linked_ptr& operator=(linked_ptr const& ptr) {
+    if (&ptr != this) {
+      depart();
+      copy(&ptr);
+    }
+    return *this;
+  }
+
+  // Smart pointer members.
+  void reset(T* ptr = NULL) {
+    depart();
+    capture(ptr);
+  }
+  T* get() const { return value_; }
+  T* operator->() const { return value_; }
+  T& operator*() const { return *value_; }
+
+  bool operator==(T* p) const { return value_ == p; }
+  bool operator!=(T* p) const { return value_ != p; }
+  template <typename U>
+  bool operator==(linked_ptr<U> const& ptr) const {
+    return value_ == ptr.get();
+  }
+  template <typename U>
+  bool operator!=(linked_ptr<U> const& ptr) const {
+    return value_ != ptr.get();
+  }
+
+ private:
+  template <typename U>
+  friend class linked_ptr;
+
+  T* value_;
+  linked_ptr_internal link_;
+
+  void depart() {
+    if (link_.depart()) delete value_;
+  }
+
+  void capture(T* ptr) {
+    value_ = ptr;
+    link_.join_new();
+  }
+
+  template <typename U> void copy(linked_ptr<U> const* ptr) {
+    value_ = ptr->get();
+    if (value_)
+      link_.join(&ptr->link_);
+    else
+      link_.join_new();
+  }
+};
+
+template<typename T> inline
+bool operator==(T* ptr, const linked_ptr<T>& x) {
+  return ptr == x.get();
+}
+
+template<typename T> inline
+bool operator!=(T* ptr, const linked_ptr<T>& x) {
+  return ptr != x.get();
+}
+
+// A function to convert T* into linked_ptr<T>
+// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation
+// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
+template <typename T>
+linked_ptr<T> make_linked_ptr(T* ptr) {
+  return linked_ptr<T>(ptr);
+}
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_LINKED_PTR_H_
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+//   void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T.  More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+//   1. foo::PrintTo(const T&, ostream*)
+//   2. operator<<(ostream&, const T&) defined in either foo or the
+//      global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+//   // Prints a value to a string.  For a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   std::string ::testing::PrintToString(const T& value);
+//
+//   // Prints a value tersely: for a reference type, the referenced
+//   // value (but not the address) is printed; for a (const or not) char
+//   // pointer, the NUL-terminated string (but not the pointer) is
+//   // printed.
+//   void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+//   // Prints value using the type inferred by the compiler.  The difference
+//   // from UniversalTersePrint() is that this function prints both the
+//   // pointer and the NUL-terminated string for a (const or not) char pointer.
+//   void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+//   // Prints the fields of a tuple tersely to a string vector, one
+//   // element for each field. Tuple support must be enabled in
+//   // gtest-port.h.
+//   std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+//       const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container.  When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect.  In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator.  We'll fix this if there's an
+// actual need for it.  Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <ostream>  // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice.  DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+                                     size_t count,
+                                     ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+  kProtobuf,              // a protobuf type
+  kConvertibleToInteger,  // a type implicitly convertible to BiggestInt
+                          // (e.g. a named or unnamed enum type)
+  kOtherType              // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+  // This default version is called when kTypeKind is kOtherType.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+                         sizeof(value), os);
+  }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const ::testing::internal::string short_str = value.ShortDebugString();
+    const ::testing::internal::string pretty_str =
+        short_str.length() <= kProtobufOneLinerMaxLength ?
+        short_str : ("\n" + value.DebugString());
+    *os << ("<" + pretty_str + ">");
+  }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+  // Since T has no << operator or PrintTo() but can be implicitly
+  // converted to BiggestInt, we print it as a BiggestInt.
+  //
+  // Most likely T is an enum type (either named or unnamed), in which
+  // case printing it as an integer is the desired behavior.  In case
+  // T is not an enum, printing it as an integer is the best we can do
+  // given that it has no user-defined printer.
+  static void PrintValue(const T& value, ::std::ostream* os) {
+    const internal::BiggestInt kBigInt = value;
+    *os << kBigInt;
+  }
+};
+
+// Prints the given value to the given ostream.  If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed.  This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream.  If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+    ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+  TypeWithoutFormatter<T,
+      (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+       internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+       kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+  return os;
+}
+
+}  // namespace internal2
+}  // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+  // With the following statement, during unqualified name lookup,
+  // testing::internal2::operator<< appears as if it was declared in
+  // the nearest enclosing namespace that contains both
+  // ::testing_internal and ::testing::internal2, i.e. the global
+  // namespace.  For more details, refer to the C++ Standard section
+  // 7.3.4-1 [namespace.udir].  This allows us to fall back onto
+  // testing::internal2::operator<< in case T doesn't come with a <<
+  // operator.
+  //
+  // We cannot write 'using ::testing::internal2::operator<<;', which
+  // gcc 3.3 fails to compile due to a compiler bug.
+  using namespace ::testing::internal2;  // NOLINT
+
+  // Assuming T is defined in namespace foo, in the next statement,
+  // the compiler will consider all of:
+  //
+  //   1. foo::operator<< (thanks to Koenig look-up),
+  //   2. ::operator<< (as the current namespace is enclosed in ::),
+  //   3. testing::internal2::operator<< (thanks to the using statement above).
+  //
+  // The operator<< whose type matches T best will be picked.
+  //
+  // We deliberately allow #2 to be a candidate, as sometimes it's
+  // impossible to define #1 (e.g. when foo is ::std, defining
+  // anything in it is undefined behavior unless you are a compiler
+  // vendor.).
+  *os << value;
+}
+
+}  // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream.  The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const C& container, ::std::ostream* os) {
+  const size_t kMaxCount = 32;  // The maximum number of elements to print.
+  *os << '{';
+  size_t count = 0;
+  for (typename C::const_iterator it = container.begin();
+       it != container.end(); ++it, ++count) {
+    if (count > 0) {
+      *os << ',';
+      if (count == kMaxCount) {  // Enough has been printed.
+        *os << " ...";
+        break;
+      }
+    }
+    *os << ' ';
+    // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+    // handle *it being a native array.
+    internal::UniversalPrint(*it, os);
+  }
+
+  if (count > 0) {
+    *os << ' ';
+  }
+  *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it.  (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space.  Their representation is
+// implementation-defined.  Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    true_type /* is a pointer */,
+                    T* p, ::std::ostream* os) {
+  if (p == NULL) {
+    *os << "NULL";
+  } else {
+    // C++ doesn't allow casting from a function pointer to any object
+    // pointer.
+    //
+    // IsTrue() silences warnings: "Condition is always true",
+    // "unreachable code".
+    if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+      // T is not a function type.  We just call << to print p,
+      // relying on ADL to pick up user-defined << for their pointer
+      // types, if any.
+      *os << p;
+    } else {
+      // T is a function type, so '*os << p' doesn't do what we want
+      // (it just prints p as bool).  We want to print p as a const
+      // void*.  However, we cannot cast it to const void* directly,
+      // even using reinterpret_cast, as earlier versions of gcc
+      // (e.g. 3.4.5) cannot compile the cast when p is a function
+      // pointer.  Casting to UInt64 first solves the problem.
+      *os << reinterpret_cast<const void*>(
+          reinterpret_cast<internal::UInt64>(p));
+    }
+  }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+                    false_type /* is not a pointer */,
+                    const T& value, ::std::ostream* os) {
+  ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it.  This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined.  We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+  // DefaultPrintTo() is overloaded.  The type of its first two
+  // arguments determine which version will be picked.  If T is an
+  // STL-style container, the version for container will be called; if
+  // T is a pointer, the pointer version will be called; otherwise the
+  // generic version will be called.
+  //
+  // Note that we check for container types here, prior to we check
+  // for protocol message types in our operator<<.  The rationale is:
+  //
+  // For protocol messages, we want to give people a chance to
+  // override Google Mock's format by defining a PrintTo() or
+  // operator<<.  For STL containers, other formats can be
+  // incompatible with Google Mock's format for the container
+  // elements; therefore we check for container types here to ensure
+  // that our format is used.
+  //
+  // The second argument of DefaultPrintTo() is needed to bypass a bug
+  // in Symbian's C++ compiler that prevents it from picking the right
+  // overload between:
+  //
+  //   PrintTo(const T& x, ...);
+  //   PrintTo(T* x, ...);
+  DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+  // When printing a plain char, we always treat it as unsigned.  This
+  // way, the output won't be affected by whether the compiler thinks
+  // char is signed or not.
+  PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+  *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short.  It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type.  When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+  PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays.  Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+  UniversalPrint(a[0], os);
+  for (size_t i = 1; i != count; i++) {
+    *os << ", ";
+    UniversalPrint(a[i], os);
+  }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+  PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+  PrintWideStringTo(s, os);
+}
+#endif  // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple.  Needed for printing function arguments,
+// which are packed as tuples.
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+
+// Overloaded PrintTo() for tuples of various arities.  We support
+// tuples of up-to 10 fields.  The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+             ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+          typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+    const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+    ::std::ostream* os) {
+  PrintTupleTo(t, os);
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+  *os << '(';
+  // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+  // a reference type.  The same for printing value.second.
+  UniversalPrinter<T1>::Print(value.first, os);
+  *os << ", ";
+  UniversalPrinter<T2>::Print(value.second, os);
+  *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  // Note: we deliberately don't call this PrintTo(), as that name
+  // conflicts with ::testing::internal::PrintTo in the body of the
+  // function.
+  static void Print(const T& value, ::std::ostream* os) {
+    // By default, ::testing::internal::PrintTo() is used for printing
+    // the value.
+    //
+    // Thanks to Koenig look-up, if T is a class and has its own
+    // PrintTo() function defined in its namespace, that function will
+    // be visible here.  Since it is more specific than the generic ones
+    // in ::testing::internal, it will be picked by the compiler in the
+    // following statement - exactly what we want.
+    PrintTo(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+  if (len == 0) {
+    *os << "{}";
+  } else {
+    *os << "{ ";
+    const size_t kThreshold = 18;
+    const size_t kChunkSize = 8;
+    // If the array has more than kThreshold elements, we'll have to
+    // omit some details by printing only the first and the last
+    // kChunkSize elements.
+    // TODO(wan@google.com): let the user control the threshold using a flag.
+    if (len <= kThreshold) {
+      PrintRawArrayTo(begin, len, os);
+    } else {
+      PrintRawArrayTo(begin, kChunkSize, os);
+      *os << ", ..., ";
+      PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+    }
+    *os << " }";
+  }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(
+    const char* begin, size_t len, ::std::ostream* os);
+
+// This overload prints a (const) wchar_t array compactly.
+GTEST_API_ void UniversalPrintArray(
+    const wchar_t* begin, size_t len, ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+  // Prints the given array, omitting some elements when there are too
+  // many.
+  static void Print(const T (&a)[N], ::std::ostream* os) {
+    UniversalPrintArray(a, N, os);
+  }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+  // MSVC warns about adding const to a function type, so we want to
+  // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4180)  // Temporarily disables warning 4180.
+#endif  // _MSC_VER
+
+  static void Print(const T& value, ::std::ostream* os) {
+    // Prints the address of the value.  We use reinterpret_cast here
+    // as static_cast doesn't compile when T is a function type.
+    *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+    // Then prints the value itself.
+    UniversalPrint(value, os);
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)           // Restores the warning state.
+#endif  // _MSC_VER
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+
+template <typename T>
+class UniversalTersePrinter {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T>
+class UniversalTersePrinter<T&> {
+ public:
+  static void Print(const T& value, ::std::ostream* os) {
+    UniversalPrint(value, os);
+  }
+};
+template <typename T, size_t N>
+class UniversalTersePrinter<T[N]> {
+ public:
+  static void Print(const T (&value)[N], ::std::ostream* os) {
+    UniversalPrinter<T[N]>::Print(value, os);
+  }
+};
+template <>
+class UniversalTersePrinter<const char*> {
+ public:
+  static void Print(const char* str, ::std::ostream* os) {
+    if (str == NULL) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(string(str), os);
+    }
+  }
+};
+template <>
+class UniversalTersePrinter<char*> {
+ public:
+  static void Print(char* str, ::std::ostream* os) {
+    UniversalTersePrinter<const char*>::Print(str, os);
+  }
+};
+
+#if GTEST_HAS_STD_WSTRING
+template <>
+class UniversalTersePrinter<const wchar_t*> {
+ public:
+  static void Print(const wchar_t* str, ::std::ostream* os) {
+    if (str == NULL) {
+      *os << "NULL";
+    } else {
+      UniversalPrint(::std::wstring(str), os);
+    }
+  }
+};
+#endif
+
+template <>
+class UniversalTersePrinter<wchar_t*> {
+ public:
+  static void Print(wchar_t* str, ::std::ostream* os) {
+    UniversalTersePrinter<const wchar_t*>::Print(str, os);
+  }
+};
+
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+  UniversalTersePrinter<T>::Print(value, os);
+}
+
+// Prints a value using the type inferred by the compiler.  The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+  // A workarond for the bug in VC++ 7.1 that prevents us from instantiating
+  // UniversalPrinter with T directly.
+  typedef T T1;
+  UniversalPrinter<T1>::Print(value, os);
+}
+
+#if GTEST_HAS_TR1_TUPLE
+typedef ::std::vector<string> Strings;
+
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields.  The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+  // Prints the first N fields of a tuple.
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+    *os << ", ";
+    UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
+        ::Print(::std::tr1::get<N - 1>(t), os);
+  }
+
+  // Tersely prints the first N fields of a tuple to a string vector,
+  // one element for each field.
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Base cases.
+template <>
+struct TuplePrefixPrinter<0> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+// We have to specialize the entire TuplePrefixPrinter<> class
+// template here, even though the definition of
+// TersePrintPrefixToStrings() is the same as the generic version, as
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
+template <>
+struct TuplePrefixPrinter<1> {
+  template <typename Tuple>
+  static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+    UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
+        Print(::std::tr1::get<0>(t), os);
+  }
+
+  template <typename Tuple>
+  static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+    ::std::stringstream ss;
+    UniversalTersePrint(::std::tr1::get<0>(t), &ss);
+    strings->push_back(ss.str());
+  }
+};
+
+// Helper function for printing a tuple.  T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os) {
+  *os << "(";
+  TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
+      PrintPrefixTo(t, os);
+  *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field.  See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+  Strings result;
+  TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
+      TersePrintPrefixToStrings(value, &result);
+  return result;
+}
+#endif  // GTEST_HAS_TR1_TUPLE
+
+}  // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+  ::std::stringstream ss;
+  internal::UniversalTersePrinter<T>::Print(value, &ss);
+  return ss.str();
+}
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+namespace internal {
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Outputs a message explaining invalid registration of different
+// fixture class for the same test case. This may happen when
+// TEST_P macro is used to define two tests with the same name
+// but in different namespaces.
+GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
+                                          const char* file, int line);
+
+template <typename> class ParamGeneratorInterface;
+template <typename> class ParamGenerator;
+
+// Interface for iterating over elements provided by an implementation
+// of ParamGeneratorInterface<T>.
+template <typename T>
+class ParamIteratorInterface {
+ public:
+  virtual ~ParamIteratorInterface() {}
+  // A pointer to the base generator instance.
+  // Used only for the purposes of iterator comparison
+  // to make sure that two iterators belong to the same generator.
+  virtual const ParamGeneratorInterface<T>* BaseGenerator() const = 0;
+  // Advances iterator to point to the next element
+  // provided by the generator. The caller is responsible
+  // for not calling Advance() on an iterator equal to
+  // BaseGenerator()->End().
+  virtual void Advance() = 0;
+  // Clones the iterator object. Used for implementing copy semantics
+  // of ParamIterator<T>.
+  virtual ParamIteratorInterface* Clone() const = 0;
+  // Dereferences the current iterator and provides (read-only) access
+  // to the pointed value. It is the caller's responsibility not to call
+  // Current() on an iterator equal to BaseGenerator()->End().
+  // Used for implementing ParamGenerator<T>::operator*().
+  virtual const T* Current() const = 0;
+  // Determines whether the given iterator and other point to the same
+  // element in the sequence generated by the generator.
+  // Used for implementing ParamGenerator<T>::operator==().
+  virtual bool Equals(const ParamIteratorInterface& other) const = 0;
+};
+
+// Class iterating over elements provided by an implementation of
+// ParamGeneratorInterface<T>. It wraps ParamIteratorInterface<T>
+// and implements the const forward iterator concept.
+template <typename T>
+class ParamIterator {
+ public:
+  typedef T value_type;
+  typedef const T& reference;
+  typedef ptrdiff_t difference_type;
+
+  // ParamIterator assumes ownership of the impl_ pointer.
+  ParamIterator(const ParamIterator& other) : impl_(other.impl_->Clone()) {}
+  ParamIterator& operator=(const ParamIterator& other) {
+    if (this != &other)
+      impl_.reset(other.impl_->Clone());
+    return *this;
+  }
+
+  const T& operator*() const { return *impl_->Current(); }
+  const T* operator->() const { return impl_->Current(); }
+  // Prefix version of operator++.
+  ParamIterator& operator++() {
+    impl_->Advance();
+    return *this;
+  }
+  // Postfix version of operator++.
+  ParamIterator operator++(int /*unused*/) {
+    ParamIteratorInterface<T>* clone = impl_->Clone();
+    impl_->Advance();
+    return ParamIterator(clone);
+  }
+  bool operator==(const ParamIterator& other) const {
+    return impl_.get() == other.impl_.get() || impl_->Equals(*other.impl_);
+  }
+  bool operator!=(const ParamIterator& other) const {
+    return !(*this == other);
+  }
+
+ private:
+  friend class ParamGenerator<T>;
+  explicit ParamIterator(ParamIteratorInterface<T>* impl) : impl_(impl) {}
+  scoped_ptr<ParamIteratorInterface<T> > impl_;
+};
+
+// ParamGeneratorInterface<T> is the binary interface to access generators
+// defined in other translation units.
+template <typename T>
+class ParamGeneratorInterface {
+ public:
+  typedef T ParamType;
+
+  virtual ~ParamGeneratorInterface() {}
+
+  // Generator interface definition
+  virtual ParamIteratorInterface<T>* Begin() const = 0;
+  virtual ParamIteratorInterface<T>* End() const = 0;
+};
+
+// Wraps ParamGeneratorInterface<T> and provides general generator syntax
+// compatible with the STL Container concept.
+// This class implements copy initialization semantics and the contained
+// ParamGeneratorInterface<T> instance is shared among all copies
+// of the original object. This is possible because that instance is immutable.
+template<typename T>
+class ParamGenerator {
+ public:
+  typedef ParamIterator<T> iterator;
+
+  explicit ParamGenerator(ParamGeneratorInterface<T>* impl) : impl_(impl) {}
+  ParamGenerator(const ParamGenerator& other) : impl_(other.impl_) {}
+
+  ParamGenerator& operator=(const ParamGenerator& other) {
+    impl_ = other.impl_;
+    return *this;
+  }
+
+  iterator begin() const { return iterator(impl_->Begin()); }
+  iterator end() const { return iterator(impl_->End()); }
+
+ private:
+  linked_ptr<const ParamGeneratorInterface<T> > impl_;
+};
+
+// Generates values from a range of two comparable values. Can be used to
+// generate sequences of user-defined types that implement operator+() and
+// operator<().
+// This class is used in the Range() function.
+template <typename T, typename IncrementT>
+class RangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  RangeGenerator(T begin, T end, IncrementT step)
+      : begin_(begin), end_(end),
+        step_(step), end_index_(CalculateEndIndex(begin, end, step)) {}
+  virtual ~RangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, begin_, 0, step_);
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, end_, end_index_, step_);
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base, T value, int index,
+             IncrementT step)
+        : base_(base), value_(value), index_(index), step_(step) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      value_ = value_ + step_;
+      index_++;
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const T* Current() const { return &value_; }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const int other_index =
+          CheckedDowncastToActualType<const Iterator>(&other)->index_;
+      return index_ == other_index;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : ParamIteratorInterface<T>(),
+          base_(other.base_), value_(other.value_), index_(other.index_),
+          step_(other.step_) {}
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<T>* const base_;
+    T value_;
+    int index_;
+    const IncrementT step_;
+  };  // class RangeGenerator::Iterator
+
+  static int CalculateEndIndex(const T& begin,
+                               const T& end,
+                               const IncrementT& step) {
+    int end_index = 0;
+    for (T i = begin; i < end; i = i + step)
+      end_index++;
+    return end_index;
+  }
+
+  // No implementation - assignment is unsupported.
+  void operator=(const RangeGenerator& other);
+
+  const T begin_;
+  const T end_;
+  const IncrementT step_;
+  // The index for the end() iterator. All the elements in the generated
+  // sequence are indexed (0-based) to aid iterator comparison.
+  const int end_index_;
+};  // class RangeGenerator
+
+
+// Generates values from a pair of STL-style iterators. Used in the
+// ValuesIn() function. The elements are copied from the source range
+// since the source can be located on the stack, and the generator
+// is likely to persist beyond that stack frame.
+template <typename T>
+class ValuesInIteratorRangeGenerator : public ParamGeneratorInterface<T> {
+ public:
+  template <typename ForwardIterator>
+  ValuesInIteratorRangeGenerator(ForwardIterator begin, ForwardIterator end)
+      : container_(begin, end) {}
+  virtual ~ValuesInIteratorRangeGenerator() {}
+
+  virtual ParamIteratorInterface<T>* Begin() const {
+    return new Iterator(this, container_.begin());
+  }
+  virtual ParamIteratorInterface<T>* End() const {
+    return new Iterator(this, container_.end());
+  }
+
+ private:
+  typedef typename ::std::vector<T> ContainerType;
+
+  class Iterator : public ParamIteratorInterface<T> {
+   public:
+    Iterator(const ParamGeneratorInterface<T>* base,
+             typename ContainerType::const_iterator iterator)
+        : base_(base), iterator_(iterator) {}
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
+      return base_;
+    }
+    virtual void Advance() {
+      ++iterator_;
+      value_.reset();
+    }
+    virtual ParamIteratorInterface<T>* Clone() const {
+      return new Iterator(*this);
+    }
+    // We need to use cached value referenced by iterator_ because *iterator_
+    // can return a temporary object (and of type other then T), so just
+    // having "return &*iterator_;" doesn't work.
+    // value_ is updated here and not in Advance() because Advance()
+    // can advance iterator_ beyond the end of the range, and we cannot
+    // detect that fact. The client code, on the other hand, is
+    // responsible for not calling Current() on an out-of-range iterator.
+    virtual const T* Current() const {
+      if (value_.get() == NULL)
+        value_.reset(new T(*iterator_));
+      return value_.get();
+    }
+    virtual bool Equals(const ParamIteratorInterface<T>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      return iterator_ ==
+          CheckedDowncastToActualType<const Iterator>(&other)->iterator_;
+    }
+
+   private:
+    Iterator(const Iterator& other)
+          // The explicit constructor call suppresses a false warning
+          // emitted by gcc when supplied with the -Wextra option.
+        : ParamIteratorInterface<T>(),
+          base_(other.base_),
+          iterator_(other.iterator_) {}
+
+    const ParamGeneratorInterface<T>* const base_;
+    typename ContainerType::const_iterator iterator_;
+    // A cached value of *iterator_. We keep it here to allow access by
+    // pointer in the wrapping iterator's operator->().
+    // value_ needs to be mutable to be accessed in Current().
+    // Use of scoped_ptr helps manage cached value's lifetime,
+    // which is bound by the lifespan of the iterator itself.
+    mutable scoped_ptr<const T> value_;
+  };  // class ValuesInIteratorRangeGenerator::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const ValuesInIteratorRangeGenerator& other);
+
+  const ContainerType container_;
+};  // class ValuesInIteratorRangeGenerator
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Stores a parameter value and later creates tests parameterized with that
+// value.
+template <class TestClass>
+class ParameterizedTestFactory : public TestFactoryBase {
+ public:
+  typedef typename TestClass::ParamType ParamType;
+  explicit ParameterizedTestFactory(ParamType parameter) :
+      parameter_(parameter) {}
+  virtual Test* CreateTest() {
+    TestClass::SetParam(&parameter_);
+    return new TestClass();
+  }
+
+ private:
+  const ParamType parameter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactoryBase is a base class for meta-factories that create
+// test factories for passing into MakeAndRegisterTestInfo function.
+template <class ParamType>
+class TestMetaFactoryBase {
+ public:
+  virtual ~TestMetaFactoryBase() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) = 0;
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// TestMetaFactory creates test factories for passing into
+// MakeAndRegisterTestInfo function. Since MakeAndRegisterTestInfo receives
+// ownership of test factory pointer, same factory object cannot be passed
+// into that method twice. But ParameterizedTestCaseInfo is going to call
+// it for each Test/Parameter value combination. Thus it needs meta factory
+// creator class.
+template <class TestCase>
+class TestMetaFactory
+    : public TestMetaFactoryBase<typename TestCase::ParamType> {
+ public:
+  typedef typename TestCase::ParamType ParamType;
+
+  TestMetaFactory() {}
+
+  virtual TestFactoryBase* CreateTestFactory(ParamType parameter) {
+    return new ParameterizedTestFactory<TestCase>(parameter);
+  }
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestMetaFactory);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfoBase is a generic interface
+// to ParameterizedTestCaseInfo classes. ParameterizedTestCaseInfoBase
+// accumulates test information provided by TEST_P macro invocations
+// and generators provided by INSTANTIATE_TEST_CASE_P macro invocations
+// and uses that information to register all resulting test instances
+// in RegisterTests method. The ParameterizeTestCaseRegistry class holds
+// a collection of pointers to the ParameterizedTestCaseInfo objects
+// and calls RegisterTests() on each of them when asked.
+class ParameterizedTestCaseInfoBase {
+ public:
+  virtual ~ParameterizedTestCaseInfoBase() {}
+
+  // Base part of test case name for display purposes.
+  virtual const string& GetTestCaseName() const = 0;
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const = 0;
+  // UnitTest class invokes this method to register tests in this
+  // test case right before running them in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  virtual void RegisterTests() = 0;
+
+ protected:
+  ParameterizedTestCaseInfoBase() {}
+
+ private:
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfoBase);
+};
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseInfo accumulates tests obtained from TEST_P
+// macro invocations for a particular test case and generators
+// obtained from INSTANTIATE_TEST_CASE_P macro invocations for that
+// test case. It registers tests with all values generated by all
+// generators when asked.
+template <class TestCase>
+class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
+ public:
+  // ParamType and GeneratorCreationFunc are private types but are required
+  // for declarations of public methods AddTestPattern() and
+  // AddTestCaseInstantiation().
+  typedef typename TestCase::ParamType ParamType;
+  // A function that returns an instance of appropriate generator type.
+  typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
+
+  explicit ParameterizedTestCaseInfo(const char* name)
+      : test_case_name_(name) {}
+
+  // Test case base name for display purposes.
+  virtual const string& GetTestCaseName() const { return test_case_name_; }
+  // Test case id to verify identity.
+  virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
+  // TEST_P macro uses AddTestPattern() to record information
+  // about a single test in a LocalTestInfo structure.
+  // test_case_name is the base name of the test case (without invocation
+  // prefix). test_base_name is the name of an individual test without
+  // parameter index. For the test SequenceA/FooTest.DoBar/1 FooTest is
+  // test case base name and DoBar is test base name.
+  void AddTestPattern(const char* test_case_name,
+                      const char* test_base_name,
+                      TestMetaFactoryBase<ParamType>* meta_factory) {
+    tests_.push_back(linked_ptr<TestInfo>(new TestInfo(test_case_name,
+                                                       test_base_name,
+                                                       meta_factory)));
+  }
+  // INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
+  // about a generator.
+  int AddTestCaseInstantiation(const string& instantiation_name,
+                               GeneratorCreationFunc* func,
+                               const char* /* file */,
+                               int /* line */) {
+    instantiations_.push_back(::std::make_pair(instantiation_name, func));
+    return 0;  // Return value used only to run this method in namespace scope.
+  }
+  // UnitTest class invokes this method to register tests in this test case
+  // test cases right before running tests in RUN_ALL_TESTS macro.
+  // This method should not be called more then once on any single
+  // instance of a ParameterizedTestCaseInfoBase derived class.
+  // UnitTest has a guard to prevent from calling this method more then once.
+  virtual void RegisterTests() {
+    for (typename TestInfoContainer::iterator test_it = tests_.begin();
+         test_it != tests_.end(); ++test_it) {
+      linked_ptr<TestInfo> test_info = *test_it;
+      for (typename InstantiationContainer::iterator gen_it =
+               instantiations_.begin(); gen_it != instantiations_.end();
+               ++gen_it) {
+        const string& instantiation_name = gen_it->first;
+        ParamGenerator<ParamType> generator((*gen_it->second)());
+
+        string test_case_name;
+        if ( !instantiation_name.empty() )
+          test_case_name = instantiation_name + "/";
+        test_case_name += test_info->test_case_base_name;
+
+        int i = 0;
+        for (typename ParamGenerator<ParamType>::iterator param_it =
+                 generator.begin();
+             param_it != generator.end(); ++param_it, ++i) {
+          Message test_name_stream;
+          test_name_stream << test_info->test_base_name << "/" << i;
+          MakeAndRegisterTestInfo(
+              test_case_name.c_str(),
+              test_name_stream.GetString().c_str(),
+              NULL,  // No type parameter.
+              PrintToString(*param_it).c_str(),
+              GetTestCaseTypeId(),
+              TestCase::SetUpTestCase,
+              TestCase::TearDownTestCase,
+              test_info->test_meta_factory->CreateTestFactory(*param_it));
+        }  // for param_it
+      }  // for gen_it
+    }  // for test_it
+  }  // RegisterTests
+
+ private:
+  // LocalTestInfo structure keeps information about a single test registered
+  // with TEST_P macro.
+  struct TestInfo {
+    TestInfo(const char* a_test_case_base_name,
+             const char* a_test_base_name,
+             TestMetaFactoryBase<ParamType>* a_test_meta_factory) :
+        test_case_base_name(a_test_case_base_name),
+        test_base_name(a_test_base_name),
+        test_meta_factory(a_test_meta_factory) {}
+
+    const string test_case_base_name;
+    const string test_base_name;
+    const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
+  };
+  typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
+  // Keeps pairs of <Instantiation name, Sequence generator creation function>
+  // received from INSTANTIATE_TEST_CASE_P macros.
+  typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
+      InstantiationContainer;
+
+  const string test_case_name_;
+  TestInfoContainer tests_;
+  InstantiationContainer instantiations_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseInfo);
+};  // class ParameterizedTestCaseInfo
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// ParameterizedTestCaseRegistry contains a map of ParameterizedTestCaseInfoBase
+// classes accessed by test case names. TEST_P and INSTANTIATE_TEST_CASE_P
+// macros use it to locate their corresponding ParameterizedTestCaseInfo
+// descriptors.
+class ParameterizedTestCaseRegistry {
+ public:
+  ParameterizedTestCaseRegistry() {}
+  ~ParameterizedTestCaseRegistry() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      delete *it;
+    }
+  }
+
+  // Looks up or creates and returns a structure containing information about
+  // tests and instantiations of a particular test case.
+  template <class TestCase>
+  ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
+      const char* test_case_name,
+      const char* file,
+      int line) {
+    ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      if ((*it)->GetTestCaseName() == test_case_name) {
+        if ((*it)->GetTestCaseTypeId() != GetTypeId<TestCase>()) {
+          // Complain about incorrect usage of Google Test facilities
+          // and terminate the program since we cannot guaranty correct
+          // test case setup and tear-down in this case.
+          ReportInvalidTestCaseType(test_case_name,  file, line);
+          posix::Abort();
+        } else {
+          // At this point we are sure that the object we found is of the same
+          // type we are looking for, so we downcast it to that type
+          // without further checks.
+          typed_test_info = CheckedDowncastToActualType<
+              ParameterizedTestCaseInfo<TestCase> >(*it);
+        }
+        break;
+      }
+    }
+    if (typed_test_info == NULL) {
+      typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name);
+      test_case_infos_.push_back(typed_test_info);
+    }
+    return typed_test_info;
+  }
+  void RegisterTests() {
+    for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
+         it != test_case_infos_.end(); ++it) {
+      (*it)->RegisterTests();
+    }
+  }
+
+ private:
+  typedef ::std::vector<ParameterizedTestCaseInfoBase*> TestCaseInfoContainer;
+
+  TestCaseInfoContainer test_case_infos_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(ParameterizedTestCaseRegistry);
+};
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_H_
+// This file was GENERATED by command:
+//     pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
+
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: vladl@google.com (Vlad Losev)
+
+// Type and function utilities for implementing parameterized tests.
+// This file is generated by a SCRIPT.  DO NOT EDIT BY HAND!
+//
+// Currently Google Test supports at most 50 arguments in Values,
+// and at most 10 arguments in Combine. Please contact
+// googletestframework@googlegroups.com if you need more.
+// Please note that the number of arguments to Combine is limited
+// by the maximum arity of the implementation of tr1::tuple which is
+// currently set at 10.
+
+#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+// scripts/fuse_gtest.py depends on gtest's own header being #included
+// *unconditionally*.  Therefore these #includes cannot be moved
+// inside #if GTEST_HAS_PARAM_TEST.
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Forward declarations of ValuesIn(), which is implemented in
+// include/gtest/gtest-param-test.h.
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container);
+
+namespace internal {
+
+// Used in the Values() function to provide polymorphic capabilities.
+template <typename T1>
+class ValueArray1 {
+ public:
+  explicit ValueArray1(T1 v1) : v1_(v1) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray1& other);
+
+  const T1 v1_;
+};
+
+template <typename T1, typename T2>
+class ValueArray2 {
+ public:
+  ValueArray2(T1 v1, T2 v2) : v1_(v1), v2_(v2) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray2& other);
+
+  const T1 v1_;
+  const T2 v2_;
+};
+
+template <typename T1, typename T2, typename T3>
+class ValueArray3 {
+ public:
+  ValueArray3(T1 v1, T2 v2, T3 v3) : v1_(v1), v2_(v2), v3_(v3) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray3& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4>
+class ValueArray4 {
+ public:
+  ValueArray4(T1 v1, T2 v2, T3 v3, T4 v4) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray4& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class ValueArray5 {
+ public:
+  ValueArray5(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray5& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class ValueArray6 {
+ public:
+  ValueArray6(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray6& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class ValueArray7 {
+ public:
+  ValueArray7(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray7& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class ValueArray8 {
+ public:
+  ValueArray8(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+      T8 v8) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray8& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class ValueArray9 {
+ public:
+  ValueArray9(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+      T9 v9) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray9& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class ValueArray10 {
+ public:
+  ValueArray10(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray10& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+class ValueArray11 {
+ public:
+  ValueArray11(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray11& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+class ValueArray12 {
+ public:
+  ValueArray12(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray12& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+class ValueArray13 {
+ public:
+  ValueArray13(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray13& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+class ValueArray14 {
+ public:
+  ValueArray14(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray14& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+class ValueArray15 {
+ public:
+  ValueArray15(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray15& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+class ValueArray16 {
+ public:
+  ValueArray16(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray16& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+class ValueArray17 {
+ public:
+  ValueArray17(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+      T17 v17) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray17& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+class ValueArray18 {
+ public:
+  ValueArray18(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray18& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+class ValueArray19 {
+ public:
+  ValueArray19(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray19& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+class ValueArray20 {
+ public:
+  ValueArray20(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray20& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+class ValueArray21 {
+ public:
+  ValueArray21(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray21& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+class ValueArray22 {
+ public:
+  ValueArray22(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray22& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+class ValueArray23 {
+ public:
+  ValueArray23(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray23& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+class ValueArray24 {
+ public:
+  ValueArray24(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray24& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+class ValueArray25 {
+ public:
+  ValueArray25(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+      T25 v25) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray25& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+class ValueArray26 {
+ public:
+  ValueArray26(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray26& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+class ValueArray27 {
+ public:
+  ValueArray27(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray27& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+class ValueArray28 {
+ public:
+  ValueArray28(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray28& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+class ValueArray29 {
+ public:
+  ValueArray29(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray29& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+class ValueArray30 {
+ public:
+  ValueArray30(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray30& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+class ValueArray31 {
+ public:
+  ValueArray31(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray31& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+class ValueArray32 {
+ public:
+  ValueArray32(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray32& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+class ValueArray33 {
+ public:
+  ValueArray33(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+      T33 v33) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray33& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+class ValueArray34 {
+ public:
+  ValueArray34(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray34& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+class ValueArray35 {
+ public:
+  ValueArray35(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray35& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+class ValueArray36 {
+ public:
+  ValueArray36(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray36& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+class ValueArray37 {
+ public:
+  ValueArray37(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray37& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+class ValueArray38 {
+ public:
+  ValueArray38(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray38& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+class ValueArray39 {
+ public:
+  ValueArray39(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray39& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+class ValueArray40 {
+ public:
+  ValueArray40(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray40& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+class ValueArray41 {
+ public:
+  ValueArray41(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+      T41 v41) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray41& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+class ValueArray42 {
+ public:
+  ValueArray42(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray42& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+class ValueArray43 {
+ public:
+  ValueArray43(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6),
+      v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13),
+      v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19),
+      v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25),
+      v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31),
+      v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37),
+      v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray43& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+class ValueArray44 {
+ public:
+  ValueArray44(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5),
+      v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12),
+      v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17), v18_(v18),
+      v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23), v24_(v24),
+      v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29), v30_(v30),
+      v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35), v36_(v36),
+      v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41), v42_(v42),
+      v43_(v43), v44_(v44) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray44& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+class ValueArray45 {
+ public:
+  ValueArray45(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45) : v1_(v1), v2_(v2), v3_(v3), v4_(v4),
+      v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10), v11_(v11),
+      v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16), v17_(v17),
+      v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22), v23_(v23),
+      v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28), v29_(v29),
+      v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34), v35_(v35),
+      v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40), v41_(v41),
+      v42_(v42), v43_(v43), v44_(v44), v45_(v45) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray45& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+class ValueArray46 {
+ public:
+  ValueArray46(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) : v1_(v1), v2_(v2), v3_(v3),
+      v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray46& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+class ValueArray47 {
+ public:
+  ValueArray47(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) : v1_(v1), v2_(v2),
+      v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9), v10_(v10),
+      v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15), v16_(v16),
+      v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21), v22_(v22),
+      v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27), v28_(v28),
+      v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33), v34_(v34),
+      v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39), v40_(v40),
+      v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45), v46_(v46),
+      v47_(v47) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray47& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+class ValueArray48 {
+ public:
+  ValueArray48(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48) : v1_(v1),
+      v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7), v8_(v8), v9_(v9),
+      v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14), v15_(v15),
+      v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20), v21_(v21),
+      v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26), v27_(v27),
+      v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32), v33_(v33),
+      v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38), v39_(v39),
+      v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44), v45_(v45),
+      v46_(v46), v47_(v47), v48_(v48) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray48& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+class ValueArray49 {
+ public:
+  ValueArray49(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48,
+      T49 v49) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_), static_cast<T>(v49_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray49& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+};
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+class ValueArray50 {
+ public:
+  ValueArray50(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+      T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+      T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+      T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+      T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+      T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47, T48 v48, T49 v49,
+      T50 v50) : v1_(v1), v2_(v2), v3_(v3), v4_(v4), v5_(v5), v6_(v6), v7_(v7),
+      v8_(v8), v9_(v9), v10_(v10), v11_(v11), v12_(v12), v13_(v13), v14_(v14),
+      v15_(v15), v16_(v16), v17_(v17), v18_(v18), v19_(v19), v20_(v20),
+      v21_(v21), v22_(v22), v23_(v23), v24_(v24), v25_(v25), v26_(v26),
+      v27_(v27), v28_(v28), v29_(v29), v30_(v30), v31_(v31), v32_(v32),
+      v33_(v33), v34_(v34), v35_(v35), v36_(v36), v37_(v37), v38_(v38),
+      v39_(v39), v40_(v40), v41_(v41), v42_(v42), v43_(v43), v44_(v44),
+      v45_(v45), v46_(v46), v47_(v47), v48_(v48), v49_(v49), v50_(v50) {}
+
+  template <typename T>
+  operator ParamGenerator<T>() const {
+    const T array[] = {static_cast<T>(v1_), static_cast<T>(v2_),
+        static_cast<T>(v3_), static_cast<T>(v4_), static_cast<T>(v5_),
+        static_cast<T>(v6_), static_cast<T>(v7_), static_cast<T>(v8_),
+        static_cast<T>(v9_), static_cast<T>(v10_), static_cast<T>(v11_),
+        static_cast<T>(v12_), static_cast<T>(v13_), static_cast<T>(v14_),
+        static_cast<T>(v15_), static_cast<T>(v16_), static_cast<T>(v17_),
+        static_cast<T>(v18_), static_cast<T>(v19_), static_cast<T>(v20_),
+        static_cast<T>(v21_), static_cast<T>(v22_), static_cast<T>(v23_),
+        static_cast<T>(v24_), static_cast<T>(v25_), static_cast<T>(v26_),
+        static_cast<T>(v27_), static_cast<T>(v28_), static_cast<T>(v29_),
+        static_cast<T>(v30_), static_cast<T>(v31_), static_cast<T>(v32_),
+        static_cast<T>(v33_), static_cast<T>(v34_), static_cast<T>(v35_),
+        static_cast<T>(v36_), static_cast<T>(v37_), static_cast<T>(v38_),
+        static_cast<T>(v39_), static_cast<T>(v40_), static_cast<T>(v41_),
+        static_cast<T>(v42_), static_cast<T>(v43_), static_cast<T>(v44_),
+        static_cast<T>(v45_), static_cast<T>(v46_), static_cast<T>(v47_),
+        static_cast<T>(v48_), static_cast<T>(v49_), static_cast<T>(v50_)};
+    return ValuesIn(array);
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const ValueArray50& other);
+
+  const T1 v1_;
+  const T2 v2_;
+  const T3 v3_;
+  const T4 v4_;
+  const T5 v5_;
+  const T6 v6_;
+  const T7 v7_;
+  const T8 v8_;
+  const T9 v9_;
+  const T10 v10_;
+  const T11 v11_;
+  const T12 v12_;
+  const T13 v13_;
+  const T14 v14_;
+  const T15 v15_;
+  const T16 v16_;
+  const T17 v17_;
+  const T18 v18_;
+  const T19 v19_;
+  const T20 v20_;
+  const T21 v21_;
+  const T22 v22_;
+  const T23 v23_;
+  const T24 v24_;
+  const T25 v25_;
+  const T26 v26_;
+  const T27 v27_;
+  const T28 v28_;
+  const T29 v29_;
+  const T30 v30_;
+  const T31 v31_;
+  const T32 v32_;
+  const T33 v33_;
+  const T34 v34_;
+  const T35 v35_;
+  const T36 v36_;
+  const T37 v37_;
+  const T38 v38_;
+  const T39 v39_;
+  const T40 v40_;
+  const T41 v41_;
+  const T42 v42_;
+  const T43 v43_;
+  const T44 v44_;
+  const T45 v45_;
+  const T46 v46_;
+  const T47 v47_;
+  const T48 v48_;
+  const T49 v49_;
+  const T50 v50_;
+};
+
+# if GTEST_HAS_COMBINE
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Generates values from the Cartesian product of values produced
+// by the argument generators.
+//
+template <typename T1, typename T2>
+class CartesianProductGenerator2
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2> ParamType;
+
+  CartesianProductGenerator2(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2)
+      : g1_(g1), g2_(g2) {}
+  virtual ~CartesianProductGenerator2() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current2_;
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator2::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator2& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+};  // class CartesianProductGenerator2
+
+
+template <typename T1, typename T2, typename T3>
+class CartesianProductGenerator3
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3> ParamType;
+
+  CartesianProductGenerator3(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  virtual ~CartesianProductGenerator3() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current3_;
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator3::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator3& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+};  // class CartesianProductGenerator3
+
+
+template <typename T1, typename T2, typename T3, typename T4>
+class CartesianProductGenerator4
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType;
+
+  CartesianProductGenerator4(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  virtual ~CartesianProductGenerator4() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current4_;
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator4::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator4& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+};  // class CartesianProductGenerator4
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+class CartesianProductGenerator5
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType;
+
+  CartesianProductGenerator5(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  virtual ~CartesianProductGenerator5() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current5_;
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator5::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator5& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+};  // class CartesianProductGenerator5
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+class CartesianProductGenerator6
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5,
+        T6> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType;
+
+  CartesianProductGenerator6(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  virtual ~CartesianProductGenerator6() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current6_;
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator6::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator6& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+};  // class CartesianProductGenerator6
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+class CartesianProductGenerator7
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
+
+  CartesianProductGenerator7(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  virtual ~CartesianProductGenerator7() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current7_;
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator7::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator7& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+};  // class CartesianProductGenerator7
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+class CartesianProductGenerator8
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
+
+  CartesianProductGenerator8(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  virtual ~CartesianProductGenerator8() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current8_;
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator8::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator8& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+};  // class CartesianProductGenerator8
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+class CartesianProductGenerator9
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
+
+  CartesianProductGenerator9(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  virtual ~CartesianProductGenerator9() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current9_;
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator9::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator9& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+};  // class CartesianProductGenerator9
+
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+class CartesianProductGenerator10
+    : public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+        T7, T8, T9, T10> > {
+ public:
+  typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
+
+  CartesianProductGenerator10(const ParamGenerator<T1>& g1,
+      const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
+      const ParamGenerator<T4>& g4, const ParamGenerator<T5>& g5,
+      const ParamGenerator<T6>& g6, const ParamGenerator<T7>& g7,
+      const ParamGenerator<T8>& g8, const ParamGenerator<T9>& g9,
+      const ParamGenerator<T10>& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  virtual ~CartesianProductGenerator10() {}
+
+  virtual ParamIteratorInterface<ParamType>* Begin() const {
+    return new Iterator(this, g1_, g1_.begin(), g2_, g2_.begin(), g3_,
+        g3_.begin(), g4_, g4_.begin(), g5_, g5_.begin(), g6_, g6_.begin(), g7_,
+        g7_.begin(), g8_, g8_.begin(), g9_, g9_.begin(), g10_, g10_.begin());
+  }
+  virtual ParamIteratorInterface<ParamType>* End() const {
+    return new Iterator(this, g1_, g1_.end(), g2_, g2_.end(), g3_, g3_.end(),
+        g4_, g4_.end(), g5_, g5_.end(), g6_, g6_.end(), g7_, g7_.end(), g8_,
+        g8_.end(), g9_, g9_.end(), g10_, g10_.end());
+  }
+
+ private:
+  class Iterator : public ParamIteratorInterface<ParamType> {
+   public:
+    Iterator(const ParamGeneratorInterface<ParamType>* base,
+      const ParamGenerator<T1>& g1,
+      const typename ParamGenerator<T1>::iterator& current1,
+      const ParamGenerator<T2>& g2,
+      const typename ParamGenerator<T2>::iterator& current2,
+      const ParamGenerator<T3>& g3,
+      const typename ParamGenerator<T3>::iterator& current3,
+      const ParamGenerator<T4>& g4,
+      const typename ParamGenerator<T4>::iterator& current4,
+      const ParamGenerator<T5>& g5,
+      const typename ParamGenerator<T5>::iterator& current5,
+      const ParamGenerator<T6>& g6,
+      const typename ParamGenerator<T6>::iterator& current6,
+      const ParamGenerator<T7>& g7,
+      const typename ParamGenerator<T7>::iterator& current7,
+      const ParamGenerator<T8>& g8,
+      const typename ParamGenerator<T8>::iterator& current8,
+      const ParamGenerator<T9>& g9,
+      const typename ParamGenerator<T9>::iterator& current9,
+      const ParamGenerator<T10>& g10,
+      const typename ParamGenerator<T10>::iterator& current10)
+        : base_(base),
+          begin1_(g1.begin()), end1_(g1.end()), current1_(current1),
+          begin2_(g2.begin()), end2_(g2.end()), current2_(current2),
+          begin3_(g3.begin()), end3_(g3.end()), current3_(current3),
+          begin4_(g4.begin()), end4_(g4.end()), current4_(current4),
+          begin5_(g5.begin()), end5_(g5.end()), current5_(current5),
+          begin6_(g6.begin()), end6_(g6.end()), current6_(current6),
+          begin7_(g7.begin()), end7_(g7.end()), current7_(current7),
+          begin8_(g8.begin()), end8_(g8.end()), current8_(current8),
+          begin9_(g9.begin()), end9_(g9.end()), current9_(current9),
+          begin10_(g10.begin()), end10_(g10.end()), current10_(current10)    {
+      ComputeCurrentValue();
+    }
+    virtual ~Iterator() {}
+
+    virtual const ParamGeneratorInterface<ParamType>* BaseGenerator() const {
+      return base_;
+    }
+    // Advance should not be called on beyond-of-range iterators
+    // so no component iterators must be beyond end of range, either.
+    virtual void Advance() {
+      assert(!AtEnd());
+      ++current10_;
+      if (current10_ == end10_) {
+        current10_ = begin10_;
+        ++current9_;
+      }
+      if (current9_ == end9_) {
+        current9_ = begin9_;
+        ++current8_;
+      }
+      if (current8_ == end8_) {
+        current8_ = begin8_;
+        ++current7_;
+      }
+      if (current7_ == end7_) {
+        current7_ = begin7_;
+        ++current6_;
+      }
+      if (current6_ == end6_) {
+        current6_ = begin6_;
+        ++current5_;
+      }
+      if (current5_ == end5_) {
+        current5_ = begin5_;
+        ++current4_;
+      }
+      if (current4_ == end4_) {
+        current4_ = begin4_;
+        ++current3_;
+      }
+      if (current3_ == end3_) {
+        current3_ = begin3_;
+        ++current2_;
+      }
+      if (current2_ == end2_) {
+        current2_ = begin2_;
+        ++current1_;
+      }
+      ComputeCurrentValue();
+    }
+    virtual ParamIteratorInterface<ParamType>* Clone() const {
+      return new Iterator(*this);
+    }
+    virtual const ParamType* Current() const { return &current_value_; }
+    virtual bool Equals(const ParamIteratorInterface<ParamType>& other) const {
+      // Having the same base generator guarantees that the other
+      // iterator is of the same type and we can downcast.
+      GTEST_CHECK_(BaseGenerator() == other.BaseGenerator())
+          << "The program attempted to compare iterators "
+          << "from different generators." << std::endl;
+      const Iterator* typed_other =
+          CheckedDowncastToActualType<const Iterator>(&other);
+      // We must report iterators equal if they both point beyond their
+      // respective ranges. That can happen in a variety of fashions,
+      // so we have to consult AtEnd().
+      return (AtEnd() && typed_other->AtEnd()) ||
+         (
+          current1_ == typed_other->current1_ &&
+          current2_ == typed_other->current2_ &&
+          current3_ == typed_other->current3_ &&
+          current4_ == typed_other->current4_ &&
+          current5_ == typed_other->current5_ &&
+          current6_ == typed_other->current6_ &&
+          current7_ == typed_other->current7_ &&
+          current8_ == typed_other->current8_ &&
+          current9_ == typed_other->current9_ &&
+          current10_ == typed_other->current10_);
+    }
+
+   private:
+    Iterator(const Iterator& other)
+        : base_(other.base_),
+        begin1_(other.begin1_),
+        end1_(other.end1_),
+        current1_(other.current1_),
+        begin2_(other.begin2_),
+        end2_(other.end2_),
+        current2_(other.current2_),
+        begin3_(other.begin3_),
+        end3_(other.end3_),
+        current3_(other.current3_),
+        begin4_(other.begin4_),
+        end4_(other.end4_),
+        current4_(other.current4_),
+        begin5_(other.begin5_),
+        end5_(other.end5_),
+        current5_(other.current5_),
+        begin6_(other.begin6_),
+        end6_(other.end6_),
+        current6_(other.current6_),
+        begin7_(other.begin7_),
+        end7_(other.end7_),
+        current7_(other.current7_),
+        begin8_(other.begin8_),
+        end8_(other.end8_),
+        current8_(other.current8_),
+        begin9_(other.begin9_),
+        end9_(other.end9_),
+        current9_(other.current9_),
+        begin10_(other.begin10_),
+        end10_(other.end10_),
+        current10_(other.current10_) {
+      ComputeCurrentValue();
+    }
+
+    void ComputeCurrentValue() {
+      if (!AtEnd())
+        current_value_ = ParamType(*current1_, *current2_, *current3_,
+            *current4_, *current5_, *current6_, *current7_, *current8_,
+            *current9_, *current10_);
+    }
+    bool AtEnd() const {
+      // We must report iterator past the end of the range when either of the
+      // component iterators has reached the end of its range.
+      return
+          current1_ == end1_ ||
+          current2_ == end2_ ||
+          current3_ == end3_ ||
+          current4_ == end4_ ||
+          current5_ == end5_ ||
+          current6_ == end6_ ||
+          current7_ == end7_ ||
+          current8_ == end8_ ||
+          current9_ == end9_ ||
+          current10_ == end10_;
+    }
+
+    // No implementation - assignment is unsupported.
+    void operator=(const Iterator& other);
+
+    const ParamGeneratorInterface<ParamType>* const base_;
+    // begin[i]_ and end[i]_ define the i-th range that Iterator traverses.
+    // current[i]_ is the actual traversing iterator.
+    const typename ParamGenerator<T1>::iterator begin1_;
+    const typename ParamGenerator<T1>::iterator end1_;
+    typename ParamGenerator<T1>::iterator current1_;
+    const typename ParamGenerator<T2>::iterator begin2_;
+    const typename ParamGenerator<T2>::iterator end2_;
+    typename ParamGenerator<T2>::iterator current2_;
+    const typename ParamGenerator<T3>::iterator begin3_;
+    const typename ParamGenerator<T3>::iterator end3_;
+    typename ParamGenerator<T3>::iterator current3_;
+    const typename ParamGenerator<T4>::iterator begin4_;
+    const typename ParamGenerator<T4>::iterator end4_;
+    typename ParamGenerator<T4>::iterator current4_;
+    const typename ParamGenerator<T5>::iterator begin5_;
+    const typename ParamGenerator<T5>::iterator end5_;
+    typename ParamGenerator<T5>::iterator current5_;
+    const typename ParamGenerator<T6>::iterator begin6_;
+    const typename ParamGenerator<T6>::iterator end6_;
+    typename ParamGenerator<T6>::iterator current6_;
+    const typename ParamGenerator<T7>::iterator begin7_;
+    const typename ParamGenerator<T7>::iterator end7_;
+    typename ParamGenerator<T7>::iterator current7_;
+    const typename ParamGenerator<T8>::iterator begin8_;
+    const typename ParamGenerator<T8>::iterator end8_;
+    typename ParamGenerator<T8>::iterator current8_;
+    const typename ParamGenerator<T9>::iterator begin9_;
+    const typename ParamGenerator<T9>::iterator end9_;
+    typename ParamGenerator<T9>::iterator current9_;
+    const typename ParamGenerator<T10>::iterator begin10_;
+    const typename ParamGenerator<T10>::iterator end10_;
+    typename ParamGenerator<T10>::iterator current10_;
+    ParamType current_value_;
+  };  // class CartesianProductGenerator10::Iterator
+
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductGenerator10& other);
+
+  const ParamGenerator<T1> g1_;
+  const ParamGenerator<T2> g2_;
+  const ParamGenerator<T3> g3_;
+  const ParamGenerator<T4> g4_;
+  const ParamGenerator<T5> g5_;
+  const ParamGenerator<T6> g6_;
+  const ParamGenerator<T7> g7_;
+  const ParamGenerator<T8> g8_;
+  const ParamGenerator<T9> g9_;
+  const ParamGenerator<T10> g10_;
+};  // class CartesianProductGenerator10
+
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Helper classes providing Combine() with polymorphic features. They allow
+// casting CartesianProductGeneratorN<T> to ParamGenerator<U> if T is
+// convertible to U.
+//
+template <class Generator1, class Generator2>
+class CartesianProductHolder2 {
+ public:
+CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
+      : g1_(g1), g2_(g2) {}
+  template <typename T1, typename T2>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2> >(
+        new CartesianProductGenerator2<T1, T2>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder2& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+};  // class CartesianProductHolder2
+
+template <class Generator1, class Generator2, class Generator3>
+class CartesianProductHolder3 {
+ public:
+CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3)
+      : g1_(g1), g2_(g2), g3_(g3) {}
+  template <typename T1, typename T2, typename T3>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >(
+        new CartesianProductGenerator3<T1, T2, T3>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder3& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+};  // class CartesianProductHolder3
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4>
+class CartesianProductHolder4 {
+ public:
+CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
+  template <typename T1, typename T2, typename T3, typename T4>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >(
+        new CartesianProductGenerator4<T1, T2, T3, T4>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder4& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+};  // class CartesianProductHolder4
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5>
+class CartesianProductHolder5 {
+ public:
+CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >(
+        new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder5& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+};  // class CartesianProductHolder5
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6>
+class CartesianProductHolder6 {
+ public:
+CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >(
+        new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder6& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+};  // class CartesianProductHolder6
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7>
+class CartesianProductHolder7 {
+ public:
+CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6,
+      T7> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >(
+        new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder7& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+};  // class CartesianProductHolder7
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8>
+class CartesianProductHolder8 {
+ public:
+CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7),
+          g8_(g8) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7,
+      T8> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
+        new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder8& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+};  // class CartesianProductHolder8
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9>
+class CartesianProductHolder9 {
+ public:
+CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9> >(
+        new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder9& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+};  // class CartesianProductHolder9
+
+template <class Generator1, class Generator2, class Generator3,
+    class Generator4, class Generator5, class Generator6, class Generator7,
+    class Generator8, class Generator9, class Generator10>
+class CartesianProductHolder10 {
+ public:
+CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
+    const Generator3& g3, const Generator4& g4, const Generator5& g5,
+    const Generator6& g6, const Generator7& g7, const Generator8& g8,
+    const Generator9& g9, const Generator10& g10)
+      : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7), g8_(g8),
+          g9_(g9), g10_(g10) {}
+  template <typename T1, typename T2, typename T3, typename T4, typename T5,
+      typename T6, typename T7, typename T8, typename T9, typename T10>
+  operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+      T9, T10> >() const {
+    return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
+        T9, T10> >(
+        new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
+            T10>(
+        static_cast<ParamGenerator<T1> >(g1_),
+        static_cast<ParamGenerator<T2> >(g2_),
+        static_cast<ParamGenerator<T3> >(g3_),
+        static_cast<ParamGenerator<T4> >(g4_),
+        static_cast<ParamGenerator<T5> >(g5_),
+        static_cast<ParamGenerator<T6> >(g6_),
+        static_cast<ParamGenerator<T7> >(g7_),
+        static_cast<ParamGenerator<T8> >(g8_),
+        static_cast<ParamGenerator<T9> >(g9_),
+        static_cast<ParamGenerator<T10> >(g10_)));
+  }
+
+ private:
+  // No implementation - assignment is unsupported.
+  void operator=(const CartesianProductHolder10& other);
+
+  const Generator1 g1_;
+  const Generator2 g2_;
+  const Generator3 g3_;
+  const Generator4 g4_;
+  const Generator5 g5_;
+  const Generator6 g6_;
+  const Generator7 g7_;
+  const Generator8 g8_;
+  const Generator9 g9_;
+  const Generator10 g10_;
+};  // class CartesianProductHolder10
+
+# endif  // GTEST_HAS_COMBINE
+
+}  // namespace internal
+}  // namespace testing
+
+#endif  //  GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
+
+#if GTEST_HAS_PARAM_TEST
+
+namespace testing {
+
+// Functions producing parameter generators.
+//
+// Google Test uses these generators to produce parameters for value-
+// parameterized tests. When a parameterized test case is instantiated
+// with a particular generator, Google Test creates and runs tests
+// for each element in the sequence produced by the generator.
+//
+// In the following sample, tests from test case FooTest are instantiated
+// each three times with parameter values 3, 5, and 8:
+//
+// class FooTest : public TestWithParam<int> { ... };
+//
+// TEST_P(FooTest, TestThis) {
+// }
+// TEST_P(FooTest, TestThat) {
+// }
+// INSTANTIATE_TEST_CASE_P(TestSequence, FooTest, Values(3, 5, 8));
+//
+
+// Range() returns generators providing sequences of values in a range.
+//
+// Synopsis:
+// Range(start, end)
+//   - returns a generator producing a sequence of values {start, start+1,
+//     start+2, ..., }.
+// Range(start, end, step)
+//   - returns a generator producing a sequence of values {start, start+step,
+//     start+step+step, ..., }.
+// Notes:
+//   * The generated sequences never include end. For example, Range(1, 5)
+//     returns a generator producing a sequence {1, 2, 3, 4}. Range(1, 9, 2)
+//     returns a generator producing {1, 3, 5, 7}.
+//   * start and end must have the same type. That type may be any integral or
+//     floating-point type or a user defined type satisfying these conditions:
+//     * It must be assignable (have operator=() defined).
+//     * It must have operator+() (operator+(int-compatible type) for
+//       two-operand version).
+//     * It must have operator<() defined.
+//     Elements in the resulting sequences will also have that type.
+//   * Condition start < end must be satisfied in order for resulting sequences
+//     to contain any elements.
+//
+template <typename T, typename IncrementT>
+internal::ParamGenerator<T> Range(T start, T end, IncrementT step) {
+  return internal::ParamGenerator<T>(
+      new internal::RangeGenerator<T, IncrementT>(start, end, step));
+}
+
+template <typename T>
+internal::ParamGenerator<T> Range(T start, T end) {
+  return Range(start, end, 1);
+}
+
+// ValuesIn() function allows generation of tests with parameters coming from
+// a container.
+//
+// Synopsis:
+// ValuesIn(const T (&array)[N])
+//   - returns a generator producing sequences with elements from
+//     a C-style array.
+// ValuesIn(const Container& container)
+//   - returns a generator producing sequences with elements from
+//     an STL-style container.
+// ValuesIn(Iterator begin, Iterator end)
+//   - returns a generator producing sequences with elements from
+//     a range [begin, end) defined by a pair of STL-style iterators. These
+//     iterators can also be plain C pointers.
+//
+// Please note that ValuesIn copies the values from the containers
+// passed in and keeps them to generate tests in RUN_ALL_TESTS().
+//
+// Examples:
+//
+// This instantiates tests from test case StringTest
+// each with C-string values of "foo", "bar", and "baz":
+//
+// const char* strings[] = {"foo", "bar", "baz"};
+// INSTANTIATE_TEST_CASE_P(StringSequence, SrtingTest, ValuesIn(strings));
+//
+// This instantiates tests from test case StlStringTest
+// each with STL strings with values "a" and "b":
+//
+// ::std::vector< ::std::string> GetParameterStrings() {
+//   ::std::vector< ::std::string> v;
+//   v.push_back("a");
+//   v.push_back("b");
+//   return v;
+// }
+//
+// INSTANTIATE_TEST_CASE_P(CharSequence,
+//                         StlStringTest,
+//                         ValuesIn(GetParameterStrings()));
+//
+//
+// This will also instantiate tests from CharTest
+// each with parameter values 'a' and 'b':
+//
+// ::std::list<char> GetParameterChars() {
+//   ::std::list<char> list;
+//   list.push_back('a');
+//   list.push_back('b');
+//   return list;
+// }
+// ::std::list<char> l = GetParameterChars();
+// INSTANTIATE_TEST_CASE_P(CharSequence2,
+//                         CharTest,
+//                         ValuesIn(l.begin(), l.end()));
+//
+template <typename ForwardIterator>
+internal::ParamGenerator<
+  typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+  typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+      ::value_type ParamType;
+  return internal::ParamGenerator<ParamType>(
+      new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
+}
+
+template <typename T, size_t N>
+internal::ParamGenerator<T> ValuesIn(const T (&array)[N]) {
+  return ValuesIn(array, array + N);
+}
+
+template <class Container>
+internal::ParamGenerator<typename Container::value_type> ValuesIn(
+    const Container& container) {
+  return ValuesIn(container.begin(), container.end());
+}
+
+// Values() allows generating tests from explicitly specified list of
+// parameters.
+//
+// Synopsis:
+// Values(T v1, T v2, ..., T vN)
+//   - returns a generator producing sequences with elements v1, v2, ..., vN.
+//
+// For example, this instantiates tests from test case BarTest each
+// with values "one", "two", and "three":
+//
+// INSTANTIATE_TEST_CASE_P(NumSequence, BarTest, Values("one", "two", "three"));
+//
+// This instantiates tests from test case BazTest each with values 1, 2, 3.5.
+// The exact type of values will depend on the type of parameter in BazTest.
+//
+// INSTANTIATE_TEST_CASE_P(FloatingNumbers, BazTest, Values(1, 2, 3.5));
+//
+// Currently, Values() supports from 1 to 50 parameters.
+//
+template <typename T1>
+internal::ValueArray1<T1> Values(T1 v1) {
+  return internal::ValueArray1<T1>(v1);
+}
+
+template <typename T1, typename T2>
+internal::ValueArray2<T1, T2> Values(T1 v1, T2 v2) {
+  return internal::ValueArray2<T1, T2>(v1, v2);
+}
+
+template <typename T1, typename T2, typename T3>
+internal::ValueArray3<T1, T2, T3> Values(T1 v1, T2 v2, T3 v3) {
+  return internal::ValueArray3<T1, T2, T3>(v1, v2, v3);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+internal::ValueArray4<T1, T2, T3, T4> Values(T1 v1, T2 v2, T3 v3, T4 v4) {
+  return internal::ValueArray4<T1, T2, T3, T4>(v1, v2, v3, v4);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+internal::ValueArray5<T1, T2, T3, T4, T5> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5) {
+  return internal::ValueArray5<T1, T2, T3, T4, T5>(v1, v2, v3, v4, v5);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6>
+internal::ValueArray6<T1, T2, T3, T4, T5, T6> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6) {
+  return internal::ValueArray6<T1, T2, T3, T4, T5, T6>(v1, v2, v3, v4, v5, v6);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7>
+internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7) {
+  return internal::ValueArray7<T1, T2, T3, T4, T5, T6, T7>(v1, v2, v3, v4, v5,
+      v6, v7);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8>
+internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8) {
+  return internal::ValueArray8<T1, T2, T3, T4, T5, T6, T7, T8>(v1, v2, v3, v4,
+      v5, v6, v7, v8);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9>
+internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9) {
+  return internal::ValueArray9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10>
+internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10) {
+  return internal::ValueArray10<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11>
+internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+    T11> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11) {
+  return internal::ValueArray11<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
+      T11>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12>
+internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+    T12> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12) {
+  return internal::ValueArray12<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13>
+internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
+    T13> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13) {
+  return internal::ValueArray13<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14>
+internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14) {
+  return internal::ValueArray14<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15>
+internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15) {
+  return internal::ValueArray15<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16>
+internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16) {
+  return internal::ValueArray16<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17>
+internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17) {
+  return internal::ValueArray17<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18>
+internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18) {
+  return internal::ValueArray18<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19>
+internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19) {
+  return internal::ValueArray19<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20>
+internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20) {
+  return internal::ValueArray20<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21>
+internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21) {
+  return internal::ValueArray21<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22>
+internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22) {
+  return internal::ValueArray22<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23>
+internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23) {
+  return internal::ValueArray23<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24>
+internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24) {
+  return internal::ValueArray24<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25>
+internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25) {
+  return internal::ValueArray25<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26>
+internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+    T26> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26) {
+  return internal::ValueArray26<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27>
+internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26,
+    T27> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27) {
+  return internal::ValueArray27<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28>
+internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27,
+    T28> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28) {
+  return internal::ValueArray28<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29>
+internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29) {
+  return internal::ValueArray29<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30>
+internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30) {
+  return internal::ValueArray30<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31>
+internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31) {
+  return internal::ValueArray31<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32>
+internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32) {
+  return internal::ValueArray32<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33>
+internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33) {
+  return internal::ValueArray33<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34>
+internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34) {
+  return internal::ValueArray34<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35>
+internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35) {
+  return internal::ValueArray35<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36>
+internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36) {
+  return internal::ValueArray36<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37>
+internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37> Values(T1 v1, T2 v2, T3 v3,
+    T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37) {
+  return internal::ValueArray37<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37>(v1, v2, v3,
+      v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38>
+internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38) {
+  return internal::ValueArray38<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38>(v1, v2,
+      v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18,
+      v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32,
+      v33, v34, v35, v36, v37, v38);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39>
+internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39> Values(T1 v1, T2 v2,
+    T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12,
+    T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20,
+    T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28,
+    T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36,
+    T37 v37, T38 v38, T39 v39) {
+  return internal::ValueArray39<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39>(v1,
+      v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17,
+      v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
+      v32, v33, v34, v35, v36, v37, v38, v39);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40>
+internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40> Values(T1 v1,
+    T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11,
+    T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19,
+    T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27,
+    T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35,
+    T36 v36, T37 v37, T38 v38, T39 v39, T40 v40) {
+  return internal::ValueArray40<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+      v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29,
+      v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41>
+internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40,
+    T41> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41) {
+  return internal::ValueArray41<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14,
+      v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28,
+      v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42>
+internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41,
+    T42> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42) {
+  return internal::ValueArray42<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13,
+      v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27,
+      v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41,
+      v42);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43>
+internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42,
+    T43> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43) {
+  return internal::ValueArray43<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12,
+      v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26,
+      v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+      v41, v42, v43);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44>
+internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9,
+    T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16, T17 v17,
+    T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24, T25 v25,
+    T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32, T33 v33,
+    T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40, T41 v41,
+    T42 v42, T43 v43, T44 v44) {
+  return internal::ValueArray44<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11,
+      v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25,
+      v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39,
+      v40, v41, v42, v43, v44);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45>
+internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8,
+    T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15, T16 v16,
+    T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23, T24 v24,
+    T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31, T32 v32,
+    T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39, T40 v40,
+    T41 v41, T42 v42, T43 v43, T44 v44, T45 v45) {
+  return internal::ValueArray45<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45>(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+      v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24,
+      v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38,
+      v39, v40, v41, v42, v43, v44, v45);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46>
+internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46) {
+  return internal::ValueArray46<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46>(v1, v2, v3, v4, v5, v6, v7, v8, v9,
+      v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47>
+internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7,
+    T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47) {
+  return internal::ValueArray47<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47>(v1, v2, v3, v4, v5, v6, v7, v8,
+      v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23,
+      v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37,
+      v38, v39, v40, v41, v42, v43, v44, v45, v46, v47);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48>
+internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6,
+    T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14, T15 v15,
+    T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22, T23 v23,
+    T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30, T31 v31,
+    T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38, T39 v39,
+    T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46, T47 v47,
+    T48 v48) {
+  return internal::ValueArray48<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48>(v1, v2, v3, v4, v5, v6, v7,
+      v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22,
+      v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36,
+      v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49>
+internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49> Values(T1 v1, T2 v2, T3 v3, T4 v4, T5 v5,
+    T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14,
+    T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21, T22 v22,
+    T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29, T30 v30,
+    T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37, T38 v38,
+    T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45, T46 v46,
+    T47 v47, T48 v48, T49 v49) {
+  return internal::ValueArray49<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49>(v1, v2, v3, v4, v5, v6,
+      v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21,
+      v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35,
+      v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+    typename T6, typename T7, typename T8, typename T9, typename T10,
+    typename T11, typename T12, typename T13, typename T14, typename T15,
+    typename T16, typename T17, typename T18, typename T19, typename T20,
+    typename T21, typename T22, typename T23, typename T24, typename T25,
+    typename T26, typename T27, typename T28, typename T29, typename T30,
+    typename T31, typename T32, typename T33, typename T34, typename T35,
+    typename T36, typename T37, typename T38, typename T39, typename T40,
+    typename T41, typename T42, typename T43, typename T44, typename T45,
+    typename T46, typename T47, typename T48, typename T49, typename T50>
+internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
+    T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28,
+    T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43,
+    T44, T45, T46, T47, T48, T49, T50> Values(T1 v1, T2 v2, T3 v3, T4 v4,
+    T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13,
+    T14 v14, T15 v15, T16 v16, T17 v17, T18 v18, T19 v19, T20 v20, T21 v21,
+    T22 v22, T23 v23, T24 v24, T25 v25, T26 v26, T27 v27, T28 v28, T29 v29,
+    T30 v30, T31 v31, T32 v32, T33 v33, T34 v34, T35 v35, T36 v36, T37 v37,
+    T38 v38, T39 v39, T40 v40, T41 v41, T42 v42, T43 v43, T44 v44, T45 v45,
+    T46 v46, T47 v47, T48 v48, T49 v49, T50 v50) {
+  return internal::ValueArray50<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
+      T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25,
+      T26, T27, T28, T29, T30, T31, T32, T33, T34, T35, T36, T37, T38, T39,
+      T40, T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>(v1, v2, v3, v4,
+      v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19,
+      v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33,
+      v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
+      v48, v49, v50);
+}
+
+// Bool() allows generating tests with parameters in a set of (false, true).
+//
+// Synopsis:
+// Bool()
+//   - returns a generator producing sequences with elements {false, true}.
+//
+// It is useful when testing code that depends on Boolean flags. Combinations
+// of multiple flags can be tested when several Bool()'s are combined using
+// Combine() function.
+//
+// In the following example all tests in the test case FlagDependentTest
+// will be instantiated twice with parameters false and true.
+//
+// class FlagDependentTest : public testing::TestWithParam<bool> {
+//   virtual void SetUp() {
+//     external_flag = GetParam();
+//   }
+// }
+// INSTANTIATE_TEST_CASE_P(BoolSequence, FlagDependentTest, Bool());
+//
+inline internal::ParamGenerator<bool> Bool() {
+  return Values(false, true);
+}
+
+# if GTEST_HAS_COMBINE
+// Combine() allows the user to combine two or more sequences to produce
+// values of a Cartesian product of those sequences' elements.
+//
+// Synopsis:
+// Combine(gen1, gen2, ..., genN)
+//   - returns a generator producing sequences with elements coming from
+//     the Cartesian product of elements from the sequences generated by
+//     gen1, gen2, ..., genN. The sequence elements will have a type of
+//     tuple<T1, T2, ..., TN> where T1, T2, ..., TN are the types
+//     of elements from sequences produces by gen1, gen2, ..., genN.
+//
+// Combine can have up to 10 arguments. This number is currently limited
+// by the maximum number of elements in the tuple implementation used by Google
+// Test.
+//
+// Example:
+//
+// This will instantiate tests in test case AnimalTest each one with
+// the parameter values tuple("cat", BLACK), tuple("cat", WHITE),
+// tuple("dog", BLACK), and tuple("dog", WHITE):
+//
+// enum Color { BLACK, GRAY, WHITE };
+// class AnimalTest
+//     : public testing::TestWithParam<tuple<const char*, Color> > {...};
+//
+// TEST_P(AnimalTest, AnimalLooksNice) {...}
+//
+// INSTANTIATE_TEST_CASE_P(AnimalVariations, AnimalTest,
+//                         Combine(Values("cat", "dog"),
+//                                 Values(BLACK, WHITE)));
+//
+// This will instantiate tests in FlagDependentTest with all variations of two
+// Boolean flags:
+//
+// class FlagDependentTest
+//     : public testing::TestWithParam<tuple<bool, bool> > {
+//   virtual void SetUp() {
+//     // Assigns external_flag_1 and external_flag_2 values from the tuple.
+//     tie(external_flag_1, external_flag_2) = GetParam();
+//   }
+// };
+//
+// TEST_P(FlagDependentTest, TestFeature1) {
+//   // Test your code using external_flag_1 and external_flag_2 here.
+// }
+// INSTANTIATE_TEST_CASE_P(TwoBoolSequence, FlagDependentTest,
+//                         Combine(Bool(), Bool()));
+//
+template <typename Generator1, typename Generator2>
+internal::CartesianProductHolder2<Generator1, Generator2> Combine(
+    const Generator1& g1, const Generator2& g2) {
+  return internal::CartesianProductHolder2<Generator1, Generator2>(
+      g1, g2);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3>
+internal::CartesianProductHolder3<Generator1, Generator2, Generator3> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3) {
+  return internal::CartesianProductHolder3<Generator1, Generator2, Generator3>(
+      g1, g2, g3);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4>
+internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+    Generator4> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4) {
+  return internal::CartesianProductHolder4<Generator1, Generator2, Generator3,
+      Generator4>(
+      g1, g2, g3, g4);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5>
+internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+    Generator4, Generator5> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5) {
+  return internal::CartesianProductHolder5<Generator1, Generator2, Generator3,
+      Generator4, Generator5>(
+      g1, g2, g3, g4, g5);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6>
+internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6) {
+  return internal::CartesianProductHolder6<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6>(
+      g1, g2, g3, g4, g5, g6);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7>
+internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7) {
+  return internal::CartesianProductHolder7<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7>(
+      g1, g2, g3, g4, g5, g6, g7);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8>
+internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8) {
+  return internal::CartesianProductHolder8<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8>(
+      g1, g2, g3, g4, g5, g6, g7, g8);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9>
+internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8,
+    Generator9> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9) {
+  return internal::CartesianProductHolder9<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9);
+}
+
+template <typename Generator1, typename Generator2, typename Generator3,
+    typename Generator4, typename Generator5, typename Generator6,
+    typename Generator7, typename Generator8, typename Generator9,
+    typename Generator10>
+internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+    Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+    Generator10> Combine(
+    const Generator1& g1, const Generator2& g2, const Generator3& g3,
+        const Generator4& g4, const Generator5& g5, const Generator6& g6,
+        const Generator7& g7, const Generator8& g8, const Generator9& g9,
+        const Generator10& g10) {
+  return internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
+      Generator4, Generator5, Generator6, Generator7, Generator8, Generator9,
+      Generator10>(
+      g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
+}
+# endif  // GTEST_HAS_COMBINE
+
+
+
+# define TEST_P(test_case_name, test_name) \
+  class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
+      : public test_case_name { \
+   public: \
+    GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {} \
+    virtual void TestBody(); \
+   private: \
+    static int AddToRegistry() { \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestPattern(\
+                  #test_case_name, \
+                  #test_name, \
+                  new ::testing::internal::TestMetaFactory< \
+                      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \
+      return 0; \
+    } \
+    static int gtest_registering_dummy_; \
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(\
+        GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
+  }; \
+  int GTEST_TEST_CLASS_NAME_(test_case_name, \
+                             test_name)::gtest_registering_dummy_ = \
+      GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
+  void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
+
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+  ::testing::internal::ParamGenerator<test_case_name::ParamType> \
+      gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
+  int gtest_##prefix##test_case_name##_dummy_ = \
+      ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
+          GetTestCasePatternHolder<test_case_name>(\
+              #test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\
+                  #prefix, \
+                  &gtest_##prefix##test_case_name##_EvalGenerator_, \
+                  __FILE__, __LINE__)
+
+}  // namespace testing
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PARAM_TEST_H_
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+//
+// Google C++ Testing Framework definitions useful in production code.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+
+// When you need to test the private or protected members of a class,
+// use the FRIEND_TEST macro to declare your tests as friends of the
+// class.  For example:
+//
+// class MyClass {
+//  private:
+//   void MyMethod();
+//   FRIEND_TEST(MyClassTest, MyMethod);
+// };
+//
+// class MyClassTest : public testing::Test {
+//   // ...
+// };
+//
+// TEST_F(MyClassTest, MyMethod) {
+//   // Can call MyClass::MyMethod() here.
+// }
+
+#define FRIEND_TEST(test_case_name, test_name)\
+friend class test_case_name##_##test_name##_Test
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PROD_H_
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: mheule@google.com (Markus Heule)
+//
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+
+#include <iosfwd>
+#include <vector>
+
+namespace testing {
+
+// A copyable object representing the result of a test part (i.e. an
+// assertion or an explicit FAIL(), ADD_FAILURE(), or SUCCESS()).
+//
+// Don't inherit from TestPartResult as its destructor is not virtual.
+class GTEST_API_ TestPartResult {
+ public:
+  // The possible outcomes of a test part (i.e. an assertion or an
+  // explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+  enum Type {
+    kSuccess,          // Succeeded.
+    kNonFatalFailure,  // Failed but the test can continue.
+    kFatalFailure      // Failed and the test should be terminated.
+  };
+
+  // C'tor.  TestPartResult does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestPartResult object.
+  TestPartResult(Type a_type,
+                 const char* a_file_name,
+                 int a_line_number,
+                 const char* a_message)
+      : type_(a_type),
+        file_name_(a_file_name == NULL ? "" : a_file_name),
+        line_number_(a_line_number),
+        summary_(ExtractSummary(a_message)),
+        message_(a_message) {
+  }
+
+  // Gets the outcome of the test part.
+  Type type() const { return type_; }
+
+  // Gets the name of the source file where the test part took place, or
+  // NULL if it's unknown.
+  const char* file_name() const {
+    return file_name_.empty() ? NULL : file_name_.c_str();
+  }
+
+  // Gets the line in the source file where the test part took place,
+  // or -1 if it's unknown.
+  int line_number() const { return line_number_; }
+
+  // Gets the summary of the failure message.
+  const char* summary() const { return summary_.c_str(); }
+
+  // Gets the message associated with the test part.
+  const char* message() const { return message_.c_str(); }
+
+  // Returns true iff the test part passed.
+  bool passed() const { return type_ == kSuccess; }
+
+  // Returns true iff the test part failed.
+  bool failed() const { return type_ != kSuccess; }
+
+  // Returns true iff the test part non-fatally failed.
+  bool nonfatally_failed() const { return type_ == kNonFatalFailure; }
+
+  // Returns true iff the test part fatally failed.
+  bool fatally_failed() const { return type_ == kFatalFailure; }
+
+ private:
+  Type type_;
+
+  // Gets the summary of the failure message by omitting the stack
+  // trace in it.
+  static std::string ExtractSummary(const char* message);
+
+  // The name of the source file where the test part took place, or
+  // "" if the source file is unknown.
+  std::string file_name_;
+  // The line in the source file where the test part took place, or -1
+  // if the line number is unknown.
+  int line_number_;
+  std::string summary_;  // The test failure summary.
+  std::string message_;  // The test failure message.
+};
+
+// Prints a TestPartResult object.
+std::ostream& operator<<(std::ostream& os, const TestPartResult& result);
+
+// An array of TestPartResult objects.
+//
+// Don't inherit from TestPartResultArray as its destructor is not
+// virtual.
+class GTEST_API_ TestPartResultArray {
+ public:
+  TestPartResultArray() {}
+
+  // Appends the given TestPartResult to the array.
+  void Append(const TestPartResult& result);
+
+  // Returns the TestPartResult at the given index (0-based).
+  const TestPartResult& GetTestPartResult(int index) const;
+
+  // Returns the number of TestPartResult objects in the array.
+  int size() const;
+
+ private:
+  std::vector<TestPartResult> array_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestPartResultArray);
+};
+
+// This interface knows how to report a test part result.
+class TestPartResultReporterInterface {
+ public:
+  virtual ~TestPartResultReporterInterface() {}
+
+  virtual void ReportTestPartResult(const TestPartResult& result) = 0;
+};
+
+namespace internal {
+
+// This helper class is used by {ASSERT|EXPECT}_NO_FATAL_FAILURE to check if a
+// statement generates new fatal failures. To do so it registers itself as the
+// current test part result reporter. Besides checking if fatal failures were
+// reported, it only delegates the reporting to the former result reporter.
+// The original result reporter is restored in the destructor.
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+class GTEST_API_ HasNewFatalFailureHelper
+    : public TestPartResultReporterInterface {
+ public:
+  HasNewFatalFailureHelper();
+  virtual ~HasNewFatalFailureHelper();
+  virtual void ReportTestPartResult(const TestPartResult& result);
+  bool has_new_fatal_failure() const { return has_new_fatal_failure_; }
+ private:
+  bool has_new_fatal_failure_;
+  TestPartResultReporterInterface* original_reporter_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(HasNewFatalFailureHelper);
+};
+
+}  // namespace internal
+
+}  // namespace testing
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TEST_PART_H_
+// Copyright 2008 Google Inc.
+// All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+#define GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// This header implements typed tests and type-parameterized tests.
+
+// Typed (aka type-driven) tests repeat the same test for types in a
+// list.  You must know which types you want to test with when writing
+// typed tests. Here's how you do it:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+ public:
+  ...
+  typedef std::list<T> List;
+  static T shared_;
+  T value_;
+};
+
+// Next, associate a list of types with the test case, which will be
+// repeated for each type in the list.  The typedef is necessary for
+// the macro to parse correctly.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+TYPED_TEST_CASE(FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   TYPED_TEST_CASE(FooTest, int);
+
+// Then, use TYPED_TEST() instead of TEST_F() to define as many typed
+// tests for this test case as you want.
+TYPED_TEST(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  // Since we are inside a derived class template, C++ requires use to
+  // visit the members of FooTest via 'this'.
+  TypeParam n = this->value_;
+
+  // To visit static members of the fixture, add the TestFixture::
+  // prefix.
+  n += TestFixture::shared_;
+
+  // To refer to typedefs in the fixture, add the "typename
+  // TestFixture::" prefix.
+  typename TestFixture::List values;
+  values.push_back(n);
+  ...
+}
+
+TYPED_TEST(FooTest, HasPropertyA) { ... }
+
+#endif  // 0
+
+// Type-parameterized tests are abstract test patterns parameterized
+// by a type.  Compared with typed tests, type-parameterized tests
+// allow you to define the test pattern without knowing what the type
+// parameters are.  The defined pattern can be instantiated with
+// different types any number of times, in any number of translation
+// units.
+//
+// If you are designing an interface or concept, you can define a
+// suite of type-parameterized tests to verify properties that any
+// valid implementation of the interface/concept should have.  Then,
+// each implementation can easily instantiate the test suite to verify
+// that it conforms to the requirements, without having to write
+// similar tests repeatedly.  Here's an example:
+
+#if 0
+
+// First, define a fixture class template.  It should be parameterized
+// by a type.  Remember to derive it from testing::Test.
+template <typename T>
+class FooTest : public testing::Test {
+  ...
+};
+
+// Next, declare that you will define a type-parameterized test case
+// (the _P suffix is for "parameterized" or "pattern", whichever you
+// prefer):
+TYPED_TEST_CASE_P(FooTest);
+
+// Then, use TYPED_TEST_P() to define as many type-parameterized tests
+// for this type-parameterized test case as you want.
+TYPED_TEST_P(FooTest, DoesBlah) {
+  // Inside a test, refer to TypeParam to get the type parameter.
+  TypeParam n = 0;
+  ...
+}
+
+TYPED_TEST_P(FooTest, HasPropertyA) { ... }
+
+// Now the tricky part: you need to register all test patterns before
+// you can instantiate them.  The first argument of the macro is the
+// test case name; the rest are the names of the tests in this test
+// case.
+REGISTER_TYPED_TEST_CASE_P(FooTest,
+                           DoesBlah, HasPropertyA);
+
+// Finally, you are free to instantiate the pattern with the types you
+// want.  If you put the above code in a header file, you can #include
+// it in multiple C++ source files and instantiate it multiple times.
+//
+// To distinguish different instances of the pattern, the first
+// argument to the INSTANTIATE_* macro is a prefix that will be added
+// to the actual test case name.  Remember to pick unique prefixes for
+// different instances.
+typedef testing::Types<char, int, unsigned int> MyTypes;
+INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
+
+// If the type list contains only one type, you can write that type
+// directly without Types<...>:
+//   INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, int);
+
+#endif  // 0
+
+
+// Implements typed tests.
+
+#if GTEST_HAS_TYPED_TEST
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the typedef for the type parameters of the
+// given test case.
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define TYPED_TEST_CASE(CaseName, Types) \
+  typedef ::testing::internal::TypeList< Types >::type \
+      GTEST_TYPE_PARAMS_(CaseName)
+
+# define TYPED_TEST(CaseName, TestName) \
+  template <typename gtest_TypeParam_> \
+  class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
+      : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTest< \
+          CaseName, \
+          ::testing::internal::TemplateSel< \
+              GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
+          GTEST_TYPE_PARAMS_(CaseName)>::Register(\
+              "", #CaseName, #TestName, 0); \
+  template <typename gtest_TypeParam_> \
+  void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
+
+#endif  // GTEST_HAS_TYPED_TEST
+
+// Implements type-parameterized tests.
+
+#if GTEST_HAS_TYPED_TEST_P
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the namespace name that the type-parameterized tests for
+// the given type-parameterized test case are defined in.  The exact
+// name of the namespace is subject to change without notice.
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
+  gtest_case_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+//
+// Expands to the name of the variable used to remember the names of
+// the defined tests in the given test case.
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+  gtest_typed_test_case_p_state_##TestCaseName##_
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
+//
+// Expands to the name of the variable used to remember the names of
+// the registered tests in the given test case.
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+  gtest_registered_test_names_##TestCaseName##_
+
+// The variables defined in the type-parameterized test macros are
+// static as typically these macros are used in a .h file that can be
+// #included in multiple translation units linked together.
+# define TYPED_TEST_CASE_P(CaseName) \
+  static ::testing::internal::TypedTestCasePState \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
+
+# define TYPED_TEST_P(CaseName, TestName) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  template <typename gtest_TypeParam_> \
+  class TestName : public CaseName<gtest_TypeParam_> { \
+   private: \
+    typedef CaseName<gtest_TypeParam_> TestFixture; \
+    typedef gtest_TypeParam_ TypeParam; \
+    virtual void TestBody(); \
+  }; \
+  static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
+          __FILE__, __LINE__, #CaseName, #TestName); \
+  } \
+  template <typename gtest_TypeParam_> \
+  void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
+
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+  namespace GTEST_CASE_NAMESPACE_(CaseName) { \
+  typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
+  } \
+  static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \
+      GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\
+          __FILE__, __LINE__, #__VA_ARGS__)
+
+// The 'Types' template argument below must have spaces around it
+// since some compilers may choke on '>>' when passing a template
+// instance (e.g. Types<int>)
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+  bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
+      ::testing::internal::TypeParameterizedTestCase<CaseName, \
+          GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
+          ::testing::internal::TypeList< Types >::type>::Register(\
+              #Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
+
+#endif  // GTEST_HAS_TYPED_TEST_P
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_TYPED_TEST_H_
+
+// Depending on the platform, different string classes are available.
+// On Linux, in addition to ::std::string, Google also makes use of
+// class ::string, which has the same interface as ::std::string, but
+// has a different implementation.
+//
+// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
+// ::string is available AND is a distinct type to ::std::string, or
+// define it to 0 to indicate otherwise.
+//
+// If the user's ::std::string and ::string are the same class due to
+// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0.
+//
+// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined
+// heuristically.
+
+namespace testing {
+
+// Declares the flags.
+
+// This flag temporary enables the disabled tests.
+GTEST_DECLARE_bool_(also_run_disabled_tests);
+
+// This flag brings the debugger on an assertion failure.
+GTEST_DECLARE_bool_(break_on_failure);
+
+// This flag controls whether Google Test catches all test-thrown exceptions
+// and logs them as failures.
+GTEST_DECLARE_bool_(catch_exceptions);
+
+// This flag enables using colors in terminal output. Available values are
+// "yes" to enable colors, "no" (disable colors), or "auto" (the default)
+// to let Google Test decide.
+GTEST_DECLARE_string_(color);
+
+// This flag sets up the filter to select by name using a glob pattern
+// the tests to run. If the filter is not given all tests are executed.
+GTEST_DECLARE_string_(filter);
+
+// This flag causes the Google Test to list tests. None of the tests listed
+// are actually run if the flag is provided.
+GTEST_DECLARE_bool_(list_tests);
+
+// This flag controls whether Google Test emits a detailed XML report to a file
+// in addition to its normal textual output.
+GTEST_DECLARE_string_(output);
+
+// This flags control whether Google Test prints the elapsed time for each
+// test.
+GTEST_DECLARE_bool_(print_time);
+
+// This flag specifies the random number seed.
+GTEST_DECLARE_int32_(random_seed);
+
+// This flag sets how many times the tests are repeated. The default value
+// is 1. If the value is -1 the tests are repeating forever.
+GTEST_DECLARE_int32_(repeat);
+
+// This flag controls whether Google Test includes Google Test internal
+// stack frames in failure stack traces.
+GTEST_DECLARE_bool_(show_internal_stack_frames);
+
+// When this flag is specified, tests' order is randomized on every iteration.
+GTEST_DECLARE_bool_(shuffle);
+
+// This flag specifies the maximum number of stack frames to be
+// printed in a failure message.
+GTEST_DECLARE_int32_(stack_trace_depth);
+
+// When this flag is specified, a failed assertion will throw an
+// exception if exceptions are enabled, or exit the program with a
+// non-zero code otherwise.
+GTEST_DECLARE_bool_(throw_on_failure);
+
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
+// The upper limit for valid stack trace depths.
+const int kMaxStackTraceDepth = 100;
+
+namespace internal {
+
+class AssertHelper;
+class DefaultGlobalTestPartResultReporter;
+class ExecDeathTest;
+class NoExecDeathTest;
+class FinalSuccessChecker;
+class GTestFlagSaver;
+class StreamingListenerTest;
+class TestResultAccessor;
+class TestEventListenersAccessor;
+class TestEventRepeater;
+class UnitTestRecordPropertyTestHelper;
+class WindowsDeathTest;
+class UnitTestImpl* GetUnitTestImpl();
+void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
+                                    const std::string& message);
+
+}  // namespace internal
+
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
+// A class for indicating whether an assertion was successful.  When
+// the assertion wasn't successful, the AssertionResult object
+// remembers a non-empty message that describes how it failed.
+//
+// To create an instance of this class, use one of the factory functions
+// (AssertionSuccess() and AssertionFailure()).
+//
+// This class is useful for two purposes:
+//   1. Defining predicate functions to be used with Boolean test assertions
+//      EXPECT_TRUE/EXPECT_FALSE and their ASSERT_ counterparts
+//   2. Defining predicate-format functions to be
+//      used with predicate assertions (ASSERT_PRED_FORMAT*, etc).
+//
+// For example, if you define IsEven predicate:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then the failed expectation EXPECT_TRUE(IsEven(Fib(5)))
+// will print the message
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false (5 is odd)
+//   Expected: true
+//
+// instead of a more opaque
+//
+//   Value of: IsEven(Fib(5))
+//     Actual: false
+//   Expected: true
+//
+// in case IsEven is a simple Boolean predicate.
+//
+// If you expect your predicate to be reused and want to support informative
+// messages in EXPECT_FALSE and ASSERT_FALSE (negative assertions show up
+// about half as often as positive ones in our tests), supply messages for
+// both success and failure cases:
+//
+//   testing::AssertionResult IsEven(int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess() << n << " is even";
+//     else
+//       return testing::AssertionFailure() << n << " is odd";
+//   }
+//
+// Then a statement EXPECT_FALSE(IsEven(Fib(6))) will print
+//
+//   Value of: IsEven(Fib(6))
+//     Actual: true (8 is even)
+//   Expected: false
+//
+// NB: Predicates that support negative Boolean assertions have reduced
+// performance in positive ones so be careful not to use them in tests
+// that have lots (tens of thousands) of positive Boolean assertions.
+//
+// To use this class with EXPECT_PRED_FORMAT assertions such as:
+//
+//   // Verifies that Foo() returns an even number.
+//   EXPECT_PRED_FORMAT1(IsEven, Foo());
+//
+// you need to define:
+//
+//   testing::AssertionResult IsEven(const char* expr, int n) {
+//     if ((n % 2) == 0)
+//       return testing::AssertionSuccess();
+//     else
+//       return testing::AssertionFailure()
+//         << "Expected: " << expr << " is even\n  Actual: it's " << n;
+//   }
+//
+// If Foo() returns 5, you will see the following message:
+//
+//   Expected: Foo() is even
+//     Actual: it's 5
+//
+class GTEST_API_ AssertionResult {
+ public:
+  // Copy constructor.
+  // Used in EXPECT_TRUE/FALSE(assertion_result).
+  AssertionResult(const AssertionResult& other);
+  // Used in the EXPECT_TRUE/FALSE(bool_expression).
+  explicit AssertionResult(bool success) : success_(success) {}
+
+  // Returns true iff the assertion succeeded.
+  operator bool() const { return success_; }  // NOLINT
+
+  // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
+  AssertionResult operator!() const;
+
+  // Returns the text streamed into this AssertionResult. Test assertions
+  // use it when they fail (i.e., the predicate's outcome doesn't match the
+  // assertion's expectation). When nothing has been streamed into the
+  // object, returns an empty string.
+  const char* message() const {
+    return message_.get() != NULL ?  message_->c_str() : "";
+  }
+  // TODO(vladl@google.com): Remove this after making sure no clients use it.
+  // Deprecated; please use message() instead.
+  const char* failure_message() const { return message(); }
+
+  // Streams a custom failure message into this object.
+  template <typename T> AssertionResult& operator<<(const T& value) {
+    AppendMessage(Message() << value);
+    return *this;
+  }
+
+  // Allows streaming basic output manipulators such as endl or flush into
+  // this object.
+  AssertionResult& operator<<(
+      ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+    AppendMessage(Message() << basic_manipulator);
+    return *this;
+  }
+
+ private:
+  // Appends the contents of message to message_.
+  void AppendMessage(const Message& a_message) {
+    if (message_.get() == NULL)
+      message_.reset(new ::std::string);
+    message_->append(a_message.GetString().c_str());
+  }
+
+  // Stores result of the assertion predicate.
+  bool success_;
+  // Stores the message describing the condition in case the expectation
+  // construct is not satisfied with the predicate's outcome.
+  // Referenced via a pointer to avoid taking too much stack frame space
+  // with test assertions.
+  internal::scoped_ptr< ::std::string> message_;
+
+  GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
+
+// Makes a successful assertion result.
+GTEST_API_ AssertionResult AssertionSuccess();
+
+// Makes a failed assertion result.
+GTEST_API_ AssertionResult AssertionFailure();
+
+// Makes a failed assertion result with the given failure message.
+// Deprecated; use AssertionFailure() << msg.
+GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
+
+// The abstract class that all tests inherit from.
+//
+// In Google Test, a unit test program contains one or many TestCases, and
+// each TestCase contains one or many Tests.
+//
+// When you define a test using the TEST macro, you don't need to
+// explicitly derive from Test - the TEST macro automatically does
+// this for you.
+//
+// The only time you derive from Test is when defining a test fixture
+// to be used a TEST_F.  For example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { ... }
+//     virtual void TearDown() { ... }
+//     ...
+//   };
+//
+//   TEST_F(FooTest, Bar) { ... }
+//   TEST_F(FooTest, Baz) { ... }
+//
+// Test is not copyable.
+class GTEST_API_ Test {
+ public:
+  friend class TestInfo;
+
+  // Defines types for pointers to functions that set up and tear down
+  // a test case.
+  typedef internal::SetUpTestCaseFunc SetUpTestCaseFunc;
+  typedef internal::TearDownTestCaseFunc TearDownTestCaseFunc;
+
+  // The d'tor is virtual as we intend to inherit from Test.
+  virtual ~Test();
+
+  // Sets up the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::SetUpTestCase() before running the first
+  // test in test case Foo.  Hence a sub-class can define its own
+  // SetUpTestCase() method to shadow the one defined in the super
+  // class.
+  static void SetUpTestCase() {}
+
+  // Tears down the stuff shared by all tests in this test case.
+  //
+  // Google Test will call Foo::TearDownTestCase() after running the last
+  // test in test case Foo.  Hence a sub-class can define its own
+  // TearDownTestCase() method to shadow the one defined in the super
+  // class.
+  static void TearDownTestCase() {}
+
+  // Returns true iff the current test has a fatal failure.
+  static bool HasFatalFailure();
+
+  // Returns true iff the current test has a non-fatal failure.
+  static bool HasNonfatalFailure();
+
+  // Returns true iff the current test has a (either fatal or
+  // non-fatal) failure.
+  static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
+  // Logs a property for the current test, test case, or for the entire
+  // invocation of the test program when used outside of the context of a
+  // test case.  Only the last value for a given key is remembered.  These
+  // are public static so they can be called from utility functions that are
+  // not members of the test fixture.  Calls to RecordProperty made during
+  // lifespan of the test (from the moment its constructor starts to the
+  // moment its destructor finishes) will be output in XML as attributes of
+  // the <testcase> element.  Properties recorded from fixture's
+  // SetUpTestCase or TearDownTestCase are logged as attributes of the
+  // corresponding <testsuite> element.  Calls to RecordProperty made in the
+  // global context (before or after invocation of RUN_ALL_TESTS and from
+  // SetUp/TearDown method of Environment objects registered with Google
+  // Test) will be output as attributes of the <testsuites> element.
+  static void RecordProperty(const std::string& key, const std::string& value);
+  static void RecordProperty(const std::string& key, int value);
+
+ protected:
+  // Creates a Test object.
+  Test();
+
+  // Sets up the test fixture.
+  virtual void SetUp();
+
+  // Tears down the test fixture.
+  virtual void TearDown();
+
+ private:
+  // Returns true iff the current test has the same fixture class as
+  // the first test in the current test case.
+  static bool HasSameFixtureClass();
+
+  // Runs the test after the test fixture has been set up.
+  //
+  // A sub-class must implement this to define the test logic.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION DIRECTLY IN A USER PROGRAM.
+  // Instead, use the TEST or TEST_F macro.
+  virtual void TestBody() = 0;
+
+  // Sets up, executes, and tears down the test.
+  void Run();
+
+  // Deletes self.  We deliberately pick an unusual name for this
+  // internal method to avoid clashing with names used in user TESTs.
+  void DeleteSelf_() { delete this; }
+
+  // Uses a GTestFlagSaver to save and restore all Google Test flags.
+  const internal::GTestFlagSaver* const gtest_flag_saver_;
+
+  // Often a user mis-spells SetUp() as Setup() and spends a long time
+  // wondering why it is never called by Google Test.  The declaration of
+  // the following method is solely for catching such an error at
+  // compile time:
+  //
+  //   - The return type is deliberately chosen to be not void, so it
+  //   will be a conflict if a user declares void Setup() in his test
+  //   fixture.
+  //
+  //   - This method is private, so it will be another compiler error
+  //   if a user calls it from his test fixture.
+  //
+  // DO NOT OVERRIDE THIS FUNCTION.
+  //
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+
+  // We disallow copying Tests.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(Test);
+};
+
+typedef internal::TimeInMillis TimeInMillis;
+
+// A copyable object representing a user specified test property which can be
+// output as a key/value string pair.
+//
+// Don't inherit from TestProperty as its destructor is not virtual.
+class TestProperty {
+ public:
+  // C'tor.  TestProperty does NOT have a default constructor.
+  // Always use this constructor (with parameters) to create a
+  // TestProperty object.
+  TestProperty(const std::string& a_key, const std::string& a_value) :
+    key_(a_key), value_(a_value) {
+  }
+
+  // Gets the user supplied key.
+  const char* key() const {
+    return key_.c_str();
+  }
+
+  // Gets the user supplied value.
+  const char* value() const {
+    return value_.c_str();
+  }
+
+  // Sets a new value, overriding the one supplied in the constructor.
+  void SetValue(const std::string& new_value) {
+    value_ = new_value;
+  }
+
+ private:
+  // The key supplied by the user.
+  std::string key_;
+  // The value supplied by the user.
+  std::string value_;
+};
+
+// The result of a single Test.  This includes a list of
+// TestPartResults, a list of TestProperties, a count of how many
+// death tests there are in the Test, and how much time it took to run
+// the Test.
+//
+// TestResult is not copyable.
+class GTEST_API_ TestResult {
+ public:
+  // Creates an empty TestResult.
+  TestResult();
+
+  // D'tor.  Do not inherit from TestResult.
+  ~TestResult();
+
+  // Gets the number of all test parts.  This is the sum of the number
+  // of successful test parts and the number of failed test parts.
+  int total_part_count() const;
+
+  // Returns the number of the test properties.
+  int test_property_count() const;
+
+  // Returns true iff the test passed (i.e. no test part failed).
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test failed.
+  bool Failed() const;
+
+  // Returns true iff the test fatally failed.
+  bool HasFatalFailure() const;
+
+  // Returns true iff the test has a non-fatal failure.
+  bool HasNonfatalFailure() const;
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test part result among all the results. i can range
+  // from 0 to test_property_count() - 1. If i is not in that range, aborts
+  // the program.
+  const TestPartResult& GetTestPartResult(int i) const;
+
+  // Returns the i-th test property. i can range from 0 to
+  // test_property_count() - 1. If i is not in that range, aborts the
+  // program.
+  const TestProperty& GetTestProperty(int i) const;
+
+ private:
+  friend class TestInfo;
+  friend class TestCase;
+  friend class UnitTest;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::ExecDeathTest;
+  friend class internal::TestResultAccessor;
+  friend class internal::UnitTestImpl;
+  friend class internal::WindowsDeathTest;
+
+  // Gets the vector of TestPartResults.
+  const std::vector<TestPartResult>& test_part_results() const {
+    return test_part_results_;
+  }
+
+  // Gets the vector of TestProperties.
+  const std::vector<TestProperty>& test_properties() const {
+    return test_properties_;
+  }
+
+  // Sets the elapsed time.
+  void set_elapsed_time(TimeInMillis elapsed) { elapsed_time_ = elapsed; }
+
+  // Adds a test property to the list. The property is validated and may add
+  // a non-fatal failure if invalid (e.g., if it conflicts with reserved
+  // key names). If a property is already recorded for the same key, the
+  // value will be updated, rather than storing multiple values for the same
+  // key.  xml_element specifies the element for which the property is being
+  // recorded and is used for validation.
+  void RecordProperty(const std::string& xml_element,
+                      const TestProperty& test_property);
+
+  // Adds a failure if the key is a reserved attribute of Google Test
+  // testcase tags.  Returns true if the property is valid.
+  // TODO(russr): Validate attribute names are legal and human readable.
+  static bool ValidateTestProperty(const std::string& xml_element,
+                                   const TestProperty& test_property);
+
+  // Adds a test part result to the list.
+  void AddTestPartResult(const TestPartResult& test_part_result);
+
+  // Returns the death test count.
+  int death_test_count() const { return death_test_count_; }
+
+  // Increments the death test count, returning the new count.
+  int increment_death_test_count() { return ++death_test_count_; }
+
+  // Clears the test part results.
+  void ClearTestPartResults();
+
+  // Clears the object.
+  void Clear();
+
+  // Protects mutable state of the property vector and of owned
+  // properties, whose values may be updated.
+  internal::Mutex test_properites_mutex_;
+
+  // The vector of TestPartResults
+  std::vector<TestPartResult> test_part_results_;
+  // The vector of TestProperties
+  std::vector<TestProperty> test_properties_;
+  // Running count of death tests.
+  int death_test_count_;
+  // The elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+
+  // We disallow copying TestResult.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestResult);
+};  // class TestResult
+
+// A TestInfo object stores the following information about a test:
+//
+//   Test case name
+//   Test name
+//   Whether the test should be run
+//   A function pointer that creates the test object when invoked
+//   Test result
+//
+// The constructor of TestInfo registers itself with the UnitTest
+// singleton such that the RUN_ALL_TESTS() macro knows which tests to
+// run.
+class GTEST_API_ TestInfo {
+ public:
+  // Destructs a TestInfo object.  This function is not virtual, so
+  // don't inherit from TestInfo.
+  ~TestInfo();
+
+  // Returns the test case name.
+  const char* test_case_name() const { return test_case_name_.c_str(); }
+
+  // Returns the test name.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a typed
+  // or a type-parameterized test.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns the text representation of the value parameter, or NULL if this
+  // is not a value-parameterized test.
+  const char* value_param() const {
+    if (value_param_.get() != NULL)
+      return value_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if this test should run, that is if the test is not
+  // disabled (or it is disabled but the also_run_disabled_tests flag has
+  // been specified) and its full name matches the user-specified filter.
+  //
+  // Google Test allows the user to filter the tests by their full names.
+  // The full name of a test Bar in test case Foo is defined as
+  // "Foo.Bar".  Only the tests that match the filter will run.
+  //
+  // A filter is a colon-separated list of glob (not regex) patterns,
+  // optionally followed by a '-' and a colon-separated list of
+  // negative patterns (tests to exclude).  A test is run if it
+  // matches one of the positive patterns and does not match any of
+  // the negative patterns.
+  //
+  // For example, *A*:Foo.* is a filter that matches any string that
+  // contains the character 'A' or starts with "Foo.".
+  bool should_run() const { return should_run_; }
+
+  // Returns true iff this test will appear in the XML report.
+  bool is_reportable() const {
+    // For now, the XML report includes all tests matching the filter.
+    // In the future, we may trim tests that are excluded because of
+    // sharding.
+    return matches_filter_;
+  }
+
+  // Returns the result of the test.
+  const TestResult* result() const { return &result_; }
+
+ private:
+#if GTEST_HAS_DEATH_TEST
+  friend class internal::DefaultDeathTestFactory;
+#endif  // GTEST_HAS_DEATH_TEST
+  friend class Test;
+  friend class TestCase;
+  friend class internal::UnitTestImpl;
+  friend class internal::StreamingListenerTest;
+  friend TestInfo* internal::MakeAndRegisterTestInfo(
+      const char* test_case_name,
+      const char* name,
+      const char* type_param,
+      const char* value_param,
+      internal::TypeId fixture_class_id,
+      Test::SetUpTestCaseFunc set_up_tc,
+      Test::TearDownTestCaseFunc tear_down_tc,
+      internal::TestFactoryBase* factory);
+
+  // Constructs a TestInfo object. The newly constructed instance assumes
+  // ownership of the factory object.
+  TestInfo(const std::string& test_case_name,
+           const std::string& name,
+           const char* a_type_param,   // NULL if not a type-parameterized test
+           const char* a_value_param,  // NULL if not a value-parameterized test
+           internal::TypeId fixture_class_id,
+           internal::TestFactoryBase* factory);
+
+  // Increments the number of death tests encountered in this test so
+  // far.
+  int increment_death_test_count() {
+    return result_.increment_death_test_count();
+  }
+
+  // Creates the test object, runs it, records its result, and then
+  // deletes it.
+  void Run();
+
+  static void ClearTestResult(TestInfo* test_info) {
+    test_info->result_.Clear();
+  }
+
+  // These fields are immutable properties of the test.
+  const std::string test_case_name_;     // Test case name
+  const std::string name_;               // Test name
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // Text representation of the value parameter, or NULL if this is not a
+  // value-parameterized test.
+  const internal::scoped_ptr<const ::std::string> value_param_;
+  const internal::TypeId fixture_class_id_;   // ID of the test fixture class
+  bool should_run_;                 // True iff this test should run
+  bool is_disabled_;                // True iff this test is disabled
+  bool matches_filter_;             // True if this test matches the
+                                    // user-specified filter.
+  internal::TestFactoryBase* const factory_;  // The factory that creates
+                                              // the test object
+
+  // This field is mutable and needs to be reset before running the
+  // test for the second time.
+  TestResult result_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
+};
+
+// A test case, which consists of a vector of TestInfos.
+//
+// TestCase is not copyable.
+class GTEST_API_ TestCase {
+ public:
+  // Creates a TestCase with the given name.
+  //
+  // TestCase does NOT have a default constructor.  Always use this
+  // constructor to create a TestCase object.
+  //
+  // Arguments:
+  //
+  //   name:         name of the test case
+  //   a_type_param: the name of the test's type parameter, or NULL if
+  //                 this is not a type-parameterized test.
+  //   set_up_tc:    pointer to the function that sets up the test case
+  //   tear_down_tc: pointer to the function that tears down the test case
+  TestCase(const char* name, const char* a_type_param,
+           Test::SetUpTestCaseFunc set_up_tc,
+           Test::TearDownTestCaseFunc tear_down_tc);
+
+  // Destructor of TestCase.
+  virtual ~TestCase();
+
+  // Gets the name of the TestCase.
+  const char* name() const { return name_.c_str(); }
+
+  // Returns the name of the parameter type, or NULL if this is not a
+  // type-parameterized test case.
+  const char* type_param() const {
+    if (type_param_.get() != NULL)
+      return type_param_->c_str();
+    return NULL;
+  }
+
+  // Returns true if any test in this test case should run.
+  bool should_run() const { return should_run_; }
+
+  // Gets the number of successful tests in this test case.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests in this test case.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests in this test case.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Get the number of tests in this test case that should run.
+  int test_to_run_count() const;
+
+  // Gets the number of all tests in this test case.
+  int total_test_count() const;
+
+  // Returns true iff the test case passed.
+  bool Passed() const { return !Failed(); }
+
+  // Returns true iff the test case failed.
+  bool Failed() const { return failed_test_count() > 0; }
+
+  // Returns the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const { return elapsed_time_; }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  const TestInfo* GetTestInfo(int i) const;
+
+  // Returns the TestResult that holds test properties recorded during
+  // execution of SetUpTestCase and TearDownTestCase.
+  const TestResult& ad_hoc_test_result() const { return ad_hoc_test_result_; }
+
+ private:
+  friend class Test;
+  friend class internal::UnitTestImpl;
+
+  // Gets the (mutable) vector of TestInfos in this TestCase.
+  std::vector<TestInfo*>& test_info_list() { return test_info_list_; }
+
+  // Gets the (immutable) vector of TestInfos in this TestCase.
+  const std::vector<TestInfo*>& test_info_list() const {
+    return test_info_list_;
+  }
+
+  // Returns the i-th test among all the tests. i can range from 0 to
+  // total_test_count() - 1. If i is not in that range, returns NULL.
+  TestInfo* GetMutableTestInfo(int i);
+
+  // Sets the should_run member.
+  void set_should_run(bool should) { should_run_ = should; }
+
+  // Adds a TestInfo to this test case.  Will delete the TestInfo upon
+  // destruction of the TestCase object.
+  void AddTestInfo(TestInfo * test_info);
+
+  // Clears the results of all tests in this test case.
+  void ClearResult();
+
+  // Clears the results of all tests in the given test case.
+  static void ClearTestCaseResult(TestCase* test_case) {
+    test_case->ClearResult();
+  }
+
+  // Runs every test in this TestCase.
+  void Run();
+
+  // Runs SetUpTestCase() for this TestCase.  This wrapper is needed
+  // for catching exceptions thrown from SetUpTestCase().
+  void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+  // Runs TearDownTestCase() for this TestCase.  This wrapper is
+  // needed for catching exceptions thrown from TearDownTestCase().
+  void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
+  // Returns true iff test passed.
+  static bool TestPassed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Passed();
+  }
+
+  // Returns true iff test failed.
+  static bool TestFailed(const TestInfo* test_info) {
+    return test_info->should_run() && test_info->result()->Failed();
+  }
+
+  // Returns true iff the test is disabled and will be reported in the XML
+  // report.
+  static bool TestReportableDisabled(const TestInfo* test_info) {
+    return test_info->is_reportable() && test_info->is_disabled_;
+  }
+
+  // Returns true iff test is disabled.
+  static bool TestDisabled(const TestInfo* test_info) {
+    return test_info->is_disabled_;
+  }
+
+  // Returns true iff this test will appear in the XML report.
+  static bool TestReportable(const TestInfo* test_info) {
+    return test_info->is_reportable();
+  }
+
+  // Returns true if the given test should run.
+  static bool ShouldRunTest(const TestInfo* test_info) {
+    return test_info->should_run();
+  }
+
+  // Shuffles the tests in this test case.
+  void ShuffleTests(internal::Random* random);
+
+  // Restores the test order to before the first shuffle.
+  void UnshuffleTests();
+
+  // Name of the test case.
+  std::string name_;
+  // Name of the parameter type, or NULL if this is not a typed or a
+  // type-parameterized test.
+  const internal::scoped_ptr<const ::std::string> type_param_;
+  // The vector of TestInfos in their original order.  It owns the
+  // elements in the vector.
+  std::vector<TestInfo*> test_info_list_;
+  // Provides a level of indirection for the test list to allow easy
+  // shuffling and restoring the test order.  The i-th element in this
+  // vector is the index of the i-th test in the shuffled test list.
+  std::vector<int> test_indices_;
+  // Pointer to the function that sets up the test case.
+  Test::SetUpTestCaseFunc set_up_tc_;
+  // Pointer to the function that tears down the test case.
+  Test::TearDownTestCaseFunc tear_down_tc_;
+  // True iff any test in this test case should run.
+  bool should_run_;
+  // Elapsed time, in milliseconds.
+  TimeInMillis elapsed_time_;
+  // Holds test properties recorded during execution of SetUpTestCase and
+  // TearDownTestCase.
+  TestResult ad_hoc_test_result_;
+
+  // We disallow copying TestCases.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestCase);
+};
+
+// An Environment object is capable of setting up and tearing down an
+// environment.  The user should subclass this to define his own
+// environment(s).
+//
+// An Environment object does the set-up and tear-down in virtual
+// methods SetUp() and TearDown() instead of the constructor and the
+// destructor, as:
+//
+//   1. You cannot safely throw from a destructor.  This is a problem
+//      as in some cases Google Test is used where exceptions are enabled, and
+//      we may want to implement ASSERT_* using exceptions where they are
+//      available.
+//   2. You cannot use ASSERT_* directly in a constructor or
+//      destructor.
+class Environment {
+ public:
+  // The d'tor is virtual as we need to subclass Environment.
+  virtual ~Environment() {}
+
+  // Override this to define how to set up the environment.
+  virtual void SetUp() {}
+
+  // Override this to define how to tear down the environment.
+  virtual void TearDown() {}
+ private:
+  // If you see an error about overriding the following function or
+  // about it being private, you have mis-spelled SetUp() as Setup().
+  struct Setup_should_be_spelled_SetUp {};
+  virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
+};
+
+// The interface for tracing execution of tests. The methods are organized in
+// the order the corresponding events are fired.
+class TestEventListener {
+ public:
+  virtual ~TestEventListener() {}
+
+  // Fired before any test activity starts.
+  virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;
+
+  // Fired before each iteration of tests starts.  There may be more than
+  // one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration
+  // index, starting from 0.
+  virtual void OnTestIterationStart(const UnitTest& unit_test,
+                                    int iteration) = 0;
+
+  // Fired before environment set-up for each iteration of tests starts.
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment set-up for each iteration of tests ends.
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;
+
+  // Fired before the test case starts.
+  virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+  // Fired before the test starts.
+  virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+  // Fired after a failed assertion or a SUCCEED() invocation.
+  virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
+
+  // Fired after the test ends.
+  virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+  // Fired after the test case ends.
+  virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+  // Fired before environment tear-down for each iteration of tests starts.
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;
+
+  // Fired after environment tear-down for each iteration of tests ends.
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;
+
+  // Fired after each iteration of tests finishes.
+  virtual void OnTestIterationEnd(const UnitTest& unit_test,
+                                  int iteration) = 0;
+
+  // Fired after all test activities have ended.
+  virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.  For
+// comments about each method please see the definition of TestEventListener
+// above.
+class EmptyTestEventListener : public TestEventListener {
+ public:
+  virtual void OnTestProgramStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationStart(const UnitTest& /*unit_test*/,
+                                    int /*iteration*/) {}
+  virtual void OnEnvironmentsSetUpStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsSetUpEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+  virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+  virtual void OnTestPartResult(const TestPartResult& /*test_part_result*/) {}
+  virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+  virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
+  virtual void OnEnvironmentsTearDownStart(const UnitTest& /*unit_test*/) {}
+  virtual void OnEnvironmentsTearDownEnd(const UnitTest& /*unit_test*/) {}
+  virtual void OnTestIterationEnd(const UnitTest& /*unit_test*/,
+                                  int /*iteration*/) {}
+  virtual void OnTestProgramEnd(const UnitTest& /*unit_test*/) {}
+};
+
+// TestEventListeners lets users add listeners to track events in Google Test.
+class GTEST_API_ TestEventListeners {
+ public:
+  TestEventListeners();
+  ~TestEventListeners();
+
+  // Appends an event listener to the end of the list. Google Test assumes
+  // the ownership of the listener (i.e. it will delete the listener when
+  // the test program finishes).
+  void Append(TestEventListener* listener);
+
+  // Removes the given event listener from the list and returns it.  It then
+  // becomes the caller's responsibility to delete the listener. Returns
+  // NULL if the listener is not found in the list.
+  TestEventListener* Release(TestEventListener* listener);
+
+  // Returns the standard listener responsible for the default console
+  // output.  Can be removed from the listeners list to shut down default
+  // console output.  Note that removing this object from the listener list
+  // with Release transfers its ownership to the caller and makes this
+  // function return NULL the next time.
+  TestEventListener* default_result_printer() const {
+    return default_result_printer_;
+  }
+
+  // Returns the standard listener responsible for the default XML output
+  // controlled by the --gtest_output=xml flag.  Can be removed from the
+  // listeners list by users who want to shut down the default XML output
+  // controlled by this flag and substitute it with custom one.  Note that
+  // removing this object from the listener list with Release transfers its
+  // ownership to the caller and makes this function return NULL the next
+  // time.
+  TestEventListener* default_xml_generator() const {
+    return default_xml_generator_;
+  }
+
+ private:
+  friend class TestCase;
+  friend class TestInfo;
+  friend class internal::DefaultGlobalTestPartResultReporter;
+  friend class internal::NoExecDeathTest;
+  friend class internal::TestEventListenersAccessor;
+  friend class internal::UnitTestImpl;
+
+  // Returns repeater that broadcasts the TestEventListener events to all
+  // subscribers.
+  TestEventListener* repeater();
+
+  // Sets the default_result_printer attribute to the provided listener.
+  // The listener is also added to the listener list and previous
+  // default_result_printer is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultResultPrinter(TestEventListener* listener);
+
+  // Sets the default_xml_generator attribute to the provided listener.  The
+  // listener is also added to the listener list and previous
+  // default_xml_generator is removed from it and deleted. The listener can
+  // also be NULL in which case it will not be added to the list. Does
+  // nothing if the previous and the current listener objects are the same.
+  void SetDefaultXmlGenerator(TestEventListener* listener);
+
+  // Controls whether events will be forwarded by the repeater to the
+  // listeners in the list.
+  bool EventForwardingEnabled() const;
+  void SuppressEventForwarding();
+
+  // The actual list of listeners.
+  internal::TestEventRepeater* repeater_;
+  // Listener responsible for the standard result output.
+  TestEventListener* default_result_printer_;
+  // Listener responsible for the creation of the XML output file.
+  TestEventListener* default_xml_generator_;
+
+  // We disallow copying TestEventListeners.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(TestEventListeners);
+};
+
+// A UnitTest consists of a vector of TestCases.
+//
+// This is a singleton class.  The only instance of UnitTest is
+// created when UnitTest::GetInstance() is first called.  This
+// instance is never deleted.
+//
+// UnitTest is not copyable.
+//
+// This class is thread-safe as long as the methods are called
+// according to their specification.
+class GTEST_API_ UnitTest {
+ public:
+  // Gets the singleton UnitTest object.  The first time this method
+  // is called, a UnitTest object is constructed and returned.
+  // Consecutive calls will return the same object.
+  static UnitTest* GetInstance();
+
+  // Runs all tests in this UnitTest object and prints the result.
+  // Returns 0 if successful, or 1 otherwise.
+  //
+  // This method can only be called from the main thread.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  int Run() GTEST_MUST_USE_RESULT_;
+
+  // Returns the working directory when the first TEST() or TEST_F()
+  // was executed.  The UnitTest object owns the string.
+  const char* original_working_dir() const;
+
+  // Returns the TestCase object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestCase* current_test_case() const
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Returns the TestInfo object for the test that's currently running,
+  // or NULL if no test is running.
+  const TestInfo* current_test_info() const
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Returns the random seed used at the start of the current test run.
+  int random_seed() const;
+
+#if GTEST_HAS_PARAM_TEST
+  // Returns the ParameterizedTestCaseRegistry object used to keep track of
+  // value-parameterized tests and instantiate and register them.
+  //
+  // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+  internal::ParameterizedTestCaseRegistry& parameterized_test_registry()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+#endif  // GTEST_HAS_PARAM_TEST
+
+  // Gets the number of successful test cases.
+  int successful_test_case_count() const;
+
+  // Gets the number of failed test cases.
+  int failed_test_case_count() const;
+
+  // Gets the number of all test cases.
+  int total_test_case_count() const;
+
+  // Gets the number of all test cases that contain at least one test
+  // that should run.
+  int test_case_to_run_count() const;
+
+  // Gets the number of successful tests.
+  int successful_test_count() const;
+
+  // Gets the number of failed tests.
+  int failed_test_count() const;
+
+  // Gets the number of disabled tests that will be reported in the XML report.
+  int reportable_disabled_test_count() const;
+
+  // Gets the number of disabled tests.
+  int disabled_test_count() const;
+
+  // Gets the number of tests to be printed in the XML report.
+  int reportable_test_count() const;
+
+  // Gets the number of all tests.
+  int total_test_count() const;
+
+  // Gets the number of tests that should run.
+  int test_to_run_count() const;
+
+  // Gets the time of the test program start, in ms from the start of the
+  // UNIX epoch.
+  TimeInMillis start_timestamp() const;
+
+  // Gets the elapsed time, in milliseconds.
+  TimeInMillis elapsed_time() const;
+
+  // Returns true iff the unit test passed (i.e. all test cases passed).
+  bool Passed() const;
+
+  // Returns true iff the unit test failed (i.e. some test case failed
+  // or something outside of all tests failed).
+  bool Failed() const;
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  const TestCase* GetTestCase(int i) const;
+
+  // Returns the TestResult containing information on test failures and
+  // properties logged outside of individual test cases.
+  const TestResult& ad_hoc_test_result() const;
+
+  // Returns the list of event listeners that can be used to track events
+  // inside Google Test.
+  TestEventListeners& listeners();
+
+ private:
+  // Registers and returns a global test environment.  When a test
+  // program is run, all global test environments will be set-up in
+  // the order they were registered.  After all tests in the program
+  // have finished, all global test environments will be torn-down in
+  // the *reverse* order they were registered.
+  //
+  // The UnitTest object takes ownership of the given environment.
+  //
+  // This method can only be called from the main thread.
+  Environment* AddEnvironment(Environment* env);
+
+  // Adds a TestPartResult to the current TestResult object.  All
+  // Google Test assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc)
+  // eventually call this to report their results.  The user code
+  // should use the assertion macros instead of calling this directly.
+  void AddTestPartResult(TestPartResult::Type result_type,
+                         const char* file_name,
+                         int line_number,
+                         const std::string& message,
+                         const std::string& os_stack_trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Adds a TestProperty to the current TestResult object when invoked from
+  // inside a test, to current TestCase's ad_hoc_test_result_ when invoked
+  // from SetUpTestCase or TearDownTestCase, or to the global property set
+  // when invoked elsewhere.  If the result already contains a property with
+  // the same key, the value will be updated.
+  void RecordProperty(const std::string& key, const std::string& value);
+
+  // Gets the i-th test case among all the test cases. i can range from 0 to
+  // total_test_case_count() - 1. If i is not in that range, returns NULL.
+  TestCase* GetMutableTestCase(int i);
+
+  // Accessors for the implementation object.
+  internal::UnitTestImpl* impl() { return impl_; }
+  const internal::UnitTestImpl* impl() const { return impl_; }
+
+  // These classes and funcions are friends as they need to access private
+  // members of UnitTest.
+  friend class Test;
+  friend class internal::AssertHelper;
+  friend class internal::ScopedTrace;
+  friend class internal::StreamingListenerTest;
+  friend class internal::UnitTestRecordPropertyTestHelper;
+  friend Environment* AddGlobalTestEnvironment(Environment* env);
+  friend internal::UnitTestImpl* internal::GetUnitTestImpl();
+  friend void internal::ReportFailureInUnknownLocation(
+      TestPartResult::Type result_type,
+      const std::string& message);
+
+  // Creates an empty UnitTest.
+  UnitTest();
+
+  // D'tor
+  virtual ~UnitTest();
+
+  // Pushes a trace defined by SCOPED_TRACE() on to the per-thread
+  // Google Test trace stack.
+  void PushGTestTrace(const internal::TraceInfo& trace)
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Pops a trace from the per-thread Google Test trace stack.
+  void PopGTestTrace()
+      GTEST_LOCK_EXCLUDED_(mutex_);
+
+  // Protects mutable state in *impl_.  This is mutable as some const
+  // methods need to lock it too.
+  mutable internal::Mutex mutex_;
+
+  // Opaque implementation object.  This field is never changed once
+  // the object is constructed.  We don't mark it as const here, as
+  // doing so will cause a warning in the constructor of UnitTest.
+  // Mutable state in *impl_ is protected by mutex_.
+  internal::UnitTestImpl* impl_;
+
+  // We disallow copying UnitTest.
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTest);
+};
+
+// A convenient wrapper for adding an environment for the test
+// program.
+//
+// You should call this before RUN_ALL_TESTS() is called, probably in
+// main().  If you use gtest_main, you need to call this before main()
+// starts for it to take effect.  For example, you can define a global
+// variable like this:
+//
+//   testing::Environment* const foo_env =
+//       testing::AddGlobalTestEnvironment(new FooEnvironment);
+//
+// However, we strongly recommend you to write your own main() and
+// call AddGlobalTestEnvironment() there, as relying on initialization
+// of global variables makes the code harder to read and may cause
+// problems when you register multiple environments from different
+// translation units and the environments have dependencies among them
+// (remember that the compiler doesn't guarantee the order in which
+// global variables from different translation units are initialized).
+inline Environment* AddGlobalTestEnvironment(Environment* env) {
+  return UnitTest::GetInstance()->AddEnvironment(env);
+}
+
+// Initializes Google Test.  This must be called before calling
+// RUN_ALL_TESTS().  In particular, it parses a command line for the
+// flags that Google Test recognizes.  Whenever a Google Test flag is
+// seen, it is removed from argv, and *argc is decremented.
+//
+// No value is returned.  Instead, the Google Test flag variables are
+// updated.
+//
+// Calling the function for the second time has no user-visible effect.
+GTEST_API_ void InitGoogleTest(int* argc, char** argv);
+
+// This overloaded version can be used in Windows programs compiled in
+// UNICODE mode.
+GTEST_API_ void InitGoogleTest(int* argc, wchar_t** argv);
+
+namespace internal {
+
+// FormatForComparison<ToPrint, OtherOperand>::Format(value) formats a
+// value of type ToPrint that is an operand of a comparison assertion
+// (e.g. ASSERT_EQ).  OtherOperand is the type of the other operand in
+// the comparison, and is used to help determine the best way to
+// format the value.  In particular, when the value is a C string
+// (char pointer) and the other operand is an STL string object, we
+// want to format the C string as a string, since we know it is
+// compared by value with the string object.  If the value is a char
+// pointer but the other operand is not an STL string object, we don't
+// know whether the pointer is supposed to point to a NUL-terminated
+// string, and thus want to print it as a pointer to be safe.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// The default case.
+template <typename ToPrint, typename OtherOperand>
+class FormatForComparison {
+ public:
+  static ::std::string Format(const ToPrint& value) {
+    return ::testing::PrintToString(value);
+  }
+};
+
+// Array.
+template <typename ToPrint, size_t N, typename OtherOperand>
+class FormatForComparison<ToPrint[N], OtherOperand> {
+ public:
+  static ::std::string Format(const ToPrint* value) {
+    return FormatForComparison<const ToPrint*, OtherOperand>::Format(value);
+  }
+};
+
+// By default, print C string as pointers to be safe, as we don't know
+// whether they actually point to a NUL-terminated string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(CharType)                \
+  template <typename OtherOperand>                                      \
+  class FormatForComparison<CharType*, OtherOperand> {                  \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(static_cast<const void*>(value)); \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const char);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(wchar_t);
+GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_(const wchar_t);
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_POINTER_
+
+// If a C string is compared with an STL string object, we know it's meant
+// to point to a NUL-terminated string, and thus can print it as a string.
+
+#define GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(CharType, OtherStringType) \
+  template <>                                                           \
+  class FormatForComparison<CharType*, OtherStringType> {               \
+   public:                                                              \
+    static ::std::string Format(CharType* value) {                      \
+      return ::testing::PrintToString(value);                           \
+    }                                                                   \
+  }
+
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::std::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::std::string);
+
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(char, ::string);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const char, ::string);
+#endif
+
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::wstring);
+#endif
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(wchar_t, ::std::wstring);
+GTEST_IMPL_FORMAT_C_STRING_AS_STRING_(const wchar_t, ::std::wstring);
+#endif
+
+#undef GTEST_IMPL_FORMAT_C_STRING_AS_STRING_
+
+// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
+// operand to be used in a failure message.  The type (but not value)
+// of the other operand may affect the format.  This allows us to
+// print a char* as a raw pointer when it is compared against another
+// char* or void*, and print it as a C string when it is compared
+// against an std::string object, for example.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename T1, typename T2>
+std::string FormatForComparisonFailureMessage(
+    const T1& value, const T2& /* other_operand */) {
+  return FormatForComparison<T1, T2>::Format(value);
+}
+
+// The helper function for {ASSERT|EXPECT}_EQ.
+template <typename T1, typename T2>
+AssertionResult CmpHelperEQ(const char* expected_expression,
+                            const char* actual_expression,
+                            const T1& expected,
+                            const T2& actual) {
+#ifdef _MSC_VER
+# pragma warning(push)          // Saves the current warning state.
+# pragma warning(disable:4389)  // Temporarily disables warning on
+                                // signed/unsigned mismatch.
+#endif
+
+  if (expected == actual) {
+    return AssertionSuccess();
+  }
+
+#ifdef _MSC_VER
+# pragma warning(pop)          // Restores the warning state.
+#endif
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   FormatForComparisonFailureMessage(expected, actual),
+                   FormatForComparisonFailureMessage(actual, expected),
+                   false);
+}
+
+// With this overloaded version, we allow anonymous enums to be used
+// in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous enums
+// can be implicitly cast to BiggestInt.
+GTEST_API_ AssertionResult CmpHelperEQ(const char* expected_expression,
+                                       const char* actual_expression,
+                                       BiggestInt expected,
+                                       BiggestInt actual);
+
+// The helper class for {ASSERT|EXPECT}_EQ.  The template argument
+// lhs_is_null_literal is true iff the first argument to ASSERT_EQ()
+// is a null pointer literal.  The following default implementation is
+// for lhs_is_null_literal being false.
+template <bool lhs_is_null_literal>
+class EqHelper {
+ public:
+  // This templatized version is for the general case.
+  template <typename T1, typename T2>
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 const T1& expected,
+                                 const T2& actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // With this overloaded version, we allow anonymous enums to be used
+  // in {ASSERT|EXPECT}_EQ when compiled with gcc 4, as anonymous
+  // enums can be implicitly cast to BiggestInt.
+  //
+  // Even though its body looks the same as the above version, we
+  // cannot merge the two, as it will make anonymous enums unhappy.
+  static AssertionResult Compare(const char* expected_expression,
+                                 const char* actual_expression,
+                                 BiggestInt expected,
+                                 BiggestInt actual) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+};
+
+// This specialization is used when the first argument to ASSERT_EQ()
+// is a null pointer literal, like NULL, false, or 0.
+template <>
+class EqHelper<true> {
+ public:
+  // We define two overloaded versions of Compare().  The first
+  // version will be picked when the second argument to ASSERT_EQ() is
+  // NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
+  // EXPECT_EQ(false, a_bool).
+  template <typename T1, typename T2>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      const T1& expected,
+      const T2& actual,
+      // The following line prevents this overload from being considered if T2
+      // is not a pointer type.  We need this because ASSERT_EQ(NULL, my_ptr)
+      // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+      // to match the Secret* in the other overload, which would otherwise make
+      // this template match better.
+      typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
+    return CmpHelperEQ(expected_expression, actual_expression, expected,
+                       actual);
+  }
+
+  // This version will be picked when the second argument to ASSERT_EQ() is a
+  // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+  template <typename T>
+  static AssertionResult Compare(
+      const char* expected_expression,
+      const char* actual_expression,
+      // We used to have a second template parameter instead of Secret*.  That
+      // template parameter would deduce to 'long', making this a better match
+      // than the first overload even without the first overload's EnableIf.
+      // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+      // non-pointer argument" (even a deduced integral argument), so the old
+      // implementation caused warnings in user code.
+      Secret* /* expected (NULL) */,
+      T* actual) {
+    // We already know that 'expected' is a null pointer.
+    return CmpHelperEQ(expected_expression, actual_expression,
+                       static_cast<T*>(NULL), actual);
+  }
+};
+
+// A macro for implementing the helper functions needed to implement
+// ASSERT_?? and EXPECT_??.  It is here just to avoid copy-and-paste
+// of similar code.
+//
+// For each templatized helper function, we also define an overloaded
+// version for BiggestInt in order to reduce code bloat and allow
+// anonymous enums to be used with {ASSERT|EXPECT}_?? when compiled
+// with gcc 4.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+#define GTEST_IMPL_CMP_HELPER_(op_name, op)\
+template <typename T1, typename T2>\
+AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
+                                   const T1& val1, const T2& val2) {\
+  if (val1 op val2) {\
+    return AssertionSuccess();\
+  } else {\
+    return AssertionFailure() \
+        << "Expected: (" << expr1 << ") " #op " (" << expr2\
+        << "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
+        << " vs " << FormatForComparisonFailureMessage(val2, val1);\
+  }\
+}\
+GTEST_API_ AssertionResult CmpHelper##op_name(\
+    const char* expr1, const char* expr2, BiggestInt val1, BiggestInt val2)
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+
+// Implements the helper function for {ASSERT|EXPECT}_NE
+GTEST_IMPL_CMP_HELPER_(NE, !=);
+// Implements the helper function for {ASSERT|EXPECT}_LE
+GTEST_IMPL_CMP_HELPER_(LE, <=);
+// Implements the helper function for {ASSERT|EXPECT}_LT
+GTEST_IMPL_CMP_HELPER_(LT, <);
+// Implements the helper function for {ASSERT|EXPECT}_GE
+GTEST_IMPL_CMP_HELPER_(GE, >=);
+// Implements the helper function for {ASSERT|EXPECT}_GT
+GTEST_IMPL_CMP_HELPER_(GT, >);
+
+#undef GTEST_IMPL_CMP_HELPER_
+
+// The helper function for {ASSERT|EXPECT}_STREQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const char* expected,
+                                          const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRCASEEQ.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASEEQ(const char* expected_expression,
+                                              const char* actual_expression,
+                                              const char* expected,
+                                              const char* actual);
+
+// The helper function for {ASSERT|EXPECT}_STRNE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const char* s1,
+                                          const char* s2);
+
+// The helper function for {ASSERT|EXPECT}_STRCASENE.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRCASENE(const char* s1_expression,
+                                              const char* s2_expression,
+                                              const char* s1,
+                                              const char* s2);
+
+
+// Helper function for *_STREQ on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTREQ(const char* expected_expression,
+                                          const char* actual_expression,
+                                          const wchar_t* expected,
+                                          const wchar_t* actual);
+
+// Helper function for *_STRNE on wide strings.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult CmpHelperSTRNE(const char* s1_expression,
+                                          const char* s2_expression,
+                                          const wchar_t* s1,
+                                          const wchar_t* s2);
+
+}  // namespace internal
+
+// IsSubstring() and IsNotSubstring() are intended to be used as the
+// first argument to {EXPECT,ASSERT}_PRED_FORMAT2(), not by
+// themselves.  They check whether needle is a substring of haystack
+// (NULL is considered a substring of itself only), and return an
+// appropriate error message when they fail.
+//
+// The {needle,haystack}_expr arguments are the stringified
+// expressions that generated the two real arguments.
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const char* needle, const char* haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const wchar_t* needle, const wchar_t* haystack);
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::string& needle, const ::std::string& haystack);
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ AssertionResult IsSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+GTEST_API_ AssertionResult IsNotSubstring(
+    const char* needle_expr, const char* haystack_expr,
+    const ::std::wstring& needle, const ::std::wstring& haystack);
+#endif  // GTEST_HAS_STD_WSTRING
+
+namespace internal {
+
+// Helper template function for comparing floating-points.
+//
+// Template parameter:
+//
+//   RawType: the raw floating-point type (either float or double)
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+template <typename RawType>
+AssertionResult CmpHelperFloatingPointEQ(const char* expected_expression,
+                                         const char* actual_expression,
+                                         RawType expected,
+                                         RawType actual) {
+  const FloatingPoint<RawType> lhs(expected), rhs(actual);
+
+  if (lhs.AlmostEquals(rhs)) {
+    return AssertionSuccess();
+  }
+
+  ::std::stringstream expected_ss;
+  expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+              << expected;
+
+  ::std::stringstream actual_ss;
+  actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
+            << actual;
+
+  return EqFailure(expected_expression,
+                   actual_expression,
+                   StringStreamToString(&expected_ss),
+                   StringStreamToString(&actual_ss),
+                   false);
+}
+
+// Helper function for implementing ASSERT_NEAR.
+//
+// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
+GTEST_API_ AssertionResult DoubleNearPredFormat(const char* expr1,
+                                                const char* expr2,
+                                                const char* abs_error_expr,
+                                                double val1,
+                                                double val2,
+                                                double abs_error);
+
+// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
+// A class that enables one to stream messages to assertion macros
+class GTEST_API_ AssertHelper {
+ public:
+  // Constructor.
+  AssertHelper(TestPartResult::Type type,
+               const char* file,
+               int line,
+               const char* message);
+  ~AssertHelper();
+
+  // Message assignment is a semantic trick to enable assertion
+  // streaming; see the GTEST_MESSAGE_ macro below.
+  void operator=(const Message& message) const;
+
+ private:
+  // We put our data in a struct so that the size of the AssertHelper class can
+  // be as small as possible.  This is important because gcc is incapable of
+  // re-using stack space even for temporary variables, so every EXPECT_EQ
+  // reserves stack space for another AssertHelper.
+  struct AssertHelperData {
+    AssertHelperData(TestPartResult::Type t,
+                     const char* srcfile,
+                     int line_num,
+                     const char* msg)
+        : type(t), file(srcfile), line(line_num), message(msg) { }
+
+    TestPartResult::Type const type;
+    const char* const file;
+    int const line;
+    std::string const message;
+
+   private:
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+  };
+
+  AssertHelperData* const data_;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
+};
+
+}  // namespace internal
+
+#if GTEST_HAS_PARAM_TEST
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
+//
+// This interface has support for accessing the test parameter value via
+// the GetParam() method.
+//
+// Use it with one of the parameter generator defining functions, like Range(),
+// Values(), ValuesIn(), Bool(), and Combine().
+//
+// class FooTest : public ::testing::TestWithParam<int> {
+//  protected:
+//   FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual ~FooTest() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void SetUp() {
+//     // Can use GetParam() here.
+//   }
+//   virtual void TearDown {
+//     // Can use GetParam() here.
+//   }
+// };
+// TEST_P(FooTest, DoesBar) {
+//   // Can use GetParam() method here.
+//   Foo foo;
+//   ASSERT_TRUE(foo.DoesBar(GetParam()));
+// }
+// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
+
+template <typename T>
+class WithParamInterface {
+ public:
+  typedef T ParamType;
+  virtual ~WithParamInterface() {}
+
+  // The current parameter value. Is also available in the test fixture's
+  // constructor. This member function is non-static, even though it only
+  // references static data, to reduce the opportunity for incorrect uses
+  // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+  // uses a fixture whose parameter type is int.
+  const ParamType& GetParam() const {
+    GTEST_CHECK_(parameter_ != NULL)
+        << "GetParam() can only be called inside a value-parameterized test "
+        << "-- did you intend to write TEST_P instead of TEST_F?";
+    return *parameter_;
+  }
+
+ private:
+  // Sets parameter value. The caller is responsible for making sure the value
+  // remains alive and unchanged throughout the current test.
+  static void SetParam(const ParamType* parameter) {
+    parameter_ = parameter;
+  }
+
+  // Static value used for accessing parameter during a test lifetime.
+  static const ParamType* parameter_;
+
+  // TestClass must be a subclass of WithParamInterface<T> and Test.
+  template <class TestClass> friend class internal::ParameterizedTestFactory;
+};
+
+template <typename T>
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
+
+#endif  // GTEST_HAS_PARAM_TEST
+
+// Macros for indicating success/failure in test code.
+
+// ADD_FAILURE unconditionally adds a failure to the current test.
+// SUCCEED generates a success - it doesn't automatically make the
+// current test successful, as a test is only successful when it has
+// no failure.
+//
+// EXPECT_* verifies that a certain condition is satisfied.  If not,
+// it behaves like ADD_FAILURE.  In particular:
+//
+//   EXPECT_TRUE  verifies that a Boolean condition is true.
+//   EXPECT_FALSE verifies that a Boolean condition is false.
+//
+// FAIL and ASSERT_* are similar to ADD_FAILURE and EXPECT_*, except
+// that they will also abort the current function on failure.  People
+// usually want the fail-fast behavior of FAIL and ASSERT_*, but those
+// writing data-driven tests often find themselves using ADD_FAILURE
+// and EXPECT_* more.
+
+// Generates a nonfatal failure with a generic message.
+#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+  GTEST_MESSAGE_AT_(file, line, "Failed", \
+                    ::testing::TestPartResult::kNonFatalFailure)
+
+// Generates a fatal failure with a generic message.
+#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
+
+// Define this macro to 1 to omit the definition of FAIL(), which is a
+// generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_FAIL
+# define FAIL() GTEST_FAIL()
+#endif
+
+// Generates a success with a generic message.
+#define GTEST_SUCCEED() GTEST_SUCCESS_("Succeeded")
+
+// Define this macro to 1 to omit the definition of SUCCEED(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_SUCCEED
+# define SUCCEED() GTEST_SUCCEED()
+#endif
+
+// Macros for testing exceptions.
+//
+//    * {ASSERT|EXPECT}_THROW(statement, expected_exception):
+//         Tests that the statement throws the expected exception.
+//    * {ASSERT|EXPECT}_NO_THROW(statement):
+//         Tests that the statement doesn't throw any exception.
+//    * {ASSERT|EXPECT}_ANY_THROW(statement):
+//         Tests that the statement throws an exception.
+
+#define EXPECT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_THROW(statement, expected_exception) \
+  GTEST_TEST_THROW_(statement, expected_exception, GTEST_FATAL_FAILURE_)
+#define ASSERT_NO_THROW(statement) \
+  GTEST_TEST_NO_THROW_(statement, GTEST_FATAL_FAILURE_)
+#define ASSERT_ANY_THROW(statement) \
+  GTEST_TEST_ANY_THROW_(statement, GTEST_FATAL_FAILURE_)
+
+// Boolean assertions. Condition can be either a Boolean expression or an
+// AssertionResult. For more information on how to use AssertionResult with
+// these macros see comments on that class.
+#define EXPECT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_NONFATAL_FAILURE_)
+#define EXPECT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_NONFATAL_FAILURE_)
+#define ASSERT_TRUE(condition) \
+  GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \
+                      GTEST_FATAL_FAILURE_)
+#define ASSERT_FALSE(condition) \
+  GTEST_TEST_BOOLEAN_(!(condition), #condition, true, false, \
+                      GTEST_FATAL_FAILURE_)
+
+// Includes the auto-generated header that implements a family of
+// generic predicate assertion macros.
+// Copyright 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * 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.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// 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.
+
+// This file is AUTOMATICALLY GENERATED on 10/31/2011 by command
+// 'gen_gtest_pred_impl.py 5'.  DO NOT EDIT BY HAND!
+//
+// Implements a family of generic predicate assertion macros.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Makes sure this header is not included before gtest.h.
+#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
+# error Do not include gtest_pred_impl.h directly.  Include gtest.h instead.
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
+
+// This header implements a family of generic predicate assertion
+// macros:
+//
+//   ASSERT_PRED_FORMAT1(pred_format, v1)
+//   ASSERT_PRED_FORMAT2(pred_format, v1, v2)
+//   ...
+//
+// where pred_format is a function or functor that takes n (in the
+// case of ASSERT_PRED_FORMATn) values and their source expression
+// text, and returns a testing::AssertionResult.  See the definition
+// of ASSERT_EQ in gtest.h for an example.
+//
+// If you don't care about formatting, you can use the more
+// restrictive version:
+//
+//   ASSERT_PRED1(pred, v1)
+//   ASSERT_PRED2(pred, v1, v2)
+//   ...
+//
+// where pred is an n-ary function or functor that returns bool,
+// and the values v1, v2, ..., must support the << operator for
+// streaming to std::ostream.
+//
+// We also define the EXPECT_* variations.
+//
+// For now we only support predicates whose arity is at most 5.
+// Please email googletestframework@googlegroups.com if you need
+// support for higher arities.
+
+// GTEST_ASSERT_ is the basic statement to which all of the assertions
+// in this file reduce.  Don't use this in your code.
+
+#define GTEST_ASSERT_(expression, on_failure) \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+  if (const ::testing::AssertionResult gtest_ar = (expression)) \
+    ; \
+  else \
+    on_failure(gtest_ar.failure_message())
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1>
+AssertionResult AssertPred1Helper(const char* pred_text,
+                                  const char* e1,
+                                  Pred pred,
+                                  const T1& v1) {
+  if (pred(v1)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT1_(pred_format, v1, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, v1), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED1.  Don't use
+// this in your code.
+#define GTEST_PRED1_(pred, v1, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred1Helper(#pred, \
+                                             #v1, \
+                                             pred, \
+                                             v1), on_failure)
+
+// Unary predicate assertion macros.
+#define EXPECT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT1(pred_format, v1) \
+  GTEST_PRED_FORMAT1_(pred_format, v1, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED1(pred, v1) \
+  GTEST_PRED1_(pred, v1, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2>
+AssertionResult AssertPred2Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2) {
+  if (pred(v1, v2)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED2.  Don't use
+// this in your code.
+#define GTEST_PRED2_(pred, v1, v2, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred2Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             pred, \
+                                             v1, \
+                                             v2), on_failure)
+
+// Binary predicate assertion macros.
+#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT2(pred_format, v1, v2) \
+  GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED2(pred, v1, v2) \
+  GTEST_PRED2_(pred, v1, v2, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3>
+AssertionResult AssertPred3Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3) {
+  if (pred(v1, v2, v3)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, v1, v2, v3), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED3.  Don't use
+// this in your code.
+#define GTEST_PRED3_(pred, v1, v2, v3, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred3Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3), on_failure)
+
+// Ternary predicate assertion macros.
+#define EXPECT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT3(pred_format, v1, v2, v3) \
+  GTEST_PRED_FORMAT3_(pred_format, v1, v2, v3, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED3(pred, v1, v2, v3) \
+  GTEST_PRED3_(pred, v1, v2, v3, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4>
+AssertionResult AssertPred4Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4) {
+  if (pred(v1, v2, v3, v4)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, v1, v2, v3, v4), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED4.  Don't use
+// this in your code.
+#define GTEST_PRED4_(pred, v1, v2, v3, v4, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred4Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4), on_failure)
+
+// 4-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT4(pred_format, v1, v2, v3, v4) \
+  GTEST_PRED_FORMAT4_(pred_format, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED4(pred, v1, v2, v3, v4) \
+  GTEST_PRED4_(pred, v1, v2, v3, v4, GTEST_FATAL_FAILURE_)
+
+
+
+// Helper function for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+template <typename Pred,
+          typename T1,
+          typename T2,
+          typename T3,
+          typename T4,
+          typename T5>
+AssertionResult AssertPred5Helper(const char* pred_text,
+                                  const char* e1,
+                                  const char* e2,
+                                  const char* e3,
+                                  const char* e4,
+                                  const char* e5,
+                                  Pred pred,
+                                  const T1& v1,
+                                  const T2& v2,
+                                  const T3& v3,
+                                  const T4& v4,
+                                  const T5& v5) {
+  if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
+
+  return AssertionFailure() << pred_text << "("
+                            << e1 << ", "
+                            << e2 << ", "
+                            << e3 << ", "
+                            << e4 << ", "
+                            << e5 << ") evaluates to false, where"
+                            << "\n" << e1 << " evaluates to " << v1
+                            << "\n" << e2 << " evaluates to " << v2
+                            << "\n" << e3 << " evaluates to " << v3
+                            << "\n" << e4 << " evaluates to " << v4
+                            << "\n" << e5 << " evaluates to " << v5;
+}
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
+// Don't use this in your code.
+#define GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(pred_format(#v1, #v2, #v3, #v4, #v5, v1, v2, v3, v4, v5), \
+                on_failure)
+
+// Internal macro for implementing {EXPECT|ASSERT}_PRED5.  Don't use
+// this in your code.
+#define GTEST_PRED5_(pred, v1, v2, v3, v4, v5, on_failure)\
+  GTEST_ASSERT_(::testing::AssertPred5Helper(#pred, \
+                                             #v1, \
+                                             #v2, \
+                                             #v3, \
+                                             #v4, \
+                                             #v5, \
+                                             pred, \
+                                             v1, \
+                                             v2, \
+                                             v3, \
+                                             v4, \
+                                             v5), on_failure)
+
+// 5-ary predicate assertion macros.
+#define EXPECT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define EXPECT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_NONFATAL_FAILURE_)
+#define ASSERT_PRED_FORMAT5(pred_format, v1, v2, v3, v4, v5) \
+  GTEST_PRED_FORMAT5_(pred_format, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+#define ASSERT_PRED5(pred, v1, v2, v3, v4, v5) \
+  GTEST_PRED5_(pred, v1, v2, v3, v4, v5, GTEST_FATAL_FAILURE_)
+
+
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_PRED_IMPL_H_
+
+// Macros for testing equalities and inequalities.
+//
+//    * {ASSERT|EXPECT}_EQ(expected, actual): Tests that expected == actual
+//    * {ASSERT|EXPECT}_NE(v1, v2):           Tests that v1 != v2
+//    * {ASSERT|EXPECT}_LT(v1, v2):           Tests that v1 < v2
+//    * {ASSERT|EXPECT}_LE(v1, v2):           Tests that v1 <= v2
+//    * {ASSERT|EXPECT}_GT(v1, v2):           Tests that v1 > v2
+//    * {ASSERT|EXPECT}_GE(v1, v2):           Tests that v1 >= v2
+//
+// When they are not, Google Test prints both the tested expressions and
+// their actual values.  The values must be compatible built-in types,
+// or you will get a compiler error.  By "compatible" we mean that the
+// values can be compared by the respective operator.
+//
+// Note:
+//
+//   1. It is possible to make a user-defined type work with
+//   {ASSERT|EXPECT}_??(), but that requires overloading the
+//   comparison operators and is thus discouraged by the Google C++
+//   Usage Guide.  Therefore, you are advised to use the
+//   {ASSERT|EXPECT}_TRUE() macro to assert that two objects are
+//   equal.
+//
+//   2. The {ASSERT|EXPECT}_??() macros do pointer comparisons on
+//   pointers (in particular, C strings).  Therefore, if you use it
+//   with two C strings, you are testing how their locations in memory
+//   are related, not how their content is related.  To compare two C
+//   strings by content, use {ASSERT|EXPECT}_STR*().
+//
+//   3. {ASSERT|EXPECT}_EQ(expected, actual) is preferred to
+//   {ASSERT|EXPECT}_TRUE(expected == actual), as the former tells you
+//   what the actual value is when it fails, and similarly for the
+//   other comparisons.
+//
+//   4. Do not depend on the order in which {ASSERT|EXPECT}_??()
+//   evaluate their arguments, which is undefined.
+//
+//   5. These macros evaluate their arguments exactly once.
+//
+// Examples:
+//
+//   EXPECT_NE(5, Foo());
+//   EXPECT_EQ(NULL, a_pointer);
+//   ASSERT_LT(i, array_size);
+//   ASSERT_GT(records.size(), 0) << "There is no record left.";
+
+#define EXPECT_EQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define EXPECT_NE(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperNE, expected, actual)
+#define EXPECT_LE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define EXPECT_LT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define EXPECT_GE(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define EXPECT_GT(val1, val2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+#define GTEST_ASSERT_EQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal:: \
+                      EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
+                      expected, actual)
+#define GTEST_ASSERT_NE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
+#define GTEST_ASSERT_LE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
+#define GTEST_ASSERT_LT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
+#define GTEST_ASSERT_GE(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
+#define GTEST_ASSERT_GT(val1, val2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
+// C-string Comparisons.  All tests treat NULL and any non-NULL string
+// as different.  Two NULLs are equal.
+//
+//    * {ASSERT|EXPECT}_STREQ(s1, s2):     Tests that s1 == s2
+//    * {ASSERT|EXPECT}_STRNE(s1, s2):     Tests that s1 != s2
+//    * {ASSERT|EXPECT}_STRCASEEQ(s1, s2): Tests that s1 == s2, ignoring case
+//    * {ASSERT|EXPECT}_STRCASENE(s1, s2): Tests that s1 != s2, ignoring case
+//
+// For wide or narrow string objects, you can use the
+// {ASSERT|EXPECT}_??() macros.
+//
+// Don't depend on the order in which the arguments are evaluated,
+// which is undefined.
+//
+// These macros evaluate their arguments exactly once.
+
+#define EXPECT_STREQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define EXPECT_STRNE(s1, s2) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define EXPECT_STRCASEEQ(expected, actual) \
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define EXPECT_STRCASENE(s1, s2)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+#define ASSERT_STREQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTREQ, expected, actual)
+#define ASSERT_STRNE(s1, s2) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRNE, s1, s2)
+#define ASSERT_STRCASEEQ(expected, actual) \
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASEEQ, expected, actual)
+#define ASSERT_STRCASENE(s1, s2)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperSTRCASENE, s1, s2)
+
+// Macros for comparing floating-point numbers.
+//
+//    * {ASSERT|EXPECT}_FLOAT_EQ(expected, actual):
+//         Tests that two float values are almost equal.
+//    * {ASSERT|EXPECT}_DOUBLE_EQ(expected, actual):
+//         Tests that two double values are almost equal.
+//    * {ASSERT|EXPECT}_NEAR(v1, v2, abs_error):
+//         Tests that v1 and v2 are within the given distance to each other.
+//
+// Google Test uses ULP-based comparison to automatically pick a default
+// error bound that is appropriate for the operands.  See the
+// FloatingPoint template class in gtest-internal.h if you are
+// interested in the implementation details.
+
+#define EXPECT_FLOAT_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define EXPECT_DOUBLE_EQ(expected, actual)\
+  EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define ASSERT_FLOAT_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<float>, \
+                      expected, actual)
+
+#define ASSERT_DOUBLE_EQ(expected, actual)\
+  ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperFloatingPointEQ<double>, \
+                      expected, actual)
+
+#define EXPECT_NEAR(val1, val2, abs_error)\
+  EXPECT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+#define ASSERT_NEAR(val1, val2, abs_error)\
+  ASSERT_PRED_FORMAT3(::testing::internal::DoubleNearPredFormat, \
+                      val1, val2, abs_error)
+
+// These predicate format functions work on floating-point values, and
+// can be used in {ASSERT|EXPECT}_PRED_FORMAT2*(), e.g.
+//
+//   EXPECT_PRED_FORMAT2(testing::DoubleLE, Foo(), 5.0);
+
+// Asserts that val1 is less than, or almost equal to, val2.  Fails
+// otherwise.  In particular, it fails if either val1 or val2 is NaN.
+GTEST_API_ AssertionResult FloatLE(const char* expr1, const char* expr2,
+                                   float val1, float val2);
+GTEST_API_ AssertionResult DoubleLE(const char* expr1, const char* expr2,
+                                    double val1, double val2);
+
+
+#if GTEST_OS_WINDOWS
+
+// Macros that test for HRESULT failure and success, these are only useful
+// on Windows, and rely on Windows SDK macros and APIs to compile.
+//
+//    * {ASSERT|EXPECT}_HRESULT_{SUCCEEDED|FAILED}(expr)
+//
+// When expr unexpectedly fails or succeeds, Google Test prints the
+// expected result and the actual result with both a human-readable
+// string representation of the error, if available, as well as the
+// hex result code.
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
+
+# define EXPECT_HRESULT_FAILED(expr) \
+    EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+# define ASSERT_HRESULT_FAILED(expr) \
+    ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
+
+#endif  // GTEST_OS_WINDOWS
+
+// Macros that execute statement and check that it doesn't generate new fatal
+// failures in the current thread.
+//
+//   * {ASSERT|EXPECT}_NO_FATAL_FAILURE(statement);
+//
+// Examples:
+//
+//   EXPECT_NO_FATAL_FAILURE(Process());
+//   ASSERT_NO_FATAL_FAILURE(Process()) << "Process() failed";
+//
+#define ASSERT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_FATAL_FAILURE_)
+#define EXPECT_NO_FATAL_FAILURE(statement) \
+    GTEST_TEST_NO_FATAL_FAILURE_(statement, GTEST_NONFATAL_FAILURE_)
+
+// Causes a trace (including the source file path, the current line
+// number, and the given message) to be included in every test failure
+// message generated by code in the current scope.  The effect is
+// undone when the control leaves the current scope.
+//
+// The message argument can be anything streamable to std::ostream.
+//
+// In the implementation, we include the current line number as part
+// of the dummy variable name, thus allowing multiple SCOPED_TRACE()s
+// to appear in the same block - as long as they are on different
+// lines.
+#define SCOPED_TRACE(message) \
+  ::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
+    __FILE__, __LINE__, ::testing::Message() << (message))
+
+// Compile-time assertion for type equality.
+// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
+// the same type.  The value it returns is not interesting.
+//
+// Instead of making StaticAssertTypeEq a class template, we make it a
+// function template that invokes a helper class template.  This
+// prevents a user from misusing StaticAssertTypeEq<T1, T2> by
+// defining objects of that type.
+//
+// CAVEAT:
+//
+// When used inside a method of a class template,
+// StaticAssertTypeEq<T1, T2>() is effective ONLY IF the method is
+// instantiated.  For example, given:
+//
+//   template <typename T> class Foo {
+//    public:
+//     void Bar() { testing::StaticAssertTypeEq<int, T>(); }
+//   };
+//
+// the code:
+//
+//   void Test1() { Foo<bool> foo; }
+//
+// will NOT generate a compiler error, as Foo<bool>::Bar() is never
+// actually instantiated.  Instead, you need:
+//
+//   void Test2() { Foo<bool> foo; foo.Bar(); }
+//
+// to cause a compiler error.
+template <typename T1, typename T2>
+bool StaticAssertTypeEq() {
+  (void)internal::StaticAssertTypeEqHelper<T1, T2>();
+  return true;
+}
+
+// Defines a test.
+//
+// The first parameter is the name of the test case, and the second
+// parameter is the name of the test within the test case.
+//
+// The convention is to end the test case name with "Test".  For
+// example, a test case for the Foo class can be named FooTest.
+//
+// The user should put his test code between braces after using this
+// macro.  Example:
+//
+//   TEST(FooTest, InitializesCorrectly) {
+//     Foo foo;
+//     EXPECT_TRUE(foo.StatusIsOK());
+//   }
+
+// Note that we call GetTestTypeId() instead of GetTypeId<
+// ::testing::Test>() here to get the type ID of testing::Test.  This
+// is to work around a suspected linker bug when using Google Test as
+// a framework on Mac OS X.  The bug causes GetTypeId<
+// ::testing::Test>() to return different values depending on whether
+// the call is from the Google Test framework itself or from user test
+// code.  GetTestTypeId() is guaranteed to always return the same
+// value, as it always calls GetTypeId<>() from the Google Test
+// framework.
+#define GTEST_TEST(test_case_name, test_name)\
+  GTEST_TEST_(test_case_name, test_name, \
+              ::testing::Test, ::testing::internal::GetTestTypeId())
+
+// Define this macro to 1 to omit the definition of TEST(), which
+// is a generic name and clashes with some other libraries.
+#if !GTEST_DONT_DEFINE_TEST
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+#endif
+
+// Defines a test that uses a test fixture.
+//
+// The first parameter is the name of the test fixture class, which
+// also doubles as the test case name.  The second parameter is the
+// name of the test within the test case.
+//
+// A test fixture class must be declared earlier.  The user should put
+// his test code between braces after using this macro.  Example:
+//
+//   class FooTest : public testing::Test {
+//    protected:
+//     virtual void SetUp() { b_.AddElement(3); }
+//
+//     Foo a_;
+//     Foo b_;
+//   };
+//
+//   TEST_F(FooTest, InitializesCorrectly) {
+//     EXPECT_TRUE(a_.StatusIsOK());
+//   }
+//
+//   TEST_F(FooTest, ReturnsElementCountCorrectly) {
+//     EXPECT_EQ(0, a_.size());
+//     EXPECT_EQ(1, b_.size());
+//   }
+
+#define TEST_F(test_fixture, test_name)\
+  GTEST_TEST_(test_fixture, test_name, test_fixture, \
+              ::testing::internal::GetTypeId<test_fixture>())
+
+}  // namespace testing
+
+// Use this function in main() to run all tests.  It returns 0 if all
+// tests are successful, or 1 otherwise.
+//
+// RUN_ALL_TESTS() should be invoked after the command line has been
+// parsed by InitGoogleTest().
+//
+// This function was formerly a macro; thus, it is in the global
+// namespace and has an all-caps name.
+int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
+
+inline int RUN_ALL_TESTS() {
+  return ::testing::UnitTest::GetInstance()->Run();
+}
+
+#endif  // GTEST_INCLUDE_GTEST_GTEST_H_
-- 
GitLab