   }
 };
 
+// saxpy function, which can either be called form host or device
+// The views are passed by value
 template<class View1, class View2, class View3>
 __host__ __device__
 void saxpy(float A, View1 X, View2 Y, View3 Z)

#include <thrust/execution_policy.h>
#include <iostream>

template<class Iterator>
class range_view
{


  saxpy_kernel<<<1, 1>>>(
      2.0, 

      // make a range view of a pair of transform_iterators
      make_range_view(thrust::make_transform_iterator(X.cbegin(), f1()),
                      thrust::make_transform_iterator(X.cend(), f1())),

      // range view of normal_iterators
      make_range_view(Y.begin(), thrust::distance(Y.begin(), Y.end())),

      // range view of naked pointers
      make_range_view(Z.data().get(), 4));
  assert(cudaSuccess == cudaDeviceSynchronize());

  // print values from original device_vector<float> Z 
  // to ensure that range view was mapped to this vector
  for (int i = 0, n = Z.size(); i < n; ++i)
  {
    cout << "z[" << i << "]= " << Z[i] << endl;
