   {
     const uint32_t lane = threadIdx.x % WARPSIZE;
     const uint32_t warp = threadIdx.x / WARPSIZE;
-    const uint32_t blockOffset = 4 * SCAN_WARPS * WARPSIZE * blockIdx.x;
-    const uint32_t threadOffset = blockOffset + 4 * threadIdx.x;
+    const uint32_t threadOffset = 4 * (SCAN_WARPS * WARPSIZE * blockIdx.x + threadIdx.x);
 
     // Fetch
     uint4 a;


namespace {
  

  template<bool inclusive, bool writeSum0, bool writeSum1>
  __global__

  }

  if (N <= std::numeric_limits<uint32_t>::max()) {
    uint32_t blockSize = SCAN_WARPS * WARPSIZE;
    uint32_t n = static_cast<uint32_t>(N);

    if (levels.empty()) {

      if (sum_d == nullptr) {
        scan<false, true, false> <<<1, blockSize, 0, stream>>> (offsets_d,
                                                                offsets_d + N,
                                                                sum_d,
                                                                counts_d,
                                                                n);
      }
      else {
        scan<false, true, true> <<<1, blockSize, 0, stream>>> (offsets_d,
                                                               offsets_d + N,
                                                               sum_d,
                                                               counts_d,
                                                               n);
      }

    }
    else {

      reduce<<<static_cast<uint32_t>(levels[0]), blockSize, 0, stream>>>(scratch_d + offsets[0],
                                                                         counts_d,
                                                                         n);
      for (size_t i = 1; i < levels.size(); i++) {
        reduce<<<static_cast<uint32_t>(levels[i]), blockSize, 0, stream>>>(scratch_d + offsets[i],
                                                                           scratch_d + offsets[i - 1],
                                                                           levels[i - 1]);
      }

      auto l = levels.size() - 1;
      if (sum_d == nullptr) {
        scan<false, true, false><<<1, blockSize, 0, stream>>>(scratch_d + offsets[l],
                                                              offsets_d + N,
                                                              nullptr,
                                                              scratch_d + offsets[l],
                                                              levels[l]);
      }
      else {
        scan<false, true, true><<<1, blockSize, 0, stream>>>(scratch_d + offsets[l],
                                                             offsets_d + N,
                                                             sum_d,
                                                             scratch_d + offsets[l],
                                                             levels[l]);
      }


    }


  }
}
